我正在尝试了解OpenGL 4.5中的纹理,纹理单元和采样器。我附上了一张我想弄清楚的图片。我认为在我的例子中一切都是正确的,但我对右侧带有问号的1D采样器不太确定。
所以,我知道OpenGL提供了许多纹理单元/绑定点,纹理和采样器可以绑定在一起,因此它们可以协同工作。
这些绑定点中的每一个都可以支持每个纹理目标中的一个(在我的情况下,我将绑定目标GL_TEXTURE_2D
和GL_TEXTURE_1D
绑定到绑定点0
,另一个{{1绑定点GL_TEXTURE_2D
)。
此外,采样器可以以相同的方式绑定到这些绑定点(我已将2D采样器绑定到pic中的绑定点1
。
执行这些操作的功能包括0
和glBindTextureUnit
。
我最初的想法是将1D采样器绑定到绑定点0,并且在着色器中根据绑定点和采样器的类型进行匹配:
glBindSampler
引用来源:
每个纹理图像单元都支持绑定到所有目标。 所以2D 纹理和数组纹理可以绑定到同一个图像单元,或 不同的2D纹理可以绑定在两个不同的图像单元中 互不影响。那么当使用哪种纹理时 渲染?在GLSL中,这取决于使用它的采样器的类型 纹理图像单元。
但我发现了以下声明:
[..]听起来很可疑,就像你可以使用相同的纹理图像单元 对于不同的采样器,只要它们具有不同的纹理类型。 不要这样做。该规范明确禁止它;如果两个不同 GLSL采样器具有不同的纹理类型,但与之相关 相同的纹理图像单元,然后渲染将失败。 给每个人 采样器不同的纹理图像单元。
所以,我的问题是,如果最终单个采样器将被绑定到该绑定点,那么将不同纹理目标绑定到同一个绑定点的目的是什么,迫使你选择?
我引用的信息:https://www.khronos.org/opengl/wiki/Texture#Texture_image_units
答案 0 :(得分:8)
那为什么会这样呢?嗯......
曾几何时,没有纹理单位(这就是为什么glActiveTexture
是与glBindTexture
分开的函数)。实际上,OpenGL 1.0中甚至没有纹理对象。但仍然需要不同种类的纹理。您仍然需要能够为2D纹理和3D纹理创建数据。因此,他们提出了纹理目标的区别,他们使用glEnable
来确定在渲染操作中使用哪个目标。
当纹理对象在GL 1.1中出现时,他们必须决定纹理对象和目标之间的关系。他们决定,一旦一个物体被绑定到一个目标,它就会永久地与该目标相关联。由于上述需要具有不同类型的多个纹理,使用旧的启用功能,因此决定每个目标表示单独的对象绑定点。并且他们让你重复了glBindTexture
中的绑定点,这样读者就可以清楚地了解哪些绑定点的数据令人不安。
切割到OpenGL 1.2,当多纹理出现时。所以现在他们需要你能够绑定同一目标的多个纹理,但需要绑定到不同的“单位”。但他们无法改变glBindTexture
来指定一个特定的单位;这将是一个向后不兼容的变化。
现在,他们可以彻底改变纹理的工作方式,创建一个专门用于多纹理等的新绑定功能。但是OpenGL ARB喜欢向后兼容;他们喜欢使旧的API函数工作,无论生成的API是什么样的。因此,他们决定纹理单元将是整个绑定的集,每个集都有一个启用状态,说明哪个目标是要使用的目标。并使用glActiveTexture
在单位之间切换。
当然,一旦着色器问世,你就可以看到这一切都发生了变化。启用状态成为着色器中的采样器类型。所以现在没有明确的代码描述启用了哪个纹理目标;它只是着色器的东西。因此,他们必须制定一条规则,即如果两个采样器的类型不同,则不能使用相同的单元。
这就是为什么每个纹理单元都有多个独立的绑定点:OpenGL对向后兼容性的承诺。
最好忽略此功能存在。绑定特定着色器所需的正确纹理。因此,请专注于使用这些功能,并且不要担心可能有两个纹理绑定到同一目标。如果你想确定你没有意外使用错误的纹理,可以使用纹理名称为0的glBindTextures
或glBindTextureUnit
,这将解除特定纹理单元中的所有目标(s) )。
答案 1 :(得分:-2)
假设你有两个GLSL程序:
在progA中:
uniform sampler1D progA_sampler1D;
uniform sampler2D progA_sampler2D;
在progB中:
uniform sampler1D progB_sampler1D;
uniform sampler2D progB_sampler2D;
你有几个纹理,名称为text1D_1,text1D_2,text1D_3,... text2D_1,text2D_2等
现在让我们假设您希望progA从text1D_1和text2D_1以及progB到text1D_2和text2D_2的样本进行采样
您已经知道每个采样器必须与纹理单元相关联,而不是与纹理名称相关联。
我们不能对采样器progA_sampler1D
和progA_sampler2D
使用相同的纹理单元
第一个选项:四个纹理单元
glUseProgram(progA);
glActiveTexture(GL_TEXTURE0 + 1);
glBindTexture(GL_TEXTURE_1D, text1D_1);
glUniform1i(locationProgA_forSampler1D, 1); // Not glUniform1i(locationProgA_forSampler1D, GL_TEXTURE0 + 1);
glActiveTexture(GL_TEXTURE0 + 2);
glBindTexture(GL_TEXTURE_2D, text2D_1);
glUniform1i(locationProgA_forSampler2D, 2);
glUseProgram(progB);
glActiveTexture(GL_TEXTURE0 + 3);
glBindTexture(GL_TEXTURE_1D, text1D_2);
glUniform1i(locationProgA_forSampler1D, 3);
glActiveTexture(GL_TEXTURE0 + 4);
glBindTexture(GL_TEXTURE_2D, text2D_2);
glUniform1i(locationProgA_forSampler2D, 4);
第二个选项:两个纹理单元
glUseProgram(progA);
glActiveTexture(GL_TEXTURE0 + 1);
glBindTexture(GL_TEXTURE_1D, text1D_1);
glUniform1i(locationProgA_forSampler1D, 1);
glActiveTexture(GL_TEXTURE0 + 2);
glBindTexture(GL_TEXTURE_2D, text2D_1);
glUniform1i(locationProgA_forSampler2D, 2);
glUseProgram(progB);
glActiveTexture(GL_TEXTURE0 + 2);
glBindTexture(GL_TEXTURE_1D, text1D_2);
glUniform1i(locationProgA_forSampler1D, 2);
glActiveTexture(GL_TEXTURE0 + 1);
glBindTexture(GL_TEXTURE_2D, text2D_2);
glUniform1i(locationProgA_forSampler2D, 1);
请注意,单位GL_TEXTURE0 + 1
已将两个纹理text1D_1和text2D_2绑定为不同的类型。
同样地,GL_TEXTURE0 + 2
绑定了两个纹理,类型为GL_TEXTURE_2D
和GL_TEXTURE_1D
错误的选项:两个纹理单元
glUseProgram(progA);
glActiveTexture(GL_TEXTURE0 + 1);
glBindTexture(GL_TEXTURE_1D, text1D_1);
glUniform1i(locationProgA_forSampler1D, 1);
glActiveTexture(GL_TEXTURE0 + 2);
glBindTexture(GL_TEXTURE_2D, text2D_1);
glUniform1i(locationProgA_forSampler2D, 2);
glUseProgram(progB);
glActiveTexture(GL_TEXTURE0 + 1);
//Next is wrong: two textures (text1D_1 and text1D_2) of same type GL_TEXTURE_1D
glBindTexture(GL_TEXTURE_1D, text1D_2);
glUniform1i(locationProgA_forSampler1D, 1);
glActiveTexture(GL_TEXTURE0 + 2);
glBindTexture(GL_TEXTURE_2D, text2D_2); //Wrong: two textures of same type GL_TEXTURE_2D
glUniform1i(locationProgA_forSampler2D, 2);