如何使用GLSL在体渲染中进行混合

How to do the blending in Volume Rendering using GLSL?

本文关键字:混合 何使用 GLSL      更新时间:2023-10-16

介绍了使用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纹理的r, g, b, a的值保持相同。但是我无法得到上面一个链接的结果。你能帮我用GLSL解决混合问题吗?

在预乘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对应于一个白色的雾状物质,所以你必须在黑暗的背景下看它。