Human & animal skin, wax, carpaint, jelly, marble, bubble soap films, rain puddles on the ground : difficult things to render in realtime 3D.
Skin are made of several layers (dermis, epidermis…), carpaint is made of clearcoat, on top of flakes and metallic paint. Soap creates thin films ; water layer is very thin compared to the ground it’s sitting on. Wax and jelly are non-homogenous (somewhat anisotropic) media…
You can of course model it with geometry but you are still going to have problems related to the rendering of the interplay of light with the material.
SRealtime 3D shaders are concerned with the relationship of light hitting a specific pixel and leaving it. It’s hard to render the specific quality of light attenuation inside the various layers of a material.
Christopher Oat, when working at ATI Research (before their acquisition by AMD) made some publications on the rendering of layered media (« Rendering Semi-Transparent, Layered Media » – ShaderX 3: Advanced Rendering with DirectX and OpenGL, Wolfgang Engel, Ed., Charles River Media, 2004) or (« Rendering Gooey Materials with Multiple Layers » – ACM SIGGRAPH Course notes, course 26, Advanced Real-Time Rendering in 3D Graphics and Games, pp. 65-79, 2006).
The media is modeled as two layers ontop of one another. When light hits the outer layer, it interacts with the geometry (and the normal map).
When light enters the outer layer, it travels along the media and is scattered and therefore attenuated.
Oat suggests using a Poisson Disc blur filter to sample the inner layer. This filter effectively blur the underlying layer (the amount is depending on the thickness of the layer).
This blurred layer is composed with the outer one by using an opacity map (a more physically based approach would use the IOR of the outer layer, involving Fresnel’s law).
Since the light vector is traveling inside the outer layer, the model should exhibit some parallax effect depending on outer layer thickness.
By working in tangent space, the light vector is reflect along the surface, and the inner layer is sampled accordling with the parallax.
However that model isn’t used by the usual game engine big players (Unreal, Unity and CryEngine). (At least, after extensive research we didn’t find any proof of it). Here’s some examples of what kind of carpaint you can create with Unreal (
When creating carpaint, you can try some multi BRDF blending via a map or a Fresnel factor (wich is already an improvement regarding simple texture based rendering (diffuse+normal+spec)) :
The realtime 3D shader
Some part of the shader have been ported to Unity, to demonstrate what is possible when trying to render layered material with that engine.
You can find here some screenshots, directly from the editor (warning, programmer’s art ahead!)
The texture used for the demo helps to bring some highlights on the various interesting effects.
You can see on Figure 3 the configuration of our scene : the plane on the left is rendered with the Standard Unity Shader (GGX BRDF).
The right plane is more ‘classic’ : diffuse (albedo) + normal map. However we can see the underlying layer through the ‘holes’ of the opacity map.
When the thickness of the outer layer increases, you can see on Figure 4 the increasing bluriness of the inner layer.
The fresnel effect states that the transparency of a media is related to the incident angle of the light when entering the media, coupled with the IOR.
At the time of the writing of the original shader (Oat’s work), the evaluation of a Fresnel formula was too costly to do it in realtime, while dedicating GPU ressources for every graphical aspect of the game concurrently. It was then done by correlating the dot product of the normal with the incident vector.
You can see on the Figure 5 screenshot the transparency of the media diminishing with the parallax effect.
On the screenshots, I disabled the specular envmap reflection, to have a better look at the parallax/blurring phenomenon. If you activate it, you’ll have that (in the original paper, the specular contribution is brutally added to the diffuse component) :
If you try your hand at Oat papers, remember that the vectors are expressed in Tangent Space, not Object Space !
In the next few iterations of the shaders, we will see some simple improvements that can be added to this shader (remember, everything was made at that time before the introduction of BRDF in realtime rendering…)