opengl中纹理单元和采样器制服之间的对应关系
Posted
技术标签:
【中文标题】opengl中纹理单元和采样器制服之间的对应关系【英文标题】:Correspondance between texture units and sampler uniforms in opengl 【发布时间】:2019-02-28 18:20:53 【问题描述】:glActiveTexture
使用的采样器制服和纹理单元之间的对应关系显然无法用 opengl 查询,而且我找不到关于如何找到哪个纹理单元映射到哪个采样器制服的好的文档。这是我能找到的:
gl_TEXTURE0
如果单个程序阶段中有多个采样器制服,则它们会按照它们在着色器中声明的顺序进行映射。
如果顶点着色器和片段着色器具有不相交的采样器 Uniform 集,则顶点着色器中的采样器首先出现,然后是片段着色器中的采样器。
此行为似乎由规范定义。
例如,如果顶点着色器定义:
uniform sampler2D color;
并且片段着色器定义:
uniform sampler2D tex;
uniform sampler2D norm;
然后color
被映射到gl_TEXTURE0
,tex
被映射到gl_TEXTURE1
,norm
被映射到gl_TEXTURE2
。但如果相反,顶点着色器定义:
uniform sampler2D norm;
然后不清楚不同的纹理是如何映射的。由于可能存在布局限定符或单独的着色器阶段,这也变得更加复杂。
我似乎在任何地方都找不到这方面的文档。我所知道的一切要么来自我自己的实验,要么来自 *** 或 OpenGL 论坛上的答案。有谁知道在所有可能的情况下如何工作的一套全面的规则,或者查询采样器对应的纹理单元的方法?
【问题讨论】:
【参考方案1】:这是我能找到的:
如果程序中只有采样器统一,则映射到gl_TEXTURE0
如果单个程序阶段中有多个采样器制服,则它们会按照它们在着色器中声明的顺序进行映射。 如果顶点着色器和片段着色器具有不相交的采样器 Uniform 集,则顶点着色器中的采样器首先出现,然后是片段着色器中的采样器。 此行为似乎由规范定义。
这些都不是真的。好的,第一个是真的,但只是偶然。
所有未在着色器中初始化的统一值都被初始化为值 0。规范非常清楚地说明了这一点:
没有绑定限定符声明的任何统一采样器或图像变量最初绑定到单元零。
采样器制服的值是它所代表的纹理单元的整数索引。所以值 0 对应于GL_TEXTURE0
。所有未初始化的采样器制服的值应为 0。
如果您描述的行为正在发生,那么该实现就违反了 OpenGL 规范。
除非您使用layout(binding = )
语法来分配制服的纹理单元,否则您必须手动在您的OpenGL 代码中为每个采样器制服为其纹理单元分配一个值。这是通过设置其统一值来完成的,就像任何其他整数统一一样:您调用glUniform1i
并使用与该统一对应的位置。因此,如果您想将其与纹理图像单元索引 4 相关联,请调用 glUniform1i(..., 4)
,其中 ...
是该制服的制服位置。
【讨论】:
【参考方案2】:您必须将纹理单元的索引设置为采样器统一(类似于设置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 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;
【讨论】:
以上是关于opengl中纹理单元和采样器制服之间的对应关系的主要内容,如果未能解决你的问题,请参考以下文章