opengl中纹理单元和采样器制服之间的对应关系

时间:2019-02-28 18:20:54

标签: opengl glsl

glActiveTexture使用的采样器制服和纹理单元之间的对应关系显然无法通过opengl进行查询,而且我找不到如何找到映射到哪个采样器制服的纹理单元的良好文档。这是我能够找到的:

  • 如果程序中只有统一的采样器,则将其映射到gl_TEXTURE0
  • 如果在一个程序阶段中有多个采样器制服,则将按照在着色器中声明的顺序对其进行映射。
  • 如果顶点着色器和片段着色器的采样器制服集不相交,则顶点着色器中的采样器排在最前面,然后是片段着色器中的采样器。
  • 此行为似乎是由规范定义的。

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

uniform sampler2D color;

片段着色器定义:

uniform sampler2D tex;
uniform sampler2D norm;

然后,color被映射到gl_TEXTURE0tex被映射到gl_TEXTURE1,并且norm被映射到gl_TEXTURE2。但是,如果顶点着色器定义为:

uniform sampler2D norm;

然后不清楚如何映射不同的纹理。由于可能存在布局限定符或单独的着色器阶段,因此使情况更加复杂。

我似乎找不到任何关于此的文档。我所知道的一切都来自我自己的实验,或者来自Stackoverflow或OpenGL论坛的答案。是否有人知道在所有可能的情况下如何工作的全面规则,还是一种查询采样器对应的纹理单位的方法?

2 个答案:

答案 0 :(得分:4)

  

这是我能够找到的:

     
      
  • 如果程序中只有统一的采样器,则将其映射到gl_TEXTURE0
  •   
  • 如果在一个程序阶段中有多个采样器制服,则将按照在着色器中声明的顺序对其进行映射。
  •   
  • 如果顶点着色器和片段着色器的采样器制服集不相交,则顶点着色器中的采样器排在最前面,然后是片段着色器中的采样器。
  •   
  • 此行为似乎是由规范定义的。
  •   

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

所有未在着色器中初始化的统一值都将初始化为值0。规范对此非常清楚:

  

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

采样器制服的值是它表示的纹理单位的整数索引。因此,值0对应于GL_TEXTURE0。所有未初始化的采样器制服的值都应为0。

如果您描述的行为正在发生,则该实现属于OpenGL规范的 violation

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

答案 1 :(得分:2)

您必须将纹理单位的索引设置为采样器均一(类似于设置类型int的均一变量的值)。例如GL_TEXTURE1的值1。

请参见OpenGL 4.6 API Compatibility Profile Specification; 7.10 Samplers; page 154

  

Samplers是OpenGL Shading Language中使用的特殊制服,用于识别   用于每个纹理查找的纹理对象。采样器的值指示正在访问的纹理图像单元。将采样器的值设置为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 Specification - 4.4.4 Opaque-Uniform Layout Qualifiers; page 60

#version 420

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