如何在不使用计算着色器的情况下遍历 3D texture/buffer 中的每个像素

How to loop over every pixel in a 3D texture/buffer without using compute shaders

我了解您将如何使用 2D 缓冲区执行此操作。只需绘制两个三角形,形成一个完全包含 2D 缓冲区的四边形 space。这样,当片段着色器运行时,它会针对缓冲区中的所有像素运行。

问题:这对于 3D 缓冲区如何工作?

你可以为 3D 缓冲区的每个横截面写很多三角形。但是,如果您有一个 1x1x256 的纹理,这意味着您需要为每个切片绘制 256*2 个三角形以遍历所有像素。我知道这是一个极端情况,有一些方法可以优化这个解决方案。但是,我觉得我缺少一个更优雅的解决方案。

我正在尝试做的事情:我正在尝试制作一个 3D 流体解算器,它遍历 3D 纹理的每个像素并计算其速度、密度等.我正在尝试通过片段着色器执行此操作,因为我使用的是不使用计算着色器的 OpenGL 3.0。

#version 330 core
out vec4 FragColor;

uniform sampler3D volume;
void main()
{
    // computing the fluid density, velocity, and center of mass
    
    // output the values to the 3D buffer to diffrent color channels:
    fragColor = vec4(density, velocity.xy, centerOfMass);
}

在片段着色器的某个时刻,您将编写一些如下形式的语句:

vec4 value = texture(my_texture, TexCoords);

其中 TexCoordsmy_texture 中映射到源纹理中某个特定值的位置。但是...映射 完全 取决于您。没有人让你使用 gl_FragCoord.xy / textureSize(my_texture)。您可以轻松地使用 vec3(gl_FragCoord.x, Y_value, gl_FragCoord.y) / textureSize(my_texture),它将片段位置的 Y 分量放在纹理的 Z 维度中。 Y_value 在这种情况下是一个从外部传递的值,它告诉要使用 3D 纹理的哪个垂直切片。

当然,当您写入数据时,也必须使用您用来获取数据的任何映射。如果您通过片段着色器输出进行编写,则会出现问题。 3D 纹理只能作为单个 2D 切片或作为一组分层的 2D 切片附加到 FBO,这些切片始终沿着图像的 Z 维度。因此,即使您尝试沿 Y 维度读取切片,也必须以 Z 切片写入。所以你会在数据的位置周围移动,这使得它不可行。

如果您使用的是图片 load/store,则没有问题。您可以只写入适当的纹素(实际上,您可以使用整数坐标将其作为图像读取,因此无需除以纹理的大小)。