你如何"免费"纹理单位?

时间:2018-05-01 07:58:02

标签: c++ opengl textures

为了使用纹理单元,我们通常或多或少地将它绑定到当前进程:

glUseProgram(program);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureID);

GLint loc = glGetUniformLocation(program, "uniform");
//error check

glUniform1i(loc,0);

你如何"免费"纹理单位。换句话说,如何从当前程序中的纹理单元绑定点分离纹理?

2 个答案:

答案 0 :(得分:5)

  

如何“释放”纹理单元。换句话说,如何从当前程序中的纹理单元绑定点分离纹理?


您不能“释放”纹理单元,但可以将默认纹理对象绑定到纹理单元。

  

请参阅OpenGL 4.6 API Compatibility Profile Specification; 8.1 Texture Objects; page 178

     

GL中的纹理由命名对象表示。纹理对象的名称空间是无符号整数,GL保留零以表示默认纹理对象

     

...

     

通过调用

实现绑定
void BindTexture( enum target, uint texture );
     

将目标设置为所需的纹理目标,并将纹理设置为未使用的名称。

这意味着

GLuint defaultTextureObjectID = 0;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, defaultTextureObjectID);

将默认纹理对象绑定到纹理单元0。


从OpenGL 4.5开始,可以使用glBindTextureUnit

  

命令

void BindTextureUnit( uint unit, uint texture );
     

将现有纹理对象绑定到编号为unit纹理单元。 texture 必须为零或现有纹理对象的名称。当texture是现有纹理对象的名称时,该对象将绑定到在创建对象时指定的相应纹理单元中的目标。

所以你也可以使用以下内容:

glBindTextureUnit( 0, 0 ); // texture unit 0, default texture object (0)

答案 1 :(得分:3)

严格意义上说......你做不到。您可以绑定纹理对象0,但这被认为是一个有效的纹理对象(尽管具有明显奇怪的行为)。您可以使用非DSA函数将其填充数据并使用它(大多数情况下)像常规纹理一样。

现在是的,大多数现代OpenGL用户从不使用纹理对象0.他们将其保留为默认状态,并且将它绑定为不使用纹理单元。实际上,将0传递给glBindTextureUnit会导致该纹理单元的所有纹理目标都绑定到它们(而使用常规对象仅将该对象的目标绑定到该单位,而使单元内的其他目标不受干扰)。

所有这一切,允许我对此提出一个不同寻常的观点:你不必取消解除上下文中的纹理。

如果一个程序没有使用纹理单元,那么某个东西绑定到该单元的事实就无关紧要了。绑定到纹理单元的纹理不会阻止您使用其他纹理单元;只有程序使用的(与正确的纹理类型匹配)实际上才重要。删除纹理将导致它们自动从上下文中解除绑定(但仅限于当前上下文;如果您有多个上下文,它们仍将被绑定在那里)。

因此它实际上并没有解开纹理的目的。实际上,它可以有一定的优势。

如果您不小心使用了0绑定的纹理单元(概念上未绑定),则可能会出现OpenGL错误。但你可能不会。如果不这样做,那么您将获得包含白色像素的纹理。这可能会或可能不会对您的代码造成严重错误。

相比之下,如果您不小心使用了绑定了旧数据的纹理单元,您将遇到OpenGL错误,或者肯定会获得明显错误的内容。

因此,如果您将纹理留在那里,如果您不小心不绑定某些内容,则更有可能看到问题。