## Marschner Shader Part I

I decided to write a trilogy (3 posts) explaining, as best as I can, what is discussed in Marschner’s paper “Light Scattering from Human Hair Fibers“.

First of all, I have to warn you that in order to understand this paper you must have some physics and math background, rather than knowing a lot about shaders, things such as Snell’s law or probability density functions being mentioned quite often.

The main advantage of the model proposed by Marschner is that it is based on the actual physical phenomenon that occurs when light passes through hair fibers. So by studying electron micrograph of hair fibers such as this one:

a model has been proposed, where each individual hair fiber is treated as a translucent cylinder, having the following components:

and the components that contribute to a distinct and visually significant aspect of hair reflectance are *R*, *TT *and *TRT*.

*R*– light that bounces off of the surface of the hair fiber toward the viewer.*TT*– light that refracts into the hair and refracts out again toward the viewer.*TRT*– light that refracts into the hair fiber, reflects off of the inside surface, and refracts out again toward the viewer.

The notation used throughout this paper is in tangent space, for the light and viewer position, reported to the current hair fiber.

These are all the variable inputs that are needed for Marschner hair shading model:

*u*– tangent to the hair, pointing in the direction from the root toward the tip.*w*– normal to the hair, pointing toward the viewer (the geometry faces the camera).*v*– binormal to the hair, pointing such that*v*and*w*complete a right-handed orthonormal basis, and are the*v*–*w*is the normal plane.*w*_{i }*w*– direction of camera (viewer)._{ r}*q*– inclinations with respect to the normal plane (measured so that 0 is perpendicular to the hair,_{i ,r }*PI*is*u*, and –*PI*is –*u*).*f*– azimuths around the hair (measured so that_{i ,r }*v*is 0 and*w*is +*PI*).

Several derived angles are used, as well:

*q*=_{d }*q*–_{r }*q*)/2_{i }*;*– the difference angle.*f*=*f*–_{r }*f*); – the relative azimuth_{i }*q*=_{ h }*q*+_{i }*q*)/2; – half angle_{r }*f*= (_{ h }*f*+_{i }*f*)/2; – half angle_{r }

Also, there are some constants parameters for hair fibers, surface and glints that you can find in Table 1 ( page 8 ) from Marschner’s paper.

Having all of this in mind we can approximate the hair model as:

*S* = *S _{R} * +

*S*+

_{TT}*S*

_{TRT,}*S _{p} * =

*M*(

_{p}*q*

_{ i },

*q*

_{r }) x

*N*(

_{p}*q*

_{ d },

*f*

_{ d }) for

*P*=

*R*,

*TT*,

*TRT*.

So it turns out the only thing we need is to find out who M and N are. My next post will do just that.

I’m a bit confused about how to calculate these normals. Could you help me with them?

The basis is the projection of the light direction and the view direction into the normal plane, and then calculate the normal as the sum of these projections.

Currently I’m making this (using the notation of the figure):

vec3 fvTangent = normalize(u);

vec3 fvviewDirection = normalize(Wr);

vec3 fvlightDirection = normalize(Wi);

float dotLightTangent = dot(fvlightDirection, fvTangent);

float dotViewTangent = dot(fvviewDirection, fvTangent);

//Projecting the lightDirection and the viewDirection into the normal Plane:

vec3 LT_P = normalize(fvlightDirection – dotLightTangent * fvTangent);

vec3 VT_P = normalize(fvviewDirection – dotViewTangent * fvTangent);

vec3 Normal = normalize(LT_P + VT_P);

vec3 Binormal = normalize(cross(Normal, fvTangent));

Is that alright? Because the results are really strange.

I actually computed tangents on the CPU (it’s kind of slow). I represented the hair as triangle strips always facing the camera.

The normal is always pointing to the camera (0, 0, -1) and the tangent can be easily computed, being a vector from the root to the tip of a hair strand. The binormal is the cross between normal and tangent (as you already computed).

I reckon if you compute the normal to have the direction from the center of the skull to a point on your hair strand you will get better results.

Cheers,

Alex.