Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/.htaccess/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android glUseProgram之间的OpenGL纹理绑定_Android_Opengl Es - Fatal编程技术网

Android glUseProgram之间的OpenGL纹理绑定

Android glUseProgram之间的OpenGL纹理绑定,android,opengl-es,Android,Opengl Es,我正在Android上用OpenGLES2.0实现一个引擎。我有多个着色器,对象可以使用多个纹理 我的目标是最小化对OpenGL的纹理绑定调用,因此我为每个着色器保留一个当前绑定纹理的列表,并且仅在纹理更改时调用glBindTexture() 例如,我有一个skybox着色器,并且我只使用它绘制单个对象(skybox立方体),那么该着色器在其生命周期中只需要一个纹理绑定 当我用相同的纹理绘制多个对象时,也会有收益 我的症状是,如果在绘制skybox纹理之前不重新绑定它,则会在skybox上使用不

我正在Android上用OpenGLES2.0实现一个引擎。我有多个着色器,对象可以使用多个纹理

我的目标是最小化对OpenGL的纹理绑定调用,因此我为每个着色器保留一个当前绑定纹理的列表,并且仅在纹理更改时调用
glBindTexture()

例如,我有一个skybox着色器,并且我只使用它绘制单个对象(skybox立方体),那么该着色器在其生命周期中只需要一个纹理绑定

当我用相同的纹理绘制多个对象时,也会有收益

我的症状是,如果在绘制skybox纹理之前不重新绑定它,则会在skybox上使用不同(以前绘制的)对象的纹理。此先前绘制的对象使用不同的着色器

所以,当我再次使用着色器程序时,假设纹理绑定被恢复是错误的吗


注:我对skybox使用单个2d纹理,而不是立方体贴图。

是的,假设在使用给定着色器程序时恢复纹理绑定是错误的

纹理绑定状态完全独立于当前着色器程序。每个纹理单元和目标都有一个当前绑定的纹理。假设您执行以下代码序列:

glActiveTexture(GL_TEXTURE7);
glBindTexture(GL_TEXTURE_2D, myTexId);
您正在将id为
myTexId
的纹理绑定到纹理单元7的2D目标。此状态将一直保持,直到您将不同的纹理绑定到单元7的2D目标(或删除纹理),完全独立于哪个着色器程序处于活动状态

通过将程序的采样器均匀变量的值设置为纹理单位,可以建立纹理和着色器程序之间的关系。继续上面的示例,指定给定程序应通过以下方式使用此纹理:

// needed only once after linking the program
GLint texLoc = glGetUniformLocation(myProgId, "MySampler");

// use the texture bound to unit 7
glUseProgram(myProgId);
glUniform1i(texLoc, 7);
基于此,如果希望避免对纹理绑定进行冗余调用,则必须跟踪哪个纹理绑定到哪个单元。该信息需要“全局”维护,即独立于特定着色器程序

请注意,统一值是每个程序的,因此绑定特定程序后不必再次设置该值,除非您希望它从绑定到不同单元的纹理采样

为了减少绑定不同纹理所需的次数,可以做的一件事是为每个着色器使用不同的纹理单元。作为一个简化的示例,请描述这样一种情况:每个程序使用一个纹理,并且每次使用该程序时都使用相同的纹理。然后可以为每个程序的采样器均匀设置不同的值,并将每个程序使用的纹理绑定到相应的纹理单元。然后,无论何时调用
glUseProgram()
,每个程序都将使用相应的纹理,而不调用
glBindTexture()

当然,当程序使用多个纹理时,这会变得更加复杂,并且您确实希望切换特定程序的纹理。但是,如果您以一种巧妙的方式管理纹理单元,您可能仍然能够大大减少纹理绑定操作的数量。执行此操作时,请记住纹理单元的数量是有限的。可通过以下方式查询限额:

glGetIntegerv(MAX_TEXTURE_IMAGE_UNITS, ...);
ES 2.0的限值可低至8

或者,从不同的角度看同一件事:如果使用的纹理少于可用纹理单元的数量,则可以将每个纹理绑定到不同的纹理单元一次,然后使用纹理绑定完成。然后,通过将每个着色器的采样器统一设置为绑定了所需纹理的纹理单元,可以控制每个着色器在任何给定时间使用的纹理

实际上,如果你的应用程序有点复杂,你很可能会混合使用这些方法。例如,可能会将一些常用纹理不断绑定到固定的纹理单元,而在必要时重新绑定其他纹理

由于这听起来可能比实际情况更复杂,让我总结一下这些关系:

  • 每个程序都有自己的一组统一值
  • 当特定程序处于活动状态时调用的
    glUniform1i()
    ,在着色器程序纹理单元之间建立关系
  • glBindTexture()
    纹理单元纹理对象之间建立关系

因此,纹理单元在程序和纹理对象之间提供了一定程度的间接性,这解释了为什么纹理绑定状态不是特定程序的直接部分。

非常感谢您的出色回答!我对装订感到困惑。