我注意到有些人选择将默认纹理绑定到他们在每个渲染循环中使用的每个纹理单元。这是常见/最佳做法吗?
伪示例:
Tick() {
glUseProgram(someProgram);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, imgTexture1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, imgTexture2);
.
.
.
//Is the following really necessary: ???
glUseProgram(0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, 0);
}
如果此处不需要,那么在资源发布之前是否应该进行此类调用?
答案 0 :(得分:2)
删除对象不需要这样做。删除对象时,它会自动从每个绑定点解除绑定。这仅适用于发出glDelete*
命令的上下文;共享对该对象的访问权限的其他上下文不会将其解除绑定。如果对象附加到另一个对象(例如附加到帧缓冲区的纹理),那么它也不会被附加。
自己清理后并不是一个坏主意,主要是为了避免错误。如果着色器试图访问一个绑定了它的纹理单元,它可能会工作"从而隐藏错误。然而,如果它试图访问一个没有任何约束力的单位,那么它很可能明显失败。
当然,这主要用于调试,因此您可以#ifdef
围绕此类代码在发布版本中删除它。
但是,上面假设您在使用它完成渲染后基本上解除了纹理的绑定。我提出这个问题是因为您显示的代码与每个纹理单元解除绑定不正确。为什么呢?
因为每个纹理单元都有多个绑定点,每个纹理的类型一个。因此,如果将纹理绑定到GL_TEXTURE_CUBE_MAP
,则调用glBindTexture(GL_TEXTURE2D, 0)
不会对绑定到立方体贴图目标的纹理执行任何操作。
因此,如果您要编写解除每个纹理单元纹理的代码,则必须使用every texture target that exists调用glBindTexture
:
void UnbindFromTextureUnit(int unit)
{
static const GLenum allTargets[] = {/*Every texture target that exists*/};
glActiveTexture(GL_TEXTURE0 + unit);
for(auto target : allTargets)
glBindTexture(target, 0);
}
或者您可以使用multibind glBindTextures
from GL 4.4。或直接状态访问4.5 glBindTextureUnit()
。