Home > OpenGL > Make it translucid! (Part Two)

Make it translucid! (Part Two)

The last time we discussed about the approximations needed to compute translucency in real time using TSM. We also created a translucent shadow map and now we are going to use it…

4 – Light diffuses through the material

The light entering the material diffuses in it according to the Rd equation Rd Equation(take a look at the figure on the right).

Thanks to the TSM computed in the last article, we only need two more informations: X_{in} and X_{out}. X_{in} represents the fragment coordinate (in light space) were light enters the material, while X_{out} is the point from which the light leaves the object.

In practice, X_{out} is the fragment coordinate as seen by the camera moving around the object PROJECTED in light space. Once you get the fragment coordinate from the vertex shade, you have it automatically projected in camera (or view) space: since we need to compare this with the data stored in the TSM, we must have them both in the same space (light space). The projection in light space is done by multiplying the view-space-projected coordinate by the camera’s model-view-projection matrix inverse: by doing so we get the object space coordinates, ready to be multiplied by the light’s model-view-projection matrix.

Once we have projected X_{out} in light space, calculating X_{in} is just a matter of shifting X_{out}‘s (x, y) coordinates by a delta (usually the size of a pixel – 1.0/resX and 1.0/res if you want resolution/ratio independency). In this way we can compute translucency simply by filtering the TSM previously calculated. An elegant an also pretty fast solution, if you ask! Of course, this method have some drawbacks: it assumes the object being completely convex so some errors might occur, even though them not being visually important in the majority of cases…

Rd function in GLSL:

vec4 multipleScattering (vec4 Xin, vec4 Xout, float lvl)


   vec4 finalColor = vec4(0.0,0.0,0.0,1.0);

   float e = 2.718281828459;


   //irradiance, depth and normals must account for coordinate shifting!

   vec4 irradIN = texture2D(Irradiance, Xin.xy,lvl);

   vec4 depthIN = texture2D(DepthBuff, Xin.xy,lvl);

   vec4 sNormIN = texture2D(SNormals, Xin.xy,lvl);


   vec4 sigma_a = lightFreqAbsorbed * tsm_freqAbsorption;

   vec4 sigma_s = lightFreqAbsorbed * (1.5-tsm_freqAbsorption);


   vec4 extinction_coeff = (sigma_a + sigma_s);

   vec4 reduced_albedo = sigma_s / extinction_coeff;

   vec4 effective_extinction_coeff = sqrt(3.0 * sigma_a * extinction_coeff);

   vec4 D = 1.0/(3.0*extinction_coeff);


   float fresnel_diff = -(1.440/(refr_index*refr_index))+(0.710/refr_index)+0.668+(0.0636*refr_index);

   float A = (1.0+fresnel_diff)/(1.0-fresnel_diff);


   vec4 zr = 1.0/extinction_coeff;

   vec4 zv = zr + 4.0*A*D;


   vec4 xr = Xin – zr * sNormIN;

   vec4 xv = Xin + zv * sNormIN;


   float dr = length(xr – Xout);

   float dv = length(xv – Xout);


   vec4 f1 = reduced_albedo/(4.0*3.1415296);

   vec4 f2 = zr * (effective_extinction_coeff * dr + 1.0);

   vec4 f3 = pow(vec4(e) , -effective_extinction_coeff * dr) / (extinction_coeff * pow(dr,3.0));

   vec4 f4 = zv * (effective_extinction_coeff * dv + 1.0);

   vec4 f5 = pow(vec4(e), -effective_extinction_coeff * dv) / (extinction_coeff * pow(dv,3.0));


   finalColor = f1 * ( f2 * f3 + f4 * f5);


   return irradIN*finalColor;


  1. junskyman
    March 26, 2008 at 6:09 am

    Great job!
    Expect your third and final part of TSM technique!

  2. eraser85
    April 9, 2008 at 4:49 pm

    thank you, glad to be helpful!

  1. No trackbacks yet.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: