如何修改默认的 iOS OpenGL ES 2.0 模板以显示纹理?

发布于 2024-12-11 22:34:22 字数 182 浏览 0 评论 0原文

我正在尝试学习一些用于 iPhone 开发的基本 OpenGL ES,但我有一项无法完全完成的任务。

我似乎无法更改默认的 OpenGL ES 模板以在弹跳方块上显示纹理,而不是默认的彩虹效果。我正在尝试为这个正方形使用纹理,但到目前为止该正方形仅显示黑色。在这个简单的情况下我可能做错了什么,以及如何修改基本模板代码来显示我的纹理?

I am attempting to learn some basic OpenGL ES for iPhone development, and I have a task I can't quite get to work.

I cannot seem to change the default OpenGL ES template to display a texture on the bouncing square instead of the default rainbow-like effect. I'm trying to use a texture for this square, but so far the square just shows black. What could I be doing wrong in this simple case, and how could I modify the base template code to display my texture?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我喜欢麦丽素 2024-12-18 22:34:22

顺便说一句,默认的 OpenGL ES 模板似乎已针对 iOS 5.0 SDK 进行了更改,现在使用 GLKit 来绘制旋转立方体,因此我无法基于他们一直使用的原始彩虹方块创建一个简单的测试项目。

相反,您可能想查看我为我的项目准备的示例应用程序该主题的课程。这是一个相当精简的应用程序,可以在旋转立方体的面上显示纹理。我在 iTunes 上该课程的视频中详细描述了它的工作原理U。

此示例应用程序使用 Apple 的 PVRTexture 类(来自其其他示例应用程序之一)加载 PVRTC 压缩纹理文件(这比普通图像更节省内存)。设置纹理的核心代码如下:

glGenTextures(1, &_name);
glBindTexture(GL_TEXTURE_2D, _name);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

glCompressedTexImage2D(GL_TEXTURE_2D, i, _internalFormat, width, height, 0, [data length], [data bytes]);

其中 _name 是稍后将用于绑定该纹理的标识符。如果您使用普通的未压缩纹理,则可以使用 glTexImage2D() 而不是最后一个函数。

然后,您可以启用纹理的使用:

glEnable(GL_TEXTURE_2D);

并使用创建纹理时获得的标识符绑定要显示的纹理:

glBindTexture(GL_TEXTURE_2D, pvrTexture.name);

默认情况下,此纹理绑定到纹理单元 0,但您可以使用 glActiveTexture(GL_TEXTURE1) 等。

然后,您需要将此纹理作为统一传递到着色器程序,第二个参数是纹理绑定到的纹理单元:

glUniform1i(uniforms[UNIFORM_TEXTURE], 0);

您还需要顶点对应的纹理位置,以便将纹理映射到表面上正确的方法:

const GLfloat cubeTexCoords[] = {
    1.0, 0.0,
    0.0, 0.0,
    1.0, 1.0,
    0.0, 1.0,
    0.0, 0.0,
    1.0, 0.0,
    0.0, 1.0,
    1.0, 1.0,
    1.0, 1.0,
    0.0, 1.0,
    0.0, 0.0,
    1.0, 0.0,
    0.0, 1.0,
    1.0, 1.0,
};

这些坐标将作为属性输入到您的着色器程序中:

glVertexAttribPointer(ATTRIB_TEXTUREPOSITION, 2, GL_FLOAT, 0, 0, cubeTexCoords);
glEnableVertexAttribArray(ATTRIB_TEXTUREPOSITION);

您的着色器程序将需要能够接受纹理统一及其坐标,因此您将在顶点着色器中拥有如下所示的内容:

attribute vec4 position;
attribute vec4 inputTextureCoordinate;

varying vec2 textureCoordinate;

uniform mat4 modelViewProjMatrix;

void main()
{
    gl_Position = modelViewProjMatrix * position;
    textureCoordinate = inputTextureCoordinate.xy;
}

