我的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以外的纹理,但我还没有弄清楚如何。
非常感谢任何指导或指示。
答案 0 :(得分:2)
您是否只是遇到浮点舍入问题?应该没有(除非单个privimitve共享具有不同纹理的顶点),但只是为了确保用TextureOut == 1.0
或类似的东西替换此TextureOut > 0.5
。
作为一般建议,你是正确的,因为绘制调用的数量应尽可能减少,但你的方法很奇怪。您正在使用片段着色器分支购买绘制调用减少。您的方法也不能很好地适应纹理的总体数量,因为您总是需要在单独的纹理单元中使用所有纹理。
减少纹理切换的常用方法是将所有纹理放入单个大纹理(即所谓的纹理图集)中,并使用纹理坐标在此纹理中选择适当的子区域。这也有一些陷阱(这是一个完全不同的问题),但没有任何东西是免费的。
编辑:哦等等,我看到你实际上做错了什么
glBindTexture(GL_TEXTURE_2D, _textureUniform0);
你将纹理绑定到当前纹理单元,但是你给这个函数一个统一的位置而不是纹理对象,这是完全垃圾(但是甚至可能在一些奇怪的情况下工作,因为统一的位置和纹理对象本身就是整数)。当然你必须绑定实际的纹理。