当前位置: 首页 > 知识库问答 >
问题:

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

谢俊力
2023-03-14

显然,opengl无法查询采样器制服和glActiveTexture使用的纹理单元之间的对应关系,我也找不到关于如何找到哪个纹理单元映射到哪个采样器制服的好文档。以下是我能找到的:

  • 如果一个程序中只有采样器统一,那么它将映射到gl_TEXTURE0

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

uniform sampler2D color;

片段着色器定义:

uniform sampler2D tex;
uniform sampler2D norm;

然后颜色映射到gl_TEXTURE0tex映射到gl_TEXTURE1规范映射到gl_TEXTURE2。但是如果相反,顶点着色器定义:

uniform sampler2D norm;

然后不清楚不同的纹理是如何映射的。由于布局限定符或单独的着色器阶段的可能性,这变得更加复杂。

我似乎在任何地方都找不到这个留档。我所知道的一切要么来自我自己的实验,要么来自Stackoverflow或OpenGL论坛上的答案。有人知道在所有可能的情况下如何工作的一套全面的规则,或者查询采样器对应的纹理单元的方法吗?

共有2个答案

谭建章
2023-03-14

必须将纹理单元的索引设置为sampler uniform(类似于设置int类型的统一变量的值)。e、 g.GL_TEXTURE1的值1。

参见OpenGL 4.6 API兼容性配置文件规范;7.10取样器;第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着色语言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;
邵宏达
2023-03-14

以下是我能找到的:

  • 如果一个html" target="_blank">程序中只有采样器统一,那么它映射到gl_TEXTURE0
  • 如果在一个程序阶段有多个采样器制服,那么它们将按照着色器中声明的顺序映射。
  • 如果顶点和片段着色器具有不相交的采样器均匀集,则顶点着色器中的采样器排在第一位,然后是片段着色器中的采样器。
  • 此行为似乎由规范定义。

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

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

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

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

如果您描述的行为正在发生,那么该实现违反了OpenGL规范。

除非使用布局(binding=)语法指定统一的纹理单位,否则必须在OpenGL代码中手动为每个采样器统一的纹理单位指定一个值。这是通过设置其统一值来实现的,就像任何其他整数统一一样:使用对应于该统一的位置调用glUniform1i。所以如果你想把它和纹理图像单位索引4联系起来,你可以调用glUniform1i(…,4),其中 是该制服的统一位置。

 类似资料:
  • 使用OpenGL(核心配置文件,4.4),将同一个采样器对象同时绑定到2个不同的纹理单元是否“合法”? 我的测试表明它是有效的,但我不知道我的司机是否原谅了我,或者这是一项功能。

  • 我对如何将纹理绑定到GLSL中的插槽有点困惑。以下是我的着色器: 当我设置矩阵时,我需要查询统一位置,然后手动设置该位置的值,执行如下操作: 然而,据我所知,我不需要这样做来初始化我的纹理采样器。在设置时,我似乎只需要这样做: 所以,我的问题是,为什么我不需要对纹理进行与矩阵相同的处理?OpenGL运行时如何“知道”我绑定的纹理应该是我定义的采样器?如果我想拥有多种纹理,我该怎么做呢?

  • 我目前正在将一个采样器对象绑定到一个纹理单元(具体来说是GL_TEXTURE12)上 与纹理自身的设置相比,初始设置非常明显。但是当我用 绑定到纹理单元的纹理过滤与之前相同,从任何角度看都没有明显的变化。 在参数更改后,我尝试将采样器重新绑定到纹理单元,但我很确定这不是必需的。 我可以做些什么改变来让它工作?

  • “我在我的申请中发现了一个奇怪的行为,希望你能解释给我听。”。你看,我有两个3D纹理,它们被发送到片段着色器,渲染得非常好。但有一个问题,当我创建另一个纹理(它是1D纹理)时,一个黑屏正在被渲染,而不是正确的前一个结果。 关于这个1D纹理,我甚至没有将其发送到片段着色器。当我调用glTexImage1D(…)时,黑屏就出现了。我评论这句话,它就消失了!!这两种纹理被渲染。 我觉得纹理单位肯定有问题

  • 最近我发现了一个OpenGL示例,它应用纹理而没有指定纹理图像单元并且没有将相应的单元整数均匀发送到着色器中,是否可以在不使用纹理单元的情况下应用纹理??或者它只是为活动纹理单元及其着色器采样器值使用默认值。 我的代码块(纹理相关): 我的片段着色器:

  • 我需要在着色器中使用两个纹理,一个在顶点着色器中,另一个在片段着色器中。在这两种情况下,它们都在着色器中引用,例如