从texture()切换到texelFetch()

时间:2017-08-10 12:07:11

标签: c++ opengl glsl shader fragment-shader

目前我正在使用函数texture(...)读取3D纹理,如下所示:

vec3 value = texture(texture_3D, coord).rgb

我现在想做的是:

vec3 value = texelFetch(texture_3D, coord, 0).xyz

但是,我不知道如何转换我的坐标以便它与texelFetch一起使用。我的纹理大小为256x256x256

我目前的坐标计算如下:

vec3 min_box = vec3(-0.5);
vec3 max_box = vec3(0.5);

vec3 coord = worldToVolume(world_pos, min_box, max_box)

vec3 worldToVolume(world_pos, min_box, max_box) {
     return (world_pos - min_box) / (max_box - min_box)
}

有什么想法吗?如果您需要更多信息,请询问,我会提供。

2 个答案:

答案 0 :(得分:5)

这两个函数在完全不同的参数上执行完全不同的任务。

http://my-domain/api/components/search?qualifiers=TRK 期望归一化的浮点纹理坐标在[0,1] 中(即0为左/下,1为右/上)并执行正确的包裹(因此坐标为根据您设置的采样模式,不一定必须在[0,1]中并过滤(因此您不一定得到确切的纹理颜色)。

另一方面,

texture期望整数纹素指数在[0,宽度-1] (以及y和z的高度/深度)并且不执行任何类型的过滤或换行,访问指定mipmap级别中指定索引处的确切texel值。

所以texelFetch应该等同于texelFetch(texture_3D, ivec3(coord * vec3(256.0), 0) 过滤模式texture(texture_3D, coord)和包装模式GL_NEAREST。但是,如果coord完全是GL_CLAMP_TO_EDGE或纹素边界,也要记住可能的舍入问题,在这方面可能1.0可能更安全。

然而,与仅使用texelFetch(texture_3D, ivec3(coord * vec3(255.0) + vec3(0.5), 0)过滤器保持当前纹理访问权限相比,仅仅以这种方式更改它似乎是一种相当无用的方法。如果您已经有整数纹理坐标并且已经知道纹理大小,那么它会更有用。只是以这种方式模拟最接近的过滤并不能真正为你买任何东西。它基本上是两种概念上不同的方法,一种过滤具有与尺寸无关的浮点坐标的纹理,另一种用于访问具有整数索引的3D数组。这取决于您的周围代码哪种方法更适合您的用例。

答案 1 :(得分:3)

worldToVolume后坐标似乎在[0,1]范围内。由于texelFetch需要整数纹理坐标而不是标准化纹理坐标,因此必须将其与纹理大小相乘:

vec3 coord = worldToVolume(world_pos, min_box, max_box);
ivec3 texel_fetch_coord = ivec3(coord * vec3(256, 256, 256));

请注意,您可以使用textureSize方法查询着色器内纹理的大小(如果纹理的大小不一致)。