让我们剖析一下你在做什么,包括一些不必要的东西,以及 GL 做了什么。
首先,您在代码中所做的 C 风格转换都不是必需的。只需使用GL_TEXTURE_2D 等等而不是GLenum(GL_TEXTURE_2D)。
glActiveTexture(GL_TEXTURE0 + i),其中i 在[0, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1] 范围内,选择当前活动的纹理单元。只要您不使用另一个有效的单元标识符调用glActiveTexture,更改纹理单元状态的命令就会影响单元i。
一旦您使用当前活动纹理单元i 调用glBindTexture(target, name),当使用适当的采样器在着色器(即name 可能绑定到TEXTURE_2D 并且相应的样本必须是sampler2D)。您只能将一个纹理对象绑定到当前活动纹理单元的特定目标 - 因此,如果您需要在着色器中对两个 2D 纹理进行采样,则需要使用两个纹理单元。
从上面可以看出glUniform1i(samplerLocation, i)做了什么。
因此,如果您有两个 2D 纹理需要在着色器中进行采样,则需要两个纹理单元和两个采样器,每个都引用一个特定的单元:
GLuint regularTextureName = 0;
GLunit videoTextureName = 0;
GLint regularTextureSamplerLocation = ...;
GLint videoTextureSamplerLocation = ...;
GLenum regularTextureUnit = 0;
GLenum videoTextureUnit = 1;
// setup texture objects and shaders ...
// make successfully linked shader program current and query
// locations, or better yet, assign locations explicitly in
// the shader (see below) ...
glActiveTexture(GL_TEXTURE0 + regularTextureUnit);
glBindTexture(GL_TEXTURE_2D, regularTextureName);
glUniform(regularTextureSamplerLocation, regularTextureUnit);
glActiveTexture(GL_TEXTURE0 + videoTextureUnit);
glBindTexture(GL_TEXTURE_2D, videoTextureName);
glUniform(videoTextureSampleLocation, videoTextureUnit);
您的片段着色器(我假设您将在其中进行采样)必须具有相应的采样器:
layout(binding = 0) uniform sampler2D regularTextureSampler;
layout(binding = 1) uniform sampler2D videoTextureSampler;
就是这样。如果绑定到上述单元的两个纹理对象都设置正确,那么纹理的内容是否在每个片段着色器调用之前动态变化都没有关系 - 有很多场景是常见的地方,例如延迟渲染或任何其他渲染到纹理算法,因此您不会在某些视频纹理方面开辟新天地。
关于您需要多久执行一次的问题:您需要在需要时执行此操作 - 不要更改不需要更改的状态。如果您从不更改相应纹理单元的绑定,则根本不需要重新绑定纹理。正确设置它们一次,然后不要管它们。
采样器绑定也是如此:如果您不使用着色器对其他纹理对象进行采样,则根本不需要更改着色器程序状态。设置一次,不用管它。
简而言之:如果没有必要,不要更改状态。
编辑:我不太确定是否是这种情况,但如果您使用相同的着色器和一个采样器分别用于 两个 纹理着色器调用,你必须改变一些东西,但你猜怎么着,就像让采样器引用另一个纹理单元一样简单:
// same texture unit setup as before
// shader program is current
while (rendering)
{
glUniform(samplerLocation, regularTextureUnit);
// draw call sampling the regular texture
glUniform(samplerLocation, videoTextureUnit);
// draw call sampling teh video texture
}