这是一个匹配的片段着色器:

varying highp vec2 textureCoordinate;

uniform sampler2D texture;

void main()
{
    gl_FragColor = texture2D(texture, textureCoordinate);
}

您可以看到着色器程序如何获取纹理坐标并将它们传递到片段着色器,在片段着色器中对纹理进行采样并用于在该片段上生成最终颜色。

编译此着色器时,您需要匹配属性和制服,但 OpenGL ES 2.0 模板应该显示如何做到这一点。

虽然我没有提供在 OpenGL ES 2.0 模板上启用纹理显示的确切代码,但您应该能够使用上面的代码作为执行此操作的基础。

As a side note, the default OpenGL ES template appears to have changed for the iOS 5.0 SDK, and now uses GLKit to draw rotating cubes, so I couldn't create a simple test project based on that original rainbow square that they had been using.

Instead, you might want to look at the sample application I prepared for my class on the subject. It's a fairly stripped-down application that displays textures on the faces of a rotating cube. I describe in detail how this works in the video for that class on iTunes U.

This sample application uses Apple's PVRTexture class (from one of their other sample applications) to load in a PVRTC-compressed texture file (which is more memory-efficient than normal images). The core code for setting up a texture is this:

glGenTextures(1, &_name);
glBindTexture(GL_TEXTURE_2D, _name);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

glCompressedTexImage2D(GL_TEXTURE_2D, i, _internalFormat, width, height, 0, [data length], [data bytes]);

where _name is the identifier that you'll later use to bind that texture. You'd use glTexImage2D() instead of the last function if you were working with a normal uncompressed texture.

You can then enable the use of textures:

glEnable(GL_TEXTURE_2D);

and bind the texture to be displayed, using the identifier you obtained when the texture was created:

glBindTexture(GL_TEXTURE_2D, pvrTexture.name);

By default, this texture is bound to texture unit 0, but you can switch to another unit using glActiveTexture(GL_TEXTURE1) or the like.

You then need to pass in this texture to your shader program as a uniform, with the second parameter being the texture unit that the texture is bound to:

glUniform1i(uniforms[UNIFORM_TEXTURE], 0);

You also need corresponding texture positions for your vertices so that your texture gets mapped onto your surface in the right way:

const GLfloat cubeTexCoords[] = {
    1.0, 0.0,
    0.0, 0.0,
    1.0, 1.0,
    0.0, 1.0,
    0.0, 0.0,
    1.0, 0.0,
    0.0, 1.0,
    1.0, 1.0,
    1.0, 1.0,
    0.0, 1.0,
    0.0, 0.0,
    1.0, 0.0,
    0.0, 1.0,
    1.0, 1.0,
};

and these coordinates will be fed into your shader program as an attribute:

glVertexAttribPointer(ATTRIB_TEXTUREPOSITION, 2, GL_FLOAT, 0, 0, cubeTexCoords);
glEnableVertexAttribArray(ATTRIB_TEXTUREPOSITION);

You shader program will need to be able to take in the texture uniform and its coordinates, so you'll have something that looks like this in your vertex shader:

attribute vec4 position;
attribute vec4 inputTextureCoordinate;

varying vec2 textureCoordinate;

uniform mat4 modelViewProjMatrix;

void main()
{
    gl_Position = modelViewProjMatrix * position;
    textureCoordinate = inputTextureCoordinate.xy;
}

and this for a matching fragment shader:

varying highp vec2 textureCoordinate;

uniform sampler2D texture;

void main()
{
    gl_FragColor = texture2D(texture, textureCoordinate);
}

You can see how the shader program takes in the texture coordinates and passes them along to the fragment shader, where the texture is sampled and used to produce the final color at that fragment.

You'll need to match attributes and uniforms when you compile this shader, but the OpenGL ES 2.0 template should show how to do that.

While I haven't provided the exact code to enable texture display on the OpenGL ES 2.0 template, you should be able to use the above as a basis to do this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文