1

我在使用gpu 光线投射技术的着色器中实现了体积渲染。基本上我的场景中心有一个单位立方体。我在顶点着色器中渲染单位立方体的顶点,并将纹理坐标传递给片段着色器,如下所示:

in vec3 aPosition;
uniform mat4 uMVPMatrix;
smooth out vec3 vUV;
void main() {
   gl_Position = uMVPMatrix * vec4(aPosition.xyz,1);
   vUV = aPosition + vec3(0.5);
}

由于单位立方体坐标从 -0.5 变为 0.5,我通过向它们添加 0.5 将纹理坐标从 0.0 固定到 1.0..

在片段着色器中,我得到了由光栅器插值的纹理坐标:

...
smooth in vec3 vUV; // Position of the data interpolated by the rasterizer
...
void main() {
    ...
    vec3 dataPos = vUV;
    ...
    for (int i = 0; i < MAX_SAMPLES; i++) {
        dataPos = dataPos + dirStep;
        ...
        float sample = texture(volume, dataPos).r;
        ...//Some more operations on the sampled color
        float prev_alpha = transferedColor.a * (1.0 - fragColor.a);
        fragColor.rgb += prev_alpha * transferedColor.rgb; 
        fragColor.a += prev_alpha; //final color
        if(fragColor.a>0.99)
            break;
    }
}

我的渲染效果很好。

现在我已经实现了一个选择算法,它可以很好地处理粒子(世界坐标中的真实顶点)。

我的问题是如何使它与体积数据集一起使用?因为我只有顶点是单位立方体的顶点。由于数据点是由光栅化器插值的,所以我不知道体素的真实(世界)坐标。

对我来说,获取体素的中心坐标并将它们视为粒子是很公平的,这样我就可以在片段着色器中省略或包含必要的体素(我猜是 vUV 坐标?)。

4

1 回答 1

2

首先,您必须计算出您的采样体素坐标。(我假设体积是你的 3D 纹理)。要找到它,您必须将它从dataPos去线性化为 3D 纹理 (wxhxd) 中的 3 轴组件。因此,如果 MAX_SAMPLES 中的样本具有计算为 ((z * d) + y) * h + x 的索引,则可以通过以下方式找到坐标。

z = 地板(样本 /(w * h))

y = floor((样本 - (z * w * h)) / w)

x = 样本 - (z * w * h) - (y * w)

地板操作对于检索整数索引很重要。

这是您的样本的坐标。现在您可以将它与用于 4 个顶点的 mvp 的倒数相乘,这将为您提供样本在世界空间中的位置(或中心,也许您必须添加 vec3(0.5))。

然而,这提出了一个新问题:看看你是否可以重写你的选择算法,这样你就不必跳过所有的计算,并在屏幕空间而不是世界空间中进行选择。

于 2014-09-23T11:48:36.760 回答