Android 如何将图形调用和采样值的更改与单个着色器程序正确混合?

Android 如何将图形调用和采样值的更改与单个着色器程序正确混合?,android,opengl-es,opengl-es-2.0,Android,Opengl Es,Opengl Es 2.0,我试图在OpenGL ES 2.0 for Android中使用一个着色器程序,使用两种不同的纹理绘制两个对象。第一个对象应该具有texture0,第二个对象应该具有texture1 在片段着色器中,我有: uniform sampler2D tex; 在java代码中: int tiu0=0; int tiu1=1; int-texLoc=glGetUniformLocation(程序,“tex”); glUseProgram(程序); //将纹理0绑定到纹理图像单元0 玻璃结构(GL_纹理

我试图在OpenGL ES 2.0 for Android中使用一个着色器程序,使用两种不同的纹理绘制两个对象。第一个对象应该具有
texture0
,第二个对象应该具有
texture1

在片段着色器中,我有:

uniform sampler2D tex;
在java代码中:

int tiu0=0;
int tiu1=1;
int-texLoc=glGetUniformLocation(程序,“tex”);
glUseProgram(程序);
//将纹理0绑定到纹理图像单元0
玻璃结构(GL_纹理0+tiu0);
glBindTexture(GL_TEXTURE_2D,texture0);
//将纹理1绑定到纹理图像单元1
玻璃结构(GL_纹理0+tiu1);
glBindTexture(GL_TEXTURE_2D,texture1);
glUniform1i(texLoc,tiu0);
//成功:glGetError返回GL_NO_错误,glGetUniformiv为texLoc返回0
drawFirstObject();//应该有纹理0
glUniform1i(texLoc,tiu1);
//成功:glGetError返回GL_NO_ERROR,glGetUniformiv为texLoc返回1
drawSecondObject();//应该有纹理1
在三星Galaxy Ace和Android 2.3.3上运行,两个对象具有相同的
texture0
。类似的代码在我的桌面计算机上的OpenGL 2.0中正确运行

如果删除
drawFirstObject
,则第二个对象将具有
texture1

如果删除
drawSecondObject
,第一个对象将具有
texture0

如果在
drawFirstObject
drawSecondObject
之间的某个位置,我会更改程序一段时间:

glUseProgram(0);//也可以是除下一次调用的程序之外的任何有效程序
glUseProgram(程序);
然后两个对象都将具有
纹理1

始终正确设置与
sampler2D
不同的制服值

我知道我可以只使用一个纹理图像单元绘制具有不同纹理的两个对象,并在绘制对象之前将适当的纹理绑定到该纹理图像单元,但我也想知道这里发生了什么


我的代码有问题吗?在OpenGL ES 2.0中,是否可以仅通过在纹理图像单元之间切换来绘制具有不同纹理的对象,如我在代码中所示?如果这是不可能的,那么OpenGL2.0(如果可能的话)和OpenGLES2.0之间的差异是否在任何地方都有记录?我找不到它。

经过数小时的进一步研究,我发现这个问题是我的三星Galaxy Ace(GT-S5830)中使用的Adreno 200 GPU特有的。似乎在第一次调用绘图函数时,Adreno 200驱动程序会将纹理指定给采样器,之后它会忽略采样器值的任何更改(
glUniform1i(采样器位置,textureImageUnit)
),直到出现以下两种情况之一:

  • glUseProgram
    使用不同的着色器程序调用
  • 不同的纹理绑定到着色器程序使用的任何纹理图像单元
在Adreno 200 GPU制造商的论坛上有一篇文章描述了同样的问题

因此,如果使用相同的着色器程序多次调用绘图函数,并且之前绑定了不同的纹理,则有两种解决方法:

  • 调用
    glUseProgram(0);glUseProgram(您的绘图程序)在每个绘图功能之前

  • 在每次图形调用之前,将不同的纹理绑定到着色器程序使用的至少一个纹理图像单元。此解决方案可能很难维护,因为如果绑定的纹理与已绑定到纹理图像单元的纹理相同,则问题仍然存在。因此,在这种情况下,最简单的解决方案是,在每次图形调用之前,不要更改采样器值并绑定着色器程序使用的所有纹理图像单元的纹理


  • 我不认为您的代码在概念上有任何问题,而且您似乎有正确的想法。你在检查代码中的错误吗?是的。在这个程序中,glGetError在每次调用任何OpenGL函数后都返回GL_NO_ERROR。将一个纹理单元(比如0)重新绑定到不同的纹理是否有效?是的,重新绑定有效。问题出在GPU驱动程序上,我发布了答案。谢谢你,我自己也不知道如何缩小问题的范围。