我将在下面阅读您的陈述。有时我会与OpenGL 4.5 core profile specification 的引用争论。这些都不是 GL 4.5 特有的,我只是选择它,因为那是最新版本。
1.将两个纹理绑定到同一个纹理单元是
不可能。
如果我说“假”,那可能会产生误导。确切的说法是“将两个纹理绑定到同一纹理单元的同一目标是不可能的”。从技术上讲,您可以说,将 2D 纹理和 3D 纹理绑定到同一个单元。但是你不能在同一个绘图调用中使用。请注意,这是一个动态错误条件,取决于您将采样器制服设置为什么值。引用自 GL 规范的第 7.10 节“采样器”:
不允许有不同采样器类型的变量
指向程序对象内的相同纹理图像单元。这
只能在下一个渲染命令发出时检测到这种情况
触发着色器调用,INVALID_OPERATION 错误将
然后生成。
因此,当您实际尝试使用该着色器绘制某些东西(或以其他方式触发着色器调用)时,GL 将立即检测到此错误情况,同时您将其配置为两个采样器制服引用同一单元的不同目标。但这不是之前的错误。如果您暂时将两个制服设置为相同的值,但不尝试在该状态下进行绘制,则不会产生错误。
2。将两个采样器绑定到同一个纹理单元是不可能的。
您的意思可能是 Sampler Objects(与 GLSL 中的“采样器”类型相反),所以这是真的。
3.将一个纹理绑定到两个不同的纹理单元是不可能的。
错误。您可以将相同的纹理对象绑定到尽可能多的可用单元。然而,这是一个相当无用的操作。在固定功能管道的时代,有一些使用有限的极端情况。例如,我看到有人绑定相同的纹理两次并使用寄存器组合器将两者相乘,因为他需要一些平方运算。但是,使用着色器,您可以对纹理进行一次采样,然后对结果做任何您想做的事情,因此真的没有用例了。
4.将一个采样器绑定到两个不同的纹理单元是不可能的。
错误。单个采样器对象可以被多个纹理单元引用。您可以为您需要的每个采样状态创建一个采样器对象,无需创建多余的。
5.应用程序有责任明确将什么采样器类型传递给什么统一变量。
6.确保将采样器作为统一变量的正确类型是着色器程序的责任。
我不确定你在这里问什么。着色器中的采样器变量选择纹理目标,并且还必须匹配您要使用的纹理对象的内部数据(即对于isampler 或usampler,您将需要未标准化的整数纹理格式,否则结果未定义) .
但我不知道“将什么采样器类型传递给什么统一变量”在这里应该是什么意思。就 GL 客户端而言,不透明采样器制服只是可以设置为要使用的纹理单元的索引的东西,并且可以通过glUniform1i 等以整数形式完成。没有“采样器类型”传递给统一变量。
7.纹理单元的数量足够大。让加载到应用程序的每个网格占用尽可能多的纹理单元。
一般情况下不会。 GL 4.5 规范要求的GL_MAX_TEXTURE_IMAGE_UNITS(它定义了片段着色器可以访问多少个不同的纹理单元)只有 16 个。(每个 shder 阶段都有单独的限制,所以有 GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS、GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 等等. 在当前规范中,它们都必须至少为 16。)
通常,您必须在两次绘制调用之间切换纹理。使用array textures 和texture atlasses 可能会进一步减少必要的状态切换次数(并最终减少绘图调用)。
非常现代的 GPU 也支持GL_ARB_bindless_texture,它完全绕过了“纹理单元”层的间接性,并允许着色器通过一些不透明的句柄直接引用纹理对象(这基本上归结为引用下面的一些虚拟 GPU 内存地址引擎盖)。但是,该功能还不是 OpenGL 标准的一部分。
8.一些采样器参数是纹理参数的副本。它们将覆盖纹理参数设置。
是的。传统上,GL 中没有单独的采样器对象。相反,过滤或环绕模式等采样器状态是纹理对象本身的一部分。但现代硬件不以这种方式运行,因此采样器对象 API 已作为 GL_ARB_sampler_objects 扩展(现在是 GL 的核心功能)引入。如果采样器对象绑定到纹理单元,则其设置将覆盖纹理对象中存在的采样器状态。
9.一些采样器参数与着色器程序中的采样器描述重复。着色器程序的描述将覆盖采样器参数。
我不确定你的意思。着色器程序定义了哪些“采样器描述”?只有统一的声明和可能通过layout(binding=...) 进行的初始化。但是,这只是初始值。客户端可以通过将统一设置为另一个值来随时更新它,因此这并不是真正“覆盖”任何东西。但我不确定你是不是这个意思。