Friday, October 08, 2010

Transparency Shader

Well, it was long pending & I always wanted to do it. Transparent objects! But other equally important things kept me occupied for long long time. As an update, am working on my small DirectX framework & Right now am working on Particle engine & Shader engine for the same. Thats for the update, now back to transparency.
The hunt for transparency was long due... after reading a lot about it via google, I came to know that , to achieve effect something as close as transparency, I need to make sure three things are done correctly. Reflection, Refraction & ofcourse Fresnel parameter, well there is something known as Dispersion phenomenon as well, but so far I have not considered that in my shader.
So, reflection part was pretty straight forward, all I did was use a cubemap to create a reflecting scene onto a geometry. Simple cubemap lookup did the job. Now for the refraction part, right from the school snell’s law holds the key. After going through the basics, I decided to go for HLSL intrinsic function “refract” as it does the trick. Though there are arguments about having our own implementation of the refract function, but things were 50-50, I decided to stick with intrinsic function just for the quick result sake. So, the refracted ray is passed to the pixel shader which does the lookup on the Cubemap to create the refraction effect.

So, as you can see in the output above, basic reflection & refraction gives decent results. But something is missing! I mean, the look and feel is just not there, it feels as more of plastic geometry than glass. This lead to adding a Fresnel parameter into the shader. So what is this Fresnel parameter all about? Well, Fresnel factor controls amount of reflection & amount of refraction based on the viewing angle! So, if you have noticed in real life, If we stand in a pool of water(CLEAN) , we can see our legs... but as the viewing angle changes the transparency goes on reducing & reflection increases. So, basically Fresnel term math makes sure this realism is achieved as close as possible. Though there are more complicated & accurate formulas for Fresnel term approximations, I decided to stick to most commonly used Fresnel term approximation.
So, after addition of Fresnel parameter & other controlling parameters this is what I got. It looks more real than the previous effect.

Next obvious thing to add into the shader is Chromatic Dispersion. Different wavelengths travel along an optical medium at different speeds. Wavelengths reach the end of the medium at different times, causing the light pulse to spread. In short, when we see any glass object , we see hint of rainbow spreading over the object, which is unique for that particular object. The distribution of a rainbow over the object depends on material properties which ultimately affects the wavelength of light travelling through the material. For more info, one can Google up the term Chromatic Dispersion, and there is tons of information available. 

Now for the shader part, exact simulation of Dispersion is possible to an extent, depending on the light & material parameters taken into consideration by the shader.But, for real time purpose, rainbow texture does the trick! All we have to is, sample a rainbow texture & spread it over the object logically. Here, to be honest, what I found out is Logically means, spread it the way you want till desired result is obtained. In my shader, I used Eye vector as a reference & spread it based on the angle between an Eye vector & surface normal.
Here is the Refraction Shader with Faked chromatic dispersion :)

I suppose, now it looks even better than the previous version without chromatic dispersion taken into consideration. Please feel free to comment on the effect in both positive & negative in order to improve my shader further. As always, Shader code is available on request.

Thats it for the time being!


SandSekh said...

Wow - this is gorgeous.

DoD said...

Thanks Sandeep :)