1

这里介绍了使用 OpenGL 的过时 API 进行体积渲染的方法。但是现在,我想使用 GLSL 完成体积渲染,并且我已经完成了其中的一些部分。我的问题是如何进行混合。在上面的链接中,混合是通过以下代码完成的:

glEnable(GL_BLEND);
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

但是如何使用 GLSL 完成混合?

我尝试使用以下等式:

C = Cs*As + Cd(1 - As)

Cs 是源对象的颜色。Cd 是目标对象的颜色。源对象的 alpha 也是如此。我在片段着色器中的代码如下:

......
vec3 dir = backPoint - frontPoint;
float len = length(dir);
float stepSize = 0.01;
vec3 deltaDir = normalize(dir)*stepSize;
float deltaLen = length(deltaDir);
float accLen = 0;
float accAlpha = 0;
float sampleAlpha = 0;
vec4 accColor = vec4(0.0);

vec3 samplePoint = frontPoint;
vec4 sampleColor;
while(accLen < len && accColor.a <= 1.0){
    sampleColor = texture(texture3D, samplePoint);

    accColor = sampleColor*sampleColor.a + accColor*(1-sampleColor.a);

    accLen += deltaLen;
    samplePoint += deltaDir;
}
color = accColor;
......

在我的项目中,我让 3D Texture 的 r,g,b,a 的值相同。但我无法获得上述链接之一的结果。你能帮我解决使用 GLSL 的混合问题吗?

4

1 回答 1

2

在预乘 alpha 颜色空间中进行计算是很自然的。它更适合体积现象的发射吸收。对应的方程为:

C = Cs + (1 - As)*Cd
A = 1 - (1 - As)*(1 - Ad) = As + (1 - As)*Ad

尽管可以在非预乘 alpha 颜色空间中进行计算,但它需要除以 alpha 值并且通常更复杂。(您的代码在非预乘中工作并且没有考虑到它......)

因此,要设置您使用的 OpenGL 混合:

glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );

你在着色器中使用这个公式:

accColor = sampleColor + accColor*(1-sampleColor.a);

在生成 3D 纹理时,您还必须考虑到这一点。例如,所有像素R = G = B = A对应于白色雾状物质的纹理,因此您必须在深色背景上查看它。

于 2016-09-19T12:07:44.347 回答