1

This introduces the method of Volume Rendering using obsolete API of OpenGL. But now, I want to complete the Volume Rendering using GLSL and I have finished some parts of it. My question is how to do the blending. In the above link, blending is completed by the following codes:

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

But how can I finish the blending using GLSL?

I tried to using the following equation:

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

Cs is the color of source object. Cd is the color of the destination object. As is the alpha of the source object. And my code in fragment shader is as following:

......
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;
......

In my project, I let the value of r, g, b, a of the 3D Texture to be the same. But I cannot obtain the result of the one of the above link. Can you help me to solve the blending problem using GLSL?

genpfault
  • 51,148
  • 11
  • 85
  • 139
Hurricane
  • 31
  • 3
  • Blending is done by HW itself not by shaders in GLSL so you should leave the `glEnable` and `glBlendFunc` in your GLSL project as is and output from fragment shader only the color to blend not process the blending equation. That would work only if you do each Blended primitive as separate render pass to/from texture which is insanely slow ... unless the count of primitives is not high. – Spektre Sep 18 '16 at 08:08
  • For example see [my simple Atmospheric scattering shader in GLSL](http://stackoverflow.com/a/19659648/2521214) which combines native Blending of gfx card and GLSL shaders (although in 2 pass rendering but that has nothing to do with blending) – Spektre Sep 18 '16 at 08:13
  • 1
    This is raycasting, and blending is indeed part of the algorithm. – kaerimasu Sep 18 '16 at 11:55
  • @kaerimasu: Can you tell me more details about blending? Thank you! – Hurricane Sep 19 '16 at 07:06
  • @Spektre: Thank you! – Hurricane Sep 19 '16 at 07:06

1 Answers1

2

It is natural to do the computations in premultiplied alpha color-space. It fits better with the emission-absorption of the volumatic phenomena. The corresponding equations are:

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

Although it is possible to do the calculations in non-premultiplied alpha color-space, it would require division by the alpha values and be generally more complicated. (Your code works in non-premultiplied and does not take it into account...)

So to set-up the OpenGL blending you use:

glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );

and you use this formula in the shader:

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

You also have to take this into account when generating your 3D textures. For example a texture where for all pixels R = G = B = A corresponds to a white foggy substance, so you have to look it over dark background.

Yakov Galka
  • 70,775
  • 16
  • 139
  • 220