如何使用OpenGL ES 2.0显示多个单独的纹理(不是多纹理)?

时间:2012-09-18 07:56:06

标签: ios4 opengl-es-2.0 textures

我的iOS 4应用程序使用OpenGL ES 2.0并使用单个纹理渲染元素。我想使用多种不同的纹理绘制元素,并且在开始工作时遇到了问题。

我在顶点着色器中添加了一个变量来指示要应用的纹理:

...
attribute float TextureIn;
varying float TextureOut;

void main(void)
{ 
    ...
    TextureOut = TextureIn;
}

我在片段着色器中使用该值来选择纹理:

...
varying lowp float TextureOut;

uniform sampler2D Texture0;
uniform sampler2D Texture1;

void main(void)
{   
    if (TextureOut == 1.0) 
    {
        gl_FragColor = texture2D(Texture1, TexCoordOut);
    }
    else // 0
    {
        gl_FragColor = texture2D(Texture0, TexCoordOut);
    }
}

编译着色器:

...
_texture = glGetAttribLocation(programHandle, "TextureIn");
glEnableVertexAttribArray(_texture);
_textureUniform0 = glGetUniformLocation(programHandle, "Texture0");
_textureUniform1 = glGetUniformLocation(programHandle, "Texture1");

初​​始化/设置:

...
GLuint _texture;
GLuint _textureUniform0;
GLuint _textureUniform1;

...
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D); // ?
glBindTexture(GL_TEXTURE_2D, _textureUniform0);
glUniform1i(_textureUniform0, 0);

glActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D); // ?
glBindTexture(GL_TEXTURE_2D, _textureUniform1);
glUniform1i(_textureUniform1, 1);

glActiveTexture(GL_TEXTURE0);

渲染:

...
glVertexAttribPointer(_texture, 1, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * 13));    

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, _textureUniform0);
glUniform1i(_textureUniform0, 0);

glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, _textureUniform1);
glUniform1i(_textureUniform1, 1);

glActiveTexture(GL_TEXTURE0);

glDrawElements(GL_TRIANGLES, indicesCountA, GL_UNSIGNED_SHORT, (GLvoid*) (sizeof(GLushort) * 0));
glDrawElements(GL_TRIANGLES, indicesCountB, GL_UNSIGNED_SHORT, (GLvoid*) (sizeof(GLushort) * indicesCountA));
glDrawElements(GL_TRIANGLES, indicesCountC, GL_UNSIGNED_SHORT, (GLvoid*) (sizeof(GLushort) * (indicesCountA + indicesCountB)));

我希望动态应用与顶点关联的纹理,但它似乎只能识别GL_TEXTURE0。

我能够改变纹理的唯一方法是将每个纹理与GL_TEXTURE0相关联,然后绘制:

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, _textureUniformX);
glUniform1i(_textureUniformX, 0);
glDrawElements(GL_TRIANGLES, indicesCountA, GL_UNSIGNED_SHORT, (GLvoid*) (sizeof(GLushort) * 0));
...

为了渲染所有纹理,我需要为每个纹理单独调用glDrawElements(),并且我已经读过glDrawElements()调用对性能的影响很大,并且应该最小化调用次数。这就是为什么我试图动态指定每个顶点使用哪个纹理。

完全有可能我的理解是错误的,或者我错过了一些重要的事情。我还是OpenGL的新手,我学到的越多,我觉得我还有更多需要学习的东西。

必须可以使用除GL_TEXTURE0以外的纹理,但我还没有弄清楚如何。

非常感谢任何指导或指示。

1 个答案:

答案 0 :(得分:2)

您是否只是遇到浮点舍入问题?应该没有(除非单个privimitve共享具有不同纹理的顶点),但只是为了确保用TextureOut == 1.0或类似的东西替换此TextureOut > 0.5

作为一般建议,你是正确的,因为绘制调用的数量应尽可能减少,但你的方法很奇怪。您正在使用片段着色器分支购买绘制调用减少。您的方法也不能很好地适应纹理的总体数量,因为您总是需要在单独的纹理单元中使用所有纹理。

减少纹理切换的常用方法是将所有纹理放入单个大纹理(即所谓的纹理图集)中,并使用纹理坐标在此纹理中选择适当的子区域。这也有一些陷阱(这是一个完全不同的问题),但没有任何东西是免费的。

编辑:哦等等,我看到你实际上做错了什么

glBindTexture(GL_TEXTURE_2D, _textureUniform0);

你将纹理绑定到当前纹理单元,但是你给这个函数一个统一的位置而不是纹理对象,这是完全垃圾(但是甚至可能在一些奇怪的情况下工作,因为统一的位置和纹理对象本身就是整数)。当然你必须绑定实际的纹理。