Alright, here it is. The big one. My skin shader. Or as I like to refer to it - my "Adjustable Light Curve Shader."
Shader_Donze_Skin.fx
Shader_Donze_Skin_NoShadows.fx
So, this has all the same features as the other shaders, but with lots of cool new stuff. And because its some pretty heavy stuff, I've made a little tut to help you all understand whats going on under the hood.
To start off with, you need a very basic understanding of how realtime lighting is calculated. Take the following example. A simple sphere with a single spot light off to the right:
Notice the nice smooth shading. The brightness of any given point along the surface is calculated by finding the Dot Product of the light vector and surface normal vector. You don't need to know what that means or how it works, but its good to know what the result is. The Dot Product will yield a value between -1 and +1. It will be -1 for normals facing directly away from the light... +1 for normals facing directly toward the light..... 0 for perfectly perpendicular normals....so on and so forth. It all sounds super complicated, but here's a simple illustration to help you visualize:
Right in the middle, there is a 0 value, or what I call the "dark point," where the color reaches complete black. On the end facing the light, you have a +1 value, or what I call the "light point," where the color reaches complete white (actually, at this point it will be the full color of the diffuse, which in this case is white). This shader simply moves where those two points are. So, by default, the Light Point is at +1 and the Dark Point is at 0. If we slide the Light Point down to 0.25, we get the following result:
If we move the Dark Point forward to 0.75, you get this result:
By moving the Dark Point back, to say, -0.75, you get a nice pseudo sub surface look, similar to the Half Lambert function of my previous shaders but perhaps a bit better:
Normally, the falloff between the Dark and Light points is a linear curve. However, I have made that curve customizable. Its a simple x^y function. 1.0 is the default. By going lower than 1.0, you can make the light more harsh, falling off rapidly as it approaches the Dark Point:
Going higher than 1.0 will make the falloff from the Light Point steep, but then gradually fade into the Dark Point.
Ok, now this is where it gets interesting. We can add a sub-surface map to blend into the surface diffuse. There are two settings here. Lets start with Color Bleed Level. This is simply how much the subsurface map shows through (my subsurface map is a simple checkerboard pattern).
By default, this map will get blended in between +0.5 and -0.5. By adjusting the Color Bleed Offset, we can move where the blending starts.
Lastly, by creating an alpha channel in your subsurface map, you can control how much all of these settings affect your model. Here I've painted some black wavy lines into the Alpha. Those areas are now no longer affected by
any of these settings (instead they are shaded like the standard shader). This can be a grey scale to get varying amounts of subsurface effect.
Well, thats a lot to digest all at once, so please ask questions if you have them. And please let me see what you come up with. There are alot of variables and different ways of tweaking things, so I'm really interesting in the creative ways you people can exploit this shader.