【发布时间】:2018-07-29 06:02:05
【问题描述】:
OpenGL 有 array textures,在着色器中由特定的采样器类型表示:
sampler2DArray array_texture;
但 GLSL 也允许将采样器聚合到数组中:
sampler2D array_of_textures[10];
这两个功能是否相互关联?它们有何不同?
【问题讨论】:
OpenGL 有 array textures,在着色器中由特定的采样器类型表示:
sampler2DArray array_texture;
但 GLSL 也允许将采样器聚合到数组中:
sampler2D array_of_textures[10];
这两个功能是否相互关联?它们有何不同?
【问题讨论】:
让我们通过类比来理解区别。 GLSL 中的采样器就像 C++ 中的指针;它们引用给定类型的其他对象。所以考虑下面的 C++ 代码:
int* pi;
std::array<int, 5>* pai;
std::array<int*, 5> api;
pi 是指向 int 类型的单个对象的指针(让我们忽略从技术上讲它可能是指向 ints 数组的指针这一事实。
pai 也是一个指针。但它并不指向int;它指向ints 中的array。 “array of ints”是一个对象,具有一个连续的存储分配。
api 不是指针;它是一个数组。具体来说,它是一个指向ints 的指针数组。每个单独的指针都可以指向单独的int 对象。每个单独的指针都独立于其他指针,它们指向的对象完全不相关,除了它们都必须是ints。
这与 OpenGL 和纹理有什么关系?
pi 就像 sampler2D。pai 就像 sampler2DArray:一个指针/采样器,它引用了多个 int/2D 纹理,这些纹理都位于一个对象中。api 就像sampler2D[]:代表多个指针/采样器的单个名称,每个指针/采样器都是独立绑定的,引用不相关的对象,除非它们都必须是int/sampler2Ds。 数组纹理是与非数组纹理不同的构造。数组纹理有一个特殊的纹理目标。在 GLSL 中访问数组纹理需要显式使用与目标匹配的不同采样器类型。采用数组纹理的纹理访问函数采用额外的纹理坐标分量,提供要访问的数组层。当您将纹理分配给阵列纹理采样器时,您将分配一个纹理对象,无论创建它时使用多少个阵列层。
相比之下,采样器数组只是按一个名称分组的多个独立采样器的编译时大小的集合。纹理被独立分配到数组中的位置,可以使用任何适当类型的纹理。数组的每个元素占用一个额外的绑定点。
除了资源消耗之外,最大的区别在于:您可以使用运行时索引从数组中选择一个采样器(在 OpenGL 4.x 中;在 4.x 之前的版本中,您必须使用编译时常量。所以采样器数组基本上没用)。
但不是任意运行时索引。您只能使用dynamically uniform expression 的索引。也就是说,对于绘图命令中的所有调用,执行该指令的每个调用必须产生相同的索引。
数组纹理没有这样的索引限制;您在纹理获取命令中为它们提供的数组索引可以是任何运行时值(当然是在数组内)。
但数组纹理确实有其他限制。数组纹理中的每个“纹理”都具有相同的大小;所以如果你创建一个 512x512x20 的二维数组纹理,每个子纹理都是 512x512。对于采样器数组,数组中每个纹理的大小可以变化。当然,每个采样器数组索引占用一个绑定点这一事实也很重要;每个阶段只有 16 个(尽管可能更多;16 是最低要求)。
【讨论】: