【问题标题】:Switching from texture() to texelFetch()从 texture() 切换到 texelFetch()
【发布时间】:2017-08-10 12:07:10
【问题描述】:

目前我使用函数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)
}

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

【问题讨论】:

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


    【解决方案1】:

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

    texture 期望 [0,1] 中的标准化浮点纹理坐标(即 0 为左/下,1 为右/上)并执行正确的环绕(因此坐标不会必须在 [0,1] 中)并根据您设置的任何采样模式进行过滤(因此您不一定获得确切的纹理颜色)。

    另一方面,

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

    所以texelFetch(texture_3D, ivec3(coord * vec3(256.0), 0) 应该等同于texture(texture_3D, coord) 带有 过滤模式GL_NEAREST 和包装模式GL_CLAMP_TO_EDGE。但是,还要记住,如果坐标正好是 1.0 或在纹素边界上,可能会出现舍入问题,也许 texelFetch(texture_3D, ivec3(coord * vec3(255.0) + vec3(0.5), 0) 在这方面可能更安全。

    但是,与简单地使用GL_NEAREST 过滤器保持当前纹理访问相比,仅以这种方式更改它似乎是一种相当无用的方法。如果您已经拥有整数纹理像素坐标并且已经知道纹理大小,则它会更有用。仅以这种方式模拟最近的过滤不会真正为您买任何东西。它基本上是两种概念上不同的方法,一种使用与大小无关的浮点坐标过滤纹理,另一种访问具有整数索引的 3D 数组。这取决于您周围的代码,哪种方法更适合您的用例。

    【讨论】:

    • 如果我只是使用 texelFetch 选项而不是 texture(),那么有什么大区别。使用 texelFetch 时,我不必关心是使用 GL_NEAREST 还是 GL_LINEAR
    • 嗯,如前所述,差别不大。这完全取决于你想做什么以及你得到了什么信息。就这样。如果您的坐标已经是整数并且在适当的范围内,那么texelFetch 是个好主意。如果您已经标准化了浮点纹理坐标并且必须明确知道纹理大小(或使用textureSize 查询),那么这似乎是一个不好的方法。一种方法是您不必关心过滤,另一种方法是您不必关心纹理大小。任何对你来说更方便的东西。
    【解决方案2】:

    worldToVolume 之后,您的坐标似乎在 [0, 1] 范围内。由于texelFetch 需要整数纹理坐标而不是归一化纹理坐标,因此必须乘以纹理大小:

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

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

    【讨论】:

    • 准确地说,texelFetch 需要 整数 纹理坐标。
    • @Ripi2:你说得对,我更新了答案:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-08
    • 2010-10-10
    • 2017-02-06
    • 2018-11-04
    • 2011-10-26
    相关资源
    最近更新 更多