/* simpleFace5.sl * copyright(c) 1995 - dsward@webnation.com * generate a simple face - two eyes and a mouth * Parameters (usually in range 0.0 to 1.0) * Mouth controls - * mouthLevel - placement of center of the mouth * mouthWidth - width of mouth * mouthOffset - vertical offset of edges from center, * positive=smile, negative=frown * mouthOpen - mouth opening size * mouthOpacity - opacity 0=transparent, 1=opaque mouthColor * Eye controls - a pupil, eye and ring * eyeLevel - placement of the eyes * eyeOffset - distance from faceCenter to center of each eye * eyeRadius - radius of the ring around the eye * pupilAngle - angle of pupil from center of eye, typically from 0 to pi*2 * pupilOffset - distance between center of pupil and center of eye * Colors - * mouthColor, pupilColor, eyeColor, ringColor * General controls - * faceCenter - the center for eye and mouth placement * mapCode - 0 = default * 1 = invert s * 2 = invert t * 3 = invert s and t * 4 = swap s and t * 5 = swap s and t, invert s * 6 = swap s and t, invert t * 7 = swap s and t, invert s and t * scaleS - scaling factor for aspect ratio (may be greater than 1.0) * fuzz - anti-aliasing factor * Ka, Kd - the usual meanings for matte shading * * thanks to the Renderman Repository, the Musgrave site and the Steve May site * for information and examples of procedural shaders. */ surface simpleFace5( float mouthLevel = 0.35; float mouthOffset = 0.05; float mouthWidth = 0.5; float mouthOpen = 0.02; float mouthOpacity = 1.0; float eyeLevel = 0.55; float eyeOffset = 0.09; float eyeRadius = 0.05; float pupilAngle = 0.0; float pupilOffset = 0.0; float pupilRadius = 0.025; color mouthColor = color(0, 0, 0); color pupilColor = color(0, 0, 1); color eyeColor = color(1, 1, 1); color ringColor = color(0, 0, 0); float faceCenter = 0.5; float mapCode = 0.0; float scaleS = 2.0; float fuzz = 0.0025; float Ka = 1.0; float Kd = 1.0; ) { color inkColor; float inkOpacity; point eyeCenter; point pupilCenter; float width; point mouthPosition; float mouthPoint, mouthEdge; float halfOpen, halfWidth; float d, d1; float interceptLower, interceptUpper; color currentColor, finalColor; color currentOpacity; point currentPosition; point Nf; float eyeLoop; float invertS = 0; float invertT = 0; float mapST = mapCode; width = eyeRadius / 8; /* width of ring around eye */ /* convert current s,t to a point for distance calculations */ if (mapST < 4.0) { currentPosition = ((1 - s) * scaleS, 1 - t, 0); } else { mapST = mapST - 4; currentPosition = ((1 - t) * scaleS, 1 - s, 0); /* swap s, t mapping */ } /* invert s, t mappings if specified */ if (mapST == 1) invertS = 1.0; if (mapST == 2) invertT = 1.0; if (mapST == 3) { invertS = 1.0; invertT = 1.0; } if (invertS != 0) { setxcomp(currentPosition, 1 - xcomp(currentPosition)); } if (invertT != 0) { setycomp(currentPosition, 1 - ycomp(currentPosition)); } currentOpacity = Os; currentColor = Cs; inkColor = Cs; inkOpacity = 0; /* two eyes */ for (eyeLoop = 0; eyeLoop < 2; eyeLoop = eyeLoop + 1) { if (eyeLoop == 0.0) { /* left eye */ eyeCenter = ((faceCenter + eyeOffset), eyeLevel, 0); } else { /* right eye */ eyeCenter = ((faceCenter - eyeOffset), eyeLevel, 0); } d = distance(eyeCenter, currentPosition); /* check for wrap around */ if (d > eyeRadius + width) { d = distance(((xcomp(eyeCenter) + scaleS), eyeLevel, 0), currentPosition); if (d <= eyeRadius + width) eyeCenter = ((xcomp(eyeCenter) + scaleS), eyeLevel, 0); } if (d > eyeRadius + width) { d = distance(((xcomp(eyeCenter) - scaleS), eyeLevel, 0), currentPosition); if (d <= eyeRadius + width) eyeCenter = ((xcomp(eyeCenter) - scaleS), eyeLevel, 0); } if (d <= eyeRadius + width) { if (d <= eyeRadius) { pupilCenter = eyeCenter; setxcomp(pupilCenter, xcomp(pupilCenter) + (cos(pupilAngle) * pupilOffset)); setycomp(pupilCenter, ycomp(pupilCenter) + (sin(pupilAngle) * pupilOffset)); d1 = distance(pupilCenter, currentPosition); if (d1 <= pupilRadius) { currentColor = pupilColor; inkColor = eyeColor; inkOpacity = smoothstep(pupilRadius - fuzz, pupilRadius, d1); } else { currentColor = eyeColor; inkColor = ringColor; inkOpacity = smoothstep( (eyeRadius - width / 2) - fuzz, (eyeRadius - width / 2) + fuzz, d) - smoothstep( (eyeRadius + width / 2) - fuzz, (eyeRadius + width / 2) + fuzz, d); } } else { currentColor = Cs; inkColor = ringColor; inkOpacity = smoothstep( (eyeRadius - width / 2) - fuzz, (eyeRadius - width / 2) + fuzz, d) - smoothstep( (eyeRadius + width / 2) - fuzz, (eyeRadius + width / 2) + fuzz, d); } } } /* mouth */ halfOpen = mouthOpen / 2; halfWidth = mouthWidth / 2; mouthPosition = currentPosition; /* check for wrap-around */ if (faceCenter - halfWidth < 0.0) { if (xcomp(mouthPosition) + faceCenter + halfWidth > scaleS) { setxcomp(mouthPosition, xcomp(mouthPosition) - scaleS); } } if (faceCenter + halfWidth > scaleS) { if (xcomp(mouthPosition) < scaleS - faceCenter) { setxcomp(mouthPosition, xcomp(mouthPosition) + scaleS); } } if (xcomp(mouthPosition) >= faceCenter - halfWidth) { if (xcomp(mouthPosition) <= faceCenter + halfWidth) { mouthPoint = (xcomp(mouthPosition) - (faceCenter - halfWidth))/ mouthWidth; mouthEdge = mouthLevel + mouthOffset; interceptLower = float spline(mouthPoint, mouthEdge, mouthEdge, mouthLevel - halfOpen, mouthEdge, mouthEdge); if (ycomp(mouthPosition) >= interceptLower) { interceptUpper = float spline(mouthPoint, mouthEdge, mouthEdge, mouthLevel + halfOpen, mouthEdge, mouthEdge); if (ycomp(mouthPosition) <= interceptUpper) { currentColor = Cs; inkColor = mouthColor; inkOpacity = smoothstep(interceptLower - fuzz, interceptLower + fuzz, ycomp(mouthPosition)) - smoothstep(interceptUpper - fuzz, interceptUpper + fuzz, ycomp(mouthPosition)); currentOpacity = 1.0 - (inkOpacity * (1.0 - mouthOpacity)); } } } } finalColor = mix(currentColor, inkColor, inkOpacity); Nf = faceforward(normalize(N),I); Ci = Os * finalColor * ( Ka*ambient() + Kd*diffuse(Nf) ) ; Oi = currentOpacity; }
|
|
|
|
|
|
|