Procedural Eye Ball Shader


This is procedural shader makes simple nurbs sphere into an eye ball.


close up shot of tree face
/*
This shader is modified from Larry Gritz's eyeball.sl
from http://www.renderman.org/RMR/Shaders/LGShaders/index.html
and Matt Breit's irisdistort3.sl shader
from http://www.sfdm.scad.edu/faculty/mkesson/vsfx419/wip/best/fall04/matthew_breit/eyeball.html

modified by Yi-Ming Chu in Oct.2006
*/
void worley(float           ss,
                            tt;
            float            jitters,
                            jittert;
            output float f1;
            output float spos1,
                            tpos1; )
{
    float   sthiscell = floor(ss)-0.5,
            tthiscell = floor(tt)-0.5;
    f1 = 1000;
    uniform float i, j;
    for (i = -1;  i <= 1;  i += 1) {
        float stestcell = sthiscell + i;
        for (j = -1;  j <= 1;  j += 1) {
            float ttestcell = tthiscell + j;
            float spos = stestcell + jitters * (float cellnoise(stestcell, ttestcell));
            float tpos = ttestcell + jittert * (float cellnoise(stestcell+20, ttestcell-80)-2.5);
            float soffset = spos - ss;
            float toffset = tpos - tt;
            //float dist = soffset*soffset + toffset*toffset;
            float dist = toffset*toffset;
            if (dist < f1) {
                f1 = dist;
                spos1 = spos;
                tpos1 = tpos;
            }
        }
    }
    f1 = sqrt(f1);
}

void dimple(float       dent, irissize, ss, tt;
            normal       n;
            output varying float sx, tx;)
{
    normal left = (-1,0,0), up = (0,-1,0);
    float sdiff, tdiff, so, to, amt, len, nu, nl;
    len = abs(tt);
    nu = n.up;
    nl = n.left;
    sx = ss;
    tx = tt;
    amt = (irissize-len) / irissize;
    amt = spline(amt, -0.5, 0 , 1 , 1);
    so = dent * ( amt ) * nl;
    to = dent * ( amt ) * nu;
    if ( len < irissize ) {
        sx += so;
        tx += to;
    }
}

void irisPatternOne( float      irisAmt,
                                normangle,                          
                                pupil,
                                radialperiod,
                                circumperiod,
                                radialjitter,
                                circumjitter;
        output varying float  irisColor;)
{
    float    worleydist = 0, worleys = 0, worleyt = 0;
            
    /* Worley: ss, tt, jitters, jittert, dist, spos, tpos */
    worley(irisAmt * radialperiod, normangle * circumperiod, radialjitter, circumjitter, worleydist, worleys, worleyt);
    
    float irisMidAmt = abs(irisAmt - 0.5) * 2;
    float worleydistSpline = spline(worleydist, -1, 0, 1, 0);
    float worleydistKapow = pow(worleydist, 3);
  
    irisColor = spline(irisAmt, pow(worleydist, 3), pow(worleydist, 2), worleydist, pow(worleydist, 0.667), pow(worleydist, 0.4));
}

