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

OpenGL4。5-绑定多个纹理和采样器

梁马鲁
2023-03-14

我试图理解OpenGL 4.5中的纹理、纹理单位和采样器。我在附上一张我想弄明白的照片。我认为在我的例子中,一切都是正确的,但我不太确定右侧带有问号的1D采样器。

因此,我知道OpenGL提供了许多纹理单元/绑定点,可以在其中绑定纹理和采样器,以便它们协同工作。

这些绑定点中的每一个都可以支持每个纹理目标中的一个(在我的例子中,我将目标GL_TEXTURE_2DGL_TEXTURE_1D绑定到绑定点0,另一个GL_TEXTURE_2D绑定点1)。

此外,采样器可以以大致相同的方式绑定到这些绑定点(我已经将2D采样器绑定到了图片中的绑定点0)。

执行这些操作的函数是glBindTexureUnitglBindSample

我最初的想法是将1D采样器也绑定到绑定点0,并在shader land中根据绑定点和采样器的类型进行匹配:

layout (binding = 0) uniform sampler1D tex1D;
layout (binding = 0) uniform sampler2D tex2D;

引用来源:

每个纹理图像单元都支持绑定到所有目标。因此,2D纹理和阵列纹理可以绑定到同一图像单元,或者不同的2D纹理可以绑定到两个不同的图像单元,而不会相互影响。那么渲染时使用哪种纹理呢?在GLSL中,这取决于使用此纹理图像单元的采样器类型。

但我发现了以下语句:

[..] 听起来似乎可以对不同的采样器使用相同的纹理图像单元,只要它们具有不同的纹理类型。不要这样做。规范明确禁止它;如果两个不同的GLSL采样器具有不同的纹理类型,但与同一纹理图像单元关联,则渲染将失败。给每个采样器一个不同的纹理图像单元。

所以,我的问题是,如果最终一个采样器将绑定到同一个绑定点,迫使您选择,那么将不同的纹理目标绑定到同一个绑定点的目的是什么?

我引用的信息是:https://www.khronos.org/opengl/wiki/Texture#Texture_image_units

共有2个答案

淳于乐池
2023-03-14

假设您有两个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_sampler1DprogA_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);

请注意,unitGL_TEXTURE0 1将两种纹理text1D_1和text2D_2绑定为不同类型
同样地,GL_TEXTURE0 2绑定了两种纹理,类型分别为GL_TEXTURE_2DGL_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);
齐才艺
2023-03-14

那么,为什么会存在这种情况呢?好

很久以前,没有纹理单元(这就是为什么glActiveTextureglBindTexture是一个独立的函数)。事实上,OpenGL 1.0中甚至没有纹理对象。但仍然需要不同种类的纹理。您仍然需要能够为2D纹理和3D纹理创建数据。因此,他们提出了纹理目标的区别,并使用glEnables来确定渲染操作中将使用哪个目标。

当纹理对象出现在GL 1.1中时,它们必须决定纹理对象和目标之间的关系。他们决定,一旦一个对象绑定到一个目标上,它就与该目标永久关联。由于上述需要具有不同类型的多个纹理,使用旧的启用功能,决定每个目标代表一个单独的对象绑定点。他们让你在glBindTexture中重复绑定点,这样代码的读者就可以清楚地知道你在干扰哪个绑定点的数据。

当multitexture问世时,切换到OpenGL 1.2。所以现在他们需要你能够绑定同一目标的多个纹理,但要绑定到不同的“单位”。但他们无法更改glBindTexture来指定特定的单位;这将是一个向后不兼容的变化。

现在,他们可以彻底改变纹理的工作方式,创建一个专门用于多纹理等的新绑定功能。但是OpenGL ARB喜欢向后兼容;他们喜欢让旧的API函数工作,不管生成的API是什么样子。因此,他们决定一个纹理单元是一整套绑定,每组绑定都有一个启用状态,表示要使用哪个目标。您可以使用glActiveTexture在单元之间切换。

当然,一旦着色器出现,您可以看到这一切是如何变化的。启用状态将成为着色器中的采样器类型。所以现在没有明确的代码描述启用了哪个纹理目标;这只是着色器的东西。因此,他们必须制定一条规则,规定如果两个采样器的类型不同,就不能使用同一个采样器。

这就是为什么每个纹理单元都有多个独立的绑定点:OpenGL对向后兼容性的promise。

最好忽略这种能力的存在。绑定特定着色器所需的正确纹理。所以专注于使用这些函数,不要担心两个纹理绑定到同一个目标。如果要确保没有意外使用错误的纹理,可以使用纹理名称为0的glBindTexturesglBindTextureUnit,这将解除特定纹理单元中所有目标的绑定。

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

  • 如何为一个纹理阵列创建多个采样器 到目前为止,我一直依赖OpenGL来确定声明的sampler是指我与绑定的纹理数组。 我尝试在片段着色器中指定两个采样器,但片段着色器出现编译错误: 我没想到这会起作用,但是,我不确定片段着色器编译器是否检查采样器是否分配了纹理,所以可能是其他问题。 我尝试生成和绑定采样器对象,但我仍然得到一个片段着色器错误: 我想坚持使用OpenGL的较低版本,有可能吗?非常感

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

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

  • 在openGL中,可以将一个纹理绑定到两个(或多个)不同的统一采样器吗?使用两种不同的纹理进行渲染时,如下所示: 着色器: 客户: 但当我尝试将一个纹理对象绑定到两个不同的纹理单元时,似乎第一个绑定的单元保持未绑定状态: 当然,可以为两个采样器设置相同的单位,但有时我还想为不同的纹理使用着色器,而不仅仅是为两个采样器设置相同的纹理对象。 这个解决方案实际上运行得很好,但它不符合我所描述的需求。也可

  • 我正在编写一个批处理系统,它跟踪当前绑定的纹理,以避免不必要的调用。我不确定是否需要跟踪特定批次已经使用了哪些纹理,因此如果一个纹理被使用两次,它将被绑定到需要它的第二个采样器的不同TIU。 OpenGL应用程序是否可以在同一着色器阶段内对多个采样器使用相同的纹理图像单元?不同着色器阶段的采样器如何?例如: 片段着色器: 主要节目: 我看不出这不起作用的任何原因,但是如果着色器程序也包括这样的顶点