I'm currently tinkering around with some subtil surface finishes and want to
see what comes out of it.
Well, I've implemented the double attenuation you get when light enters an
object with an IOR != the IOR of the surrounding material. Roughly speaking,
if the IOR of two adjacent materials are different, there will be attenuation
whenever the light enters any of them as can be computed from the Fresnel
equations. With the attenuated transmitted light inside the object getting
scattered whatsoever, it may also leave the object at some point and will as
such undergo an additional attenuation when crossing the material interface
again producing a double attenuation, which is what I've implemented for the
diffuse component;
IOR 1.0
IOR 1.2 (single attenuation)
IOR 1.2 (double attenuation)
With an IOR of 1 the light will pass unaltered, no attenuation. However, with
an IOR > 1 the light entering and leaving the interface gets attenuated.
What gives?
Better energy preservation and better matching of specular reflected light.
With an IOR > 1 you always get some specular reflection from somewhere else
(not computed in the scene above). With double attenuation the specular
(surface) reflection of the object and diffuse (body) reflection will match
up much better, esp. at grazing where the specular components dominate the
diffuse one producing more pleasing surface finishes. So basically, reflection
mapping should look more stunning that way, which is what I will try next.
The implementation is rather simple. The attenuation of the light entering is
computed with classic Fresnel, Fr_outside, with the diffuse component
attenuated by (1-Fr_outside). See second image above. To get the double
attenuation you simply compute Fresnel, Fr_inside, but now from the inside and
multiply the diffuse component with (1-Fr_inside). Hence, the total
attenuation is (1-Fr_outside)*(1-Fr_inside). See third image above.
The attenuation of the light leaving the interface from inside of the object I
computed simply as follows;
Code:
// wrt vacuum, i.e. IOR 1.0
T = refract(-I, N, 1.0f/ior_n);
R = reflect(-T, N);
Fr_inside = fresnel(acosf(dot(R,N)), ior_n, 1.0f);
That's a simplification because I assume everything happens right at the
surface. So we compute the refracted ray, T, as usual and simply reflect it
at the normal at the same point and then compute the Fresnel attenuation but
now from the "inside" of the object looking out through the reflected ray R.
The amount of light leaving the object is the part transmitted through, which
is (1 - Fr_inside).
Well, if you actually want to a have a thicker transparent layer with the
texture of the object showing refraction effects you can use the angle the
refraction ray make with the normal and the depth of the layer to compute an
texture offset. This should give some pretty cool effects, I guess.
I will try some reflection mapping next and attenuate it with Fr_outside based
on the same IOR of the object and view angle, which basically should produce
some more pleasing reflections esp. towards grazing.