OpenGL中纹理单元和采样器统一变量之间的对应关系

4
glActiveTexture显然不能查询采样器统一和纹理单元之间的对应关系,我找不到很好的文档来查找哪个纹理单元映射到哪个采样器统一。这是我能够找到的信息:
  • 如果程序中只有一个采样器统一,则它被映射到gl_TEXTURE0
  • 如果单个程序阶段中有多个采样器统一,则它们按照在着色器中声明的顺序进行映射。
  • 如果顶点着色器和片段着色器具有不相交的采样器统一集,则顶点着色器中的采样器首先出现,然后是片段着色器中的采样器。
  • 此行为似乎由规范定义。

例如,如果顶点着色器定义如下:

uniform sampler2D color;

而片元着色器定义了:

uniform sampler2D tex;
uniform sampler2D norm;

然后color被映射到gl_TEXTURE0tex被映射到gl_TEXTURE1norm被映射到gl_TEXTURE2。但是,如果顶点着色器定义如下:

uniform sampler2D norm;

那么不清楚如何映射不同的纹理。这也会受到布局限定符或独立着色器阶段的影响,这使得问题更加复杂。

我似乎无法在任何地方找到相关文档。我所知道的一切都来源于我的实验或者Stackoverflow或OpenGL论坛上的回答。有人知道在所有可能情况下如何工作的全面规则集,或者知道查询sampler与哪个纹理单元相对应的方法吗?

2个回答

8
以下是我找到的信息:
  • 如果程序中只有一个采样器统一变量,则将其映射到gl_TEXTURE0
  • 如果单个程序阶段中有多个采样器统一变量,则它们按照它们在着色器中声明的顺序进行映射。
  • 如果顶点和片段着色器具有不相交的采样器统一变量集,则顶点着色器中的采样器首先出现,然后是片段着色器中的采样器。
  • 该行为似乎是由规范定义的。

这些都不是真的。好吧,第一个是真的,但只是偶然。

在着色器中未初始化的所有统一值都会初始化为值0。规范非常清楚地说明了这一点:

任何未带有绑定限定符的统一采样器或图像变量最初都被绑定到单元零。

采样器统一变量的值是它所表示的纹理单元的整数索引。因此,值0对应于GL_TEXTURE0。所有未初始化的采样器统一变量应该具有值0。

如果发生您所描述的行为,则该实现违反了OpenGL规范。

除非使用layout(binding=)语法将统一变量的纹理单元分配给它,否则必须在OpenGL代码中手动为每个采样器统一变量分配纹理单元值。这是通过设置其统一值来完成的,就像任何其他整数统一变量一样:您调用具有对应于该统一变量的位置的glUniform1i。因此,如果要将其与纹理图像单元索引4关联,则调用glUniform1i(...,4),其中...是该统一变量的统一位置。


4
你需要将纹理单元的索引设置为采样器统一变量(类似于设置类型为int的统一变量的值)。例如,GL_TEXTURE1的值为1。
参见OpenGL 4.6 API Compatibility Profile Specification; 7.10 Samplers; page 154

采样器是OpenGL着色语言中用于标识每个纹理查找使用的特殊统一变量。采样器的值表示正在访问的纹理图像单元。将采样器的值设置为i会选择纹理图像单元号码i

例如:
layout (location = 11) uniform sampler2D color;
layout (location = 12) uniform sampler2D tex;
layout (location = 13) uniform sampler2D norm;

glUniform1i(11, 0); // 0: GL_TEXTURE0
glUniform1i(12, 1); // 1: GL_TEXTURE1
glUniform1i(13, 2); // 2: GL_TEXTURE2

自GLSL 4.2版本起,可以通过在片段着色器中指定绑定点来实现 - 详见OpenGL Shading Language 4.20规范-4.4.4不透明统一布局限定符;第60页

#version 420

layout (binding = 0) uniform sampler2D color;
layout (binding = 1) uniform sampler2D tex;
layout (binding = 2) uniform sampler2D norm;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接