S&H Hair shader update for Pixar RMS2

A few months ago we had a new working version at my office it's just been too hectic here to test. David Lin was kind enough to come around the office Saturday and tested it works with RMS2 env lights.
BTW our inhouse version has automatic baking and various other tweaks using RMS, this version is the "bare bones" version so you can modify it for your needs.
If you need some more advanced things shoot me an email, sometimes I'm available.
Code posted with Joe's permission.

/*
Shave and a Haircut emulation shader (c) 2010 Joe Alter, Inc
by Joe Alter
Illuminance fixes by Bernard Edlington, updated by David Lin
*/

#include "pxslRayUtil.h"

surface Shave (float Ka = 0,
SHAVEambdiff = .6,
SHAVEspec = .35,
SHAVEgloss = .07,
SHAVEopacity = 1.0,
SHAVEselfshad = 1,
coneangle = 30; /* note to Joe: this parameter should be converted from the SHAVEgloss primvar */
color SHAVEspec_color = 1,
rootcolor = 1,
tipcolor = 1;) {

normal Ns = pxslUtilShadingNormal(N);
normal Nn = normalize(N);
vector In = normalize(I);

vector T = normalize (dPdv); /* tangent along length of hair */
vector V = -normalize(I); /* V is the view vector */
float df2 = 0, diffterm = 0;
color Cspec = 0, Cdiff = 0; /* collect specular & diffuse light */
color mixed = 1;
float rawspec;
color Cl2;
float vt, tl;

// Direct illumination
illuminance ("-environment", P, Ns, 1.57, "lightcache", "reuse")
{
float sq2;
df2=(T.normalize(L));
df2*=df2;
df2=1.0-df2;
if (df2<0) df2=0;
if (df2>0) df2=sqrt(df2);
diffterm=df2; /* diffuse */
if (diffterm<0) diffterm=0;

vt = V.T;
sq2=1.0-vt*vt;
if (sq2<0) sq2=0;
if (sq2>0) sq2=sqrt(sq2);
rawspec = df2* sqrt( 1.0- vt * vt ) - (normalize(L). T ) * vt; /* raw specular */
if (rawspec<0) rawspec=0;

diffterm=(1.0-SHAVEambdiff)+diffterm*SHAVEambdiff; /* limits gamut of diffuse term */
Cl2=Cl*SHAVEselfshad+(1-SHAVEselfshad); /* limits the gamut of shadowing */
Cspec += Cl2*pow( rawspec, 1.0 / ( 3.0 * ( .101 - SHAVEgloss ) ) )*.5; /* specular exponent x illumination */
Cdiff += Cl2*diffterm; /* diffuse x illumination */
}

// illumination from environments
// this will include both environment and indirect illum
float occl = 0;
color indiff = 0;
color envCol = 0;
color specCol = 0;

shader envlights[] = getlights("category", "environment");
uniform float i, n = arraylength(envlights);
vector envdir = reflect(In, Nn);
float angle = radians(coneangle);

for(i=0 ; i < n ; i+=1) // Loop through each envlight
{
//Diffuse contributions from EnvLight
envlights[i]->diffuseIllum(P, Ns, Nn, indiff, envCol, envdir, occl);
color env = envCol * (1-occl);
Cdiff += env;
Cdiff += indiff;

//Specular contributions from EnvLight
envlights[i]->specularIllum(P, envdir, angle, specCol);
Cspec += specCol;
}

mixed = mix( rootcolor, tipcolor, v );
Oi = Os*SHAVEopacity;
Ci = Oi * Cs * mixed* (Ka*ambient() + Cdiff) + ( Cspec * SHAVEspec_color *SHAVEspec); /*sum terms and premult color x opac */
}

2 Comments

  • February 3, 2011 at 1:12 AM | Permalink

    Hello!
    I'm just trying to get good hairs and fur with shave and haircut 5.5 v5 and RenderMan Studio 3.0.1
    I have some problems with lights.
    When I use Enviroment Lights - colorbleeding render doesn't get any changes.
    But when I use Maya's fur it works great with colorbleeding!
    how I can use your shave.sl?
    Is it helps me?
    Do I need shave.slo?

  • February 3, 2011 at 1:12 AM | Permalink
    This comment has been removed by the author.