Archive

Archive for April, 2008

Make it translucid! (Part Three)

April 4, 2008 19 comments

Finally the third and final part of this tutorial.

In the first one we focused on the TSM creation, then in the second one we saw the translucency’s multiple scattering contribution. In this final part, we are going to see how to filter the TSM.

The main idea with TSM is that the more the object is “thick”, consequently the less the light will be able to pass through it. Another important idea with TSM is that since light (once penetrated the material) scatters in pseudo-random direction, can leave the object from a point that do not coincides with the point from where the light entered.

In order to simulate the first behaviour, one can simply read the Z coordinate from one vertex in light space (we can call it X_{in}) and then compare with the Z from another point (taken by the camera, but then projected in light space – called X_{out}). Obviously, X_{out} have to be on the same line that ideally connects the light source with X_{in}: this means X_{out}.XY must be equal to X_{in}.XY. Then, the only difference between those two points will lie in the Z value: by arbitrarily choosing X_{out} and projecting it in light space, X_{in} is simply taken by reading the content of the TSM in X_{out}.XY!

TSM thickness idea

That’s what basically has been discussed in the second part. The thickness is computed and used to modulate light intensity in the Rd function: the latter however does not take into account the scattering: it’s like the light enters one point, then it simply “fly” through the object in a straight line, and finally leaves it exactly in the same direction as when entered the material.

This problem is solved in this final part (thus implementing the second idea of TSM) by simulating pseudo-random scattering through filtering. Filtering an image basically consists in taking the whole image and then apply some sort of algorithm to produce the final result. In this case we need to simulate the scattering: simplifying this behaviour in order to make the algorithm real-time friendly is done by taking into account not only the point where the light enters or leaves, but also its neighbours. The more the neighbour are far from the original point, the less they will contribute to the final result.

One can implement filtering by following any schema, even though I’ve found the one from the Dachsbacher’s 2003 paper being of high quality (and a little heavy on the GPU 😛 ). A graphical representation can be seen in the following image, consisting in a 21-samples schema:

TSM Filtering Schema

The code used to implement the filtering is just too long to be posted here, so I decided to post the most important parts of it.

Filtering the TSM

vec4 filter21 (vec4 Xout)

{

   const float d = 1.0/1024.0;

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

   vec4 Xin;

   //

   float v0 = tsm_smoothness*1.0;

   float v1 = tsm_smoothness*2.0;

   float v2 = tsm_smoothness*3.0;

   float k0 = 0.05556; // 1.0/18.0

   float k1 = 0.04167; // 1.0/24.0

   float k2 = 0.04167; // 1.0/24.0

   //

   Xin = Xout;

   finalColor = multipleScattering(Xin,Xout, v0)*k0;

   Xin.y = Xout.y + d;

   Xin.x = Xout.x;

   finalColor += multipleScattering(Xin,Xout, v0)*k0;

   Xin.y = Xout.y + d + d;

   Xin.x = Xout.x;

   //

   […]

   //

   Xin.y = Xout.y + 1.5*d;

   Xin.x = Xout.x – 1.5*d;

   finalColor += multipleScattering(Xin,Xout, v1)*k1;

   Xin.y = Xout.y + 1.5*d;

   Xin.x = Xout.x + 1.5*d;

   finalColor += multipleScattering(Xin,Xout, v1)*k1;

   //

   […]

   //

   Xin.y = Xout.y + 5.0*d;

   Xin.x = Xout.x;

   finalColor += multipleScattering(Xin,Xout, v2)*k2;

   Xin.y = Xout.y;

   Xin.x = Xout.x + 5.0*d;

   finalColor += multipleScattering(Xin,Xout, v2)*k2;

   Xin.y = Xout.y – 5.0*d;

   Xin.x = Xout.x;

   finalColor += multipleScattering(Xin,Xout, v2)*k2;

   Xin.y = Xout.y;

   Xin.x = Xout.x – 5.0*d;

   finalColor += multipleScattering(Xin,Xout, v2)*k2;

   //

   return finalColor*tsmGainFactor;
}


A little bit of gain is added to the final color in order to increase the TSM contribution in the final rendering.

The whole TSM stuff is then simply called in the main function of your GLSL code through filter21(..) . In order to correctly apply the translucency, the TSM’s result color must be added up to the base color. You can further increase the final look by taking into account the clamped-to-zero N dot L product, thus simulating dark zones not directly lit by the light source; or even ambient reflections on the main model..

Thank you for reading my very first tutorial. I know there are some unclear parts: some were not written by purpose, in order to give you greater flexibility. Lastly, excuse me if there are some grammar errors, but I’m Italian and I do not write long posts in English from long time…

Bye!