surface LGEyeBall_modify(float  Ka = .75,
                                Kd = 0.75,
                                Ks = 0.9,
                                roughness = 0.1;
                        color specularcolor = 1,
                                irisColor = (0.152, 0.443, 0.074),
                                corneaColor = (1.0, 0.831, 0.243),
                                irisinnercolor = (0.086, 0.054, 0.0),
                                eyeballcolor = (1.0, 0.831, 0.243),
                                bloodcolor = (0.137, 0.345, 0.070),
                                pupilcolor = 0;
                        float pupilsize = 0.05,
                                pupilmargin = 0.02,
                                irissize = 0.12,
                                irismargin = 0.025,
                                dent = 0.5,
                                radialperiod = 2,
                                circumperiod = 20,
                                radialjitter = 0.8,
                                circumjitter = 0.3,
                                blursamples = 32,
                                blurRadius = 1.5,
                                bloodshot = 1.0,
                                veinfreq = 8,
                                veinlevel = 8,
                                index = 0;
                        string    envMap = "";
                        float envblend = 0.5;)
{
#define snoise(P) (2*noise(P)-1)
#define MINFILTERWIDTH 1.0e-7
    color Ct;
    point PP, PO;
    float i, turb, newturb, freq, f2;
    float displayed, newdisp;
    color Cball, Ciris;
    float irisstat, pupilstat;
    float bloody, tt;
    float ks, rough;
    float twidth, cutoff;
    normal Nn = normalize(N);
    normal Nf = faceforward (normalize(Nn), I);;
    vector V = -normalize(I);
    float  irisAmt = 1, irisMidAmt,
            normangle, angle, gAngle = 0, gNormAngle = 0, gIrisAmt = 0,
            anglestep = 140, gRadius = 0, shade = 0,
            irisVal = 0, irisVal2 = 0, irisVal3 = 0,
            irisBlurVal = 0, irisBlurTotal = 0,
            irisNeg = 0, irisMasked = 0, irisHeight = 0;
    /* Calculate an appropriate filter width for antialiasing */
    twidth = max (abs(Du(t)*du) + abs(Dv(t)*dv), MINFILTERWIDTH);
    PO = transform ("object", P) + index;

    tt = 1-t;
    irisstat = smoothstep (irissize, irissize+twidth, tt);
    pupilstat = smoothstep (pupilsize, pupilsize+twidth, tt);
    bloody = bloodshot * (smoothstep (-irissize, 2.5*irissize, tt));

    if (irisstat * bloody > 0.001) {
        turb = bloody;  freq = veinfreq;
        displayed = 0;
        for (i = 1;  (i <= veinlevel) && (turb > 0.1);  i += 1) {
            newturb = 1 - abs (snoise(PO*freq + point(0, 0, 20*freq)));
            newdisp = pow (smoothstep (.85, 1, newturb), 10);
            displayed += (1-displayed) * newdisp * smoothstep (.1, .85, turb * turb);
            turb *= newturb;
            freq *= 2;
        }
        Cball = mix (eyeballcolor, bloodcolor, smoothstep(0,.75,displayed));
    } else {
        Cball = eyeballcolor;
    }

    Ciris = mix(irisColor, corneaColor, smoothstep(irissize*.8, irissize, tt));
    /* If we're somewhere in the iris, calculate the iris pattern
    */
    if ( irisstat == 0 && pupilstat != 0) {
        float sx, tx,
                lenx,
                leng;
    
        float sa = mod(s * 5, 1);
        dimple(dent, irissize, sa, tt, Nn, sx, tx);
        lenx = abs(tt);
        angle = atan(tt, 0.5 - sx);
        normangle = 0.5 + angle * (1/(2 * PI));
        irisAmt = ( tt - pupilsize ) / ( irissize - pupilsize -irismargin);
        irisMidAmt = 2 * (abs(irisAmt - 0.5));
        irisPatternOne( irisAmt, normangle, pupilsize, radialperiod, circumperiod, radialjitter, circumjitter, irisVal);
        irisVal = spline(irisAmt, pow(irisVal, 3), pow(irisVal, 2), irisVal, pow(irisVal, 0.667), pow(irisVal, 0.4));
        irisVal2 = spline(irisAmt, 0, irisAmt, pow(irisVal, 3), irisVal, irisAmt, 1);
        irisPatternOne( irisAmt, normangle, pupilsize, radialperiod, circumperiod*2.5, radialjitter, circumjitter*0.5, irisVal3);

        for(i = 0; i < blursamples; i+= 1) {
            gAngle = anglestep * i;
            gRadius = blurRadius * pow( ( i / blursamples ), 0.75 ) * 0.01;
            float tg = tx + sin(gAngle)*gRadius;
            gIrisAmt = ( 1 - tg - pupilsize ) / ( irissize - pupilsize );
            gAngle = atan( 1 - tg, sx );
            gNormAngle = 0.5 + gAngle * ( 1 / ( 2 * PI ) );
            irisPatternOne( gIrisAmt, gNormAngle, pupilsize, radialperiod, circumperiod, radialjitter, circumjitter, irisBlurVal);
            irisBlurTotal += irisBlurVal;
        }

        irisBlurVal = irisBlurTotal / blursamples;

        irisNeg = 0.5 * ( ( 1 - irisBlurVal ) + irisVal );
        irisMasked = smoothstep(0.565, 0.575, (irisNeg + irisAmt * 0.15 + clamp(irisAmt - 0.7, 0, 0.2) ) );
        irisHeight = (irisMasked*.1);
        
        if (irisMasked == 0) {
            shade = smoothstep (0.4, 0.565, irisNeg);
            Ciris *= (Ciris + irisVal3) * 0.5;
        } else {
            shade = 0;
            Ciris = (1-irisNeg)*irisColor;
        }

        shade *= 1-irisMidAmt;
        if (tt - pupilsize <= pupilmargin) {
            /* Caculate the pattern in the inner edge of the iris */
            Ciris = spline( abs( tt - pupilsize ) / pupilmargin, pupilcolor,pupilcolor, irisinnercolor, Ciris,irisinnercolor);
            irisHeight = spline( abs ( tt - pupilsize ) / pupilmargin, 0, 0, irisHeight, irisHeight);
        } else if (tt-irissize <= irismargin) {
            /* Caculate the pattern in the outer edge of the iris */
            Ciris = spline( ( abs( tt - irissize )/ irismargin ), Cball, corneaColor, corneaColor*Ciris/3,Ciris, Ciris, Ciris);
            irisHeight = spline( ( abs( tt - irissize ) / irismargin ), 0, 0, irisHeight, irisHeight);
        } else {
            Ciris *= irisColor;
        }
    }

    
    
    /* OK, now calculate a surface texture color (Ct) */

    Ct = mix (Ciris, Cball, irisstat);
    Ct = mix (pupilcolor, Ct, pupilstat);
    
    /* Make the eye a little glossier on the iris and pupil */
    ks = Ks * (1+2*(1-irisstat));
    rough = roughness * (1 - .75*(1-irisstat));

    if(envMap != "") {
        vector Rray = vector transform("world", point "world" (0,0,0) + reflect(-V,Nf));
        Ct = mix(Ct, color environment(envMap, Rray), envblend);
    }

    color spec1 = ks * specular(Nf, V, rough);

    point pDu = P - Nn * irisHeight * 0.05;
    normal pNn = calculatenormal(pDu);
    normal pNf = faceforward (normalize(pNn), I);

    color diffColor = Kd * diffuse(pNf)*(1-shade);
    color ambiColor = Ka * ambient();
    color spec = specular(pNf, V, rough);
    //float spec2 = comp(spec, 0);
    //spec2 += smoothstep(0.1, 0.4, spec2);
    color specColor = max(spec1,spec)*specularcolor;
    Oi = Os;
    Ci = Oi * Ct*(ambiColor + diffColor) + specColor;
}

eye 1 eye 2