Shaders



simpleFace5 - A procedural shader for a face

 
/* 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;
}
 
 

 


HOME

NEW

LINKS

GALLERY

ARTICLES

PLUG-INS

RENDERMAN

Switch to Frame View




Copyright © 1997 by WebNation
All trademarks are the property of their respective holders