C++ “你怎么看?”;“免费”;纹理单位?

C++ “你怎么看?”;“免费”;纹理单位?,c++,opengl,textures,C++,Opengl,Textures,为了使用纹理单元,我们通常将其绑定到当前进程,大致如下所示: glUseProgram(program); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, textureID); GLint loc = glGetUniformLocation(program, "uniform"); //error check glUniform1i(loc,0); 如何“释放”纹理单元。换句话说,如何从当前程序中的纹理单元绑定点分离

为了使用纹理单元,我们通常将其绑定到当前进程,大致如下所示:

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

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

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

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


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

见:

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

绑定是通过调用

void BindTexture( enum target, uint texture );
将目标设置为所需的纹理目标,并将纹理设置为未使用的名称

这意味着

GLuint defaultTextureObjectID = 0;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, defaultTextureObjectID);
将默认纹理对象绑定到纹理单元0


由于OpenGL 4.5,因此可以使用它

命令

void BindTextureUnit( uint unit, uint texture );
将现有纹理对象绑定到编号为
单元的纹理单元
<代码>纹理必须为零或现有纹理对象的名称。当
texture
是现有纹理对象的名称时,该对象将绑定到创建对象时指定的相应纹理单元中的目标

因此,您也可以使用以下选项:

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

从严格意义上说。。。你不能。您可以绑定纹理对象0,但它被认为是有效的纹理对象(尽管它的行为非常奇怪)。您可以使用非DSA函数来填充数据,并像使用常规纹理一样使用它(大部分)

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

尽管如此,请允许我给出一个不同寻常的观点:你不必从上下文中解开纹理

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

因此,解除纹理绑定并不是真正的目的。事实上,它可以有某些优势

如果不小心使用了绑定为0的纹理单元(概念上未绑定),则可能会出现OpenGL错误。但你可能不会。如果没有,则会得到包含白色像素的纹理。这可能对代码来说是错误的,也可能不是

相比之下,如果您不小心使用了一个绑定了旧数据的纹理单元,您要么会得到一个OpenGL错误,要么肯定会得到一些明显错误的东西


因此,如果您将纹理保留在那里,如果您不小心没有绑定某个对象,则更有可能看到问题。

为什么您的示例使用
textureId
而不是将
0
传递给绑定调用?
textureId
没有这样的含义。更具描述性的名称,如
defaultTextureObjectID
,将更好地实现这一目的。