如何使用纹理缓冲区读取单个整数而不是vec4

9

我有一段工作代码,其中我从纹理缓冲区中读取着色器中的vec4值。

在客户端,我创建了一个位移向量缓冲区:

vec4 vector1 : vec4(x1, y1, z1, w1);
vec4 vector2 : vec4(x2, y2, z2, w2);
vec4 vector3 : vec4(x3, y3, z3, w3);
..

接下来,我创建一个顶点缓冲区,其中包含向量1、向量2、向量3等。

然后,我创建一个纹理,并使用以下方式将上述缓冲区绑定到它上面:

glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, bufferID);

我选择GL_RGBA32F是因为x1、y1、z1、w1等都是浮点数。
在着色器中,我可以使用以下代码获取单个向量:
vec4 vector1 = texelFetch(samplerObj, 0);
vec4 vector2 = texelFetch(samplerObj, 1);
.
.

但是,现在假设我的位移向量不是vec4,而是一个整数。

int vector1 = x1; //(int is 32 bit unsigned)
int vector2 = x2; //(int is 32 bit unsigned)

有人能告诉我对应的内部格式会是什么吗?是

吗?
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32UI, bufferID);

同时,我该如何使用texelFetch在着色器中获取值?

int vector1 = texelFetch(samplerObj, 0);

或者

int vector1 = texelFetch(samplerObj, 0).r ?

我感到困惑,因为texelFetch应该返回一个有4个组件的像素,所以我必须使用结果的红色组件吗?


我不了解samplerBuffers,但对于image_load_store,内部格式必须匹配layout()语句。当调用imageLoad()时,它总是返回一个vec4/uivec4/ivec4等。如果它没有4个分量,你可以忽略剩下的部分,就像你说的那样,只读取.r作为例子。我在这里只是推测,也许这意味着最好按16字节块读取。 - jozxyqk
@jozxyqk:非图像统一布局没有格式限定符这样的东西。 - thokra
@thokra,这就是为什么我说“我不了解samplerBuffers”。我试图提供我的有关类似事物的知识。虽然它不完全匹配,但也许有一些重叠。texelFetch是否会隐式地用4个字节的步长索引GL_R32UI内部格式的usamplerbuffer,并且将rgba的gba未定义?我不知道。 - jozxyqk
@jozxyqk:如果您使用的采样器与内部格式不匹配,则纹理查找函数返回的值将是未定义的。因此,对于浮点格式,您应该使用sampler,对于非规范化的int和uint格式,分别使用isampler或usampler*。 - thokra
1个回答

11

您已经提到了无符号整数的正确内部格式:R32UI。允许使用的格式在OpenGL 4.4核心配置规范的第8.9节中列举在表8.15中。请注意,当使用上述内部格式的缓冲纹理进行texelFetch时,缓冲存储区的内容不会被归一化!这意味着,在查找时,您得到的值不是[0,1]范围内的值,而是[0,2 ^(n-1)]的范围。

您需要一个usamplerBuffer,而不是samplerBuffer

如果您使用在前面提到的表中指定的R32UI内部格式的samplerBuffer进行texelFetch,将返回一个包含以下值的: uvec4(R,0,0,1)

int vector1 = texelFetch(samplerObj, 0);

这将导致编译时出错,因为从uvec4int没有隐式转换。

int vector1 = texelFetch(samplerObj, 0).r;

这个swizzle掩码将返回由texelFetch返回的uvec4的R分量,并将uint隐式转换为int。语义上,将标量值命名为向量是没有意义的。 ;)

实际上你想要的是类似于:

uint displacement = texelFetch(samplerObj, 0).r;

samplerObj 是一个 usamplerBuffer

编辑: 仅澄清一下,texelFetch 总是返回一个 gvec4 - 其中 g 简单地为空(固定点和浮点格式)、iu。向量如何填充取决于缓冲纹理的内部格式。如果选择 R32F,则会得到一个非规范化的 vec4(R, 0, 0, 1),对于 RGBA16,您将获得一个规范化的 vec4(R, G, B, A)。

为了避免进一步混淆:当使用单组分格式时,不需要为 4 组件向量分配内存!它们在查询时只会扩展为 gvec4!


1
我相信问题的一大部分是指texelFetch总是返回一个四分量矢量的事实。如果你使用texelFetch(samplerObj,0)。r,那么它就会给出第一个元素。texelFetch(samplerObj,1)。r会给出第二个还是第五个元素?这个问题的答案是否取决于内部格式?例如,如果内部格式为GL_R32UI,则如果返回第二个元素,GL_RGBA32UI则会导致返回第五个无符号整数,这是可以理解的。Image_load_store需要显式布局声明,samplerBuffer是否类似但隐式? - jozxyqk
@jozxyqk:看我的编辑。你将得到数据存储中的第一个和第二个元素。通过将texcoord增加一,您始终会得到下一个元素,因为缓冲纹理本质上是由1D数组(缓冲对象的数据存储)支持的。 - thokra

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