OpenGL纹理使用

3

图片

最近我开始阅读OpenGL维基文章。以下是我从这里了解到的OpenGL纹理描述。但是,有一些点还不太清楚。

以下说法是真是假还是取决于情况?

  1. 将两个纹理绑定到同一个纹理单元是不可能的。
  2. 将两个采样器绑定到同一个纹理单元是不可能的。
  3. 将一个纹理绑定到两个不同的纹理单元是不可能的。
  4. 将一个采样器绑定到两个不同的纹理单元是不可能的。
  5. 应用程序需要明确传递哪种采样器类型到哪个统一变量。
  6. 着色器程序需要确保以正确的统一变量类型接收采样器。
  7. 纹理单元的数量足够大。让每个加载到应用程序中的网格占据尽可能多的纹理单元。
  8. 某些采样器参数与纹理参数重复。它们将覆盖纹理参数设置。
  9. 某些采样器参数与着色器程序中的采样器描述重复。着色器程序的描述将覆盖采样器参数。
1个回答

3
我正在阅读以下声明。有时我会引用OpenGL 4.5核心规范中的内容进行辩论。这些内容并不特定于GL 4.5,我选择它只是因为这是最新版本。

1. 将两个纹理绑定到同一纹理单元是不可能的。

如果我说"false",可能会误导人。确切的陈述是“将两个纹理绑定到同一纹理单元的相同目标是不可能的”。技术上说,您可以说将2D纹理和3D纹理绑定到同一单元。但是您不能在同一绘制调用中同时使用两者。请注意,这是一个动态错误条件,取决于您将采样器uniform设置为什么值。从GL规范的第7.10节“采样器”中引用:

不允许将不同采样器类型的变量指向程序对象内的相同纹理图像单元。此情况仅能在下一个触发着色器调用的渲染命令中检测到,并且将生成一个INVALID_OPERATION错误。

因此,GL将在您尝试绘制某些东西(或以其他方式触发着色器调用)时检测到此错误条件,而您配置了该着色器,使得两个采样器uniform引用同一单元的不同目标。但在之前不是错误。如果您暂时将两个uniform都设置为相同的值,但不尝试在该状态下进行绘制,则永远不会生成错误。

2. 将两个采样器绑定到相同的纹理单元是不可能的。

您可能指的是采样器对象(与GLSL中的“sampler”类型相对),因此这是正确的。

3. 将一个纹理绑定到两个不同的纹理单元是不可能的。

假的。您可以将相同的纹理对象绑定到所有可用的单元。但是,这是一个非常无用的操作。在固定功能管道的时代,有一些极端情况下这是有限制使用的。例如,我曾看到有人将相同的纹理绑定两次,并使用寄存器组合器将两个纹理相乘,因为他需要某种平方运算。但是,使用着色器,您可以对纹理进行一次采样,然后对结果进行任何操作,因此没有用例留下。

4. 将一个采样器绑定到两个不同的纹理单元是不可能的。

假的。可以通过多个纹理单元引用单个采样器对象。您只需为每个需要的采样状态创建采样器对象,无需创建冗余采样器对象。

5. 应用程序应清楚地知道将哪种采样器类型传递给哪个统一变量。

6. 着色器程序必须确保将采样器作为正确类型的统一变量使用。

我不太确定您在这里究竟要求什么。着色器中的采样器变量选择纹理目标,并且还必须与您想要使用的纹理对象的内部数据格式匹配(例如,对于isamplerusampler,您需要非规范化的整数纹理格式,否则结果是未定义的)。

但是我不知道“将哪种采样器类型传递给哪个统一变量”在这里意味着什么。就GL客户端而言,不透明的采样器统一变量只是可以设置为要使用的纹理单元索引的东西,而且可以通过glUniform1i等方式以整数形式进行设置。没有将“采样器类型”传递给统一变量。

7. 纹理单元的数量足够大。让每个加载到应用程序的网格占用尽可能多的纹理单元。

通常情况下不是这样。 GL 4.5规范中定义的GL_MAX_TEXTURE_IMAGE_UNITS(它定义了片段着色器可以访问多少个不同的纹理单元)仅为16。(每个着色器阶段都有单独的限制,因此有GL_MAX_VERTEX_TEXTURE_IMAGE_UNITSGL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS等等。在当前规范中,它们都必须至少为16。)

通常情况下,您需要在绘制调用之间切换纹理。使用数组纹理纹理地图可能允许进一步减少所需状态切换的数量(最终减少绘制调用次数)。

非常现代的GPU还支持GL_ARB_bindless_texture,它完全绕过了“纹理单元”间接层,并允许着色器通过某些不透明句柄直接引用纹理对象(这基本上归结为引用底层虚拟GPU内存地址)。但是,该功能尚未成为OpenGL标准的一部分。

8. 一些采样器参数是纹理参数的重复。它们将覆盖纹理参数设置。

是的。传统上,GL中没有单独的采样器对象。相反,过滤或包裹模式等采样器状态是纹理对象本身的一部分。但现代硬件不是这样工作的,因此采样器对象API已被引入作为GL_ARB_sampler_objects扩展(现在是GL的核心功能)。如果将采样器对象绑定到纹理单元,则其设置将覆盖纹理对象中存在的采样器状态。
9. 一些采样器参数与着色器程序中的采样器描述重复。着色器程序的描述将覆盖采样器参数。
我不确定您的意思是什么。着色器程序定义了什么“采样器描述”?只有uniform的声明和可能通过layout(binding=...)进行初始化。然而,那只是初始值。客户端可以随时通过将uniform设置为另一个值来更新它,因此它实际上并没有“覆盖”任何内容。但我不确定您是否是这个意思。

谢谢你的回答。我没有区分glsl中的采样器对象和采样器。通过着色器“程序描述”,我指的是着色器类型(sampler1D,sampler2D,sampler3D等),因为我认为在将其传递到着色器程序之前,应用程序会设置采样器将查找哪个目标纹理单元,并将其存储为参数。我猜那是错误的?着色器对象只是对纹理单元的引用,“使用哪个目标”仅由glsl给出的类型(sampler1D等)决定。这是正确的方向吗? - user2883715

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