DIRECTORY Imager, ImagerColor, ImagerColorPrivate, RealFns, Shading, SV3d, SVModelTypes, SVVector3d; ShadingImpl: CEDAR PROGRAM IMPORTS ImagerColor, ImagerColorPrivate, RealFns, SVVector3d EXPORTS Shading = BEGIN Color: TYPE = Imager.Color; Vector3d: TYPE = SV3d.Vector3d; Point3d: TYPE = SV3d.Point3d; LightSource: TYPE = SVModelTypes.LightSource; LightSourceList: TYPE = SVModelTypes.LightSourceList; ExtractRGB: PUBLIC PROC [color: Color] RETURNS [r,g,b: REAL] = { rgb: ImagerColor.RGB; rgb _ ImagerColorPrivate.RGBFromColor[NARROW[color]]; r _ rgb.R; g _ rgb.G; b _ rgb.B; }; NormalizeRGB: PUBLIC PROC [r,g,b: REAL] RETURNS [color: Color] = { scaleFactor: REAL; scaleFactor _ MAX[r,g,b]; IF scaleFactor > 1.0 THEN { r _ r/scaleFactor; g _ g/scaleFactor; b _ b/scaleFactor; }; color _ ImagerColor.ColorFromRGB[[r,g,b]]; }; CollimatedSpecularRadiance: PUBLIC PROC [surfaceNormal: Vector3d, lightSource: LightSource, albedo: REAL _ 1] RETURNS [radiance: REAL] = {radiance _ 180}; DiffuseReflectance: PUBLIC PROC [surfaceNormal: Vector3d, surfacePt: Point3d, surfaceColor: Color, lightSources: LightSourceList] RETURNS [r, g, b: REAL] = { OPEN SVVector3d; intensity: REAL; surfaceToLight, surfaceClr, surfaceClrTemp, liteClr, ambientClr: Vector3d; colorSum: Vector3d _ [0,0,0]; [r, g, b] _ ExtractRGB[NARROW[surfaceColor]]; IF lightSources.first.type # ambient THEN ERROR; [ambientClr[1], ambientClr[2], ambientClr[3]] _ ExtractRGB[NARROW[lightSources.first.color]]; surfaceClr _ [r,g,b]; surfaceNormal _ Normalize[surfaceNormal]; -- all vectors must be kept normalized IF ambientClr[1] > 0.0 OR ambientClr[2] > 0. OR ambientClr[3] > 0.0 THEN colorSum _ ElementwiseProduct[surfaceClr, ambientClr]; -- initialize colorSum. FOR lite: LightSourceList _ lightSources.rest, lite.rest UNTIL lite = NIL -- for each light source DO [r, g, b] _ ExtractRGB[NARROW[lite.first.color]]; liteClr _ [r,g,b]; surfaceToLight _ Normalize[Sub[lite.first.position, surfacePt]]; intensity _ DotProduct[surfaceNormal, surfaceToLight]; -- lambertian reflectance IF intensity < 0.0 THEN intensity _ 0.0; -- no negative reflectance allowed surfaceClrTemp _ Scale[surfaceClr, intensity]; -- scale surface color by reflectance surfaceClrTemp _ ElementwiseProduct[surfaceClrTemp, liteClr]; colorSum _ Add[colorSum, surfaceClrTemp];-- sum reflectances for all lights ENDLOOP; r _ colorSum[1]; g _ colorSum[2]; b _ colorSum[3]; }; DiffuseAndSpecularReflectance: PUBLIC PROCEDURE [eyePoint: Point3d, surfaceNormal: Vector3d, surfacePt: Point3d, surfaceColor: Color, lightSources: LightSourceList] RETURNS [r, g, b: REAL] = { OPEN SVVector3d; intensity, hilitValue: REAL; surfaceToLight, surfaceToEye, surfaceClr, surfaceClrTemp: Vector3d; ambientClr, finalClr, halfAngle, liteClr: Vector3d; colorSum: Vector3d _ [0,0,0]; [r,g,b] _ ExtractRGB[surfaceColor]; IF lightSources.first.type # ambient THEN ERROR; [ambientClr[1], ambientClr[2], ambientClr[3]] _ ExtractRGB[lightSources.first.color]; surfaceClr _ [r,g,b]; surfaceNormal _ Normalize[surfaceNormal]; -- all vectors must be kept normalized IF ambientClr[1] > 0.0 OR ambientClr[2] > 0. OR ambientClr[3] > 0.0 THEN colorSum _ ElementwiseProduct[surfaceClr, ambientClr]; FOR lite: LightSourceList _ lightSources.rest, lite.rest UNTIL lite = NIL -- for each light source DO [r,g,b] _ ExtractRGB[lite.first.color]; liteClr _ [r,g,b]; surfaceToLight _ Normalize[Sub[lite.first.position, surfacePt]]; -- vector from surface to light source intensity _ DotProduct[surfaceNormal, surfaceToLight]; -- lambertian reflectance IF intensity < 0.0 THEN intensity _ 0.0;-- no negative reflectance allowed surfaceClrTemp _ Scale[surfaceClr, intensity];-- scale surface color by reflectance surfaceClrTemp _ ElementwiseProduct[surfaceClrTemp, liteClr]; surfaceToEye _ Normalize[Sub[eyePoint, surfacePt]]; halfAngle _ Normalize[Add[surfaceToLight, surfaceToEye]]; hilitValue _ DotProduct[surfaceNormal, halfAngle]; -- specular reflectance IF hilitValue < 0.95 THEN hilitValue _ 0.0 ELSE hilitValue _ RealFns.Power[hilitValue, 100]; -- all surfaces have same specular power IF hilitValue > .01 THEN -- add in light source color for highlight finalClr _ Add[surfaceClrTemp, Scale[Sub[liteClr, surfaceClrTemp], hilitValue]] ELSE finalClr _ surfaceClrTemp; colorSum _ Add[colorSum, finalClr];-- sum reflectances for all lights ENDLOOP; r _ colorSum[1]; g _ colorSum[2]; b _ colorSum[3]; }; Power: PRIVATE PROC [base: REAL, exponent: NAT] RETURNS [baseToExp: REAL] = { baseToExp _ 1.0; FOR i: NAT IN [1..exponent] DO baseToExp _ baseToExp * base; ENDLOOP; }; SimpleFilmIrradiance: PUBLIC PROCEDURE [radiance: REAL, omegaAperture: REAL] RETURNS [irradiance: REAL] = { irradiance _ radiance*omegaAperture; }; SolidAngle: PUBLIC PROCEDURE [surfacePoint: Point3d, areaAperture: REAL] RETURNS [omegaAperture: REAL] = { fromApertureToSurface: Vector3d _ surfacePoint;-- same as surfacePoint because aperture at [0,0,0] r: REAL _ SVVector3d.Magnitude[fromApertureToSurface]; cosTheta: REAL _ -fromApertureToSurface[3]/r; omegaAperture _ (areaAperture*cosTheta)/(r*r); }; SpecFilmIrradiance: PUBLIC PROCEDURE [surfaceNormal: Vector3d, lightSource: LightSource, albedo: REAL _ 1, omegaAperture: REAL] RETURNS [irradiance: REAL] = { radiance: REAL _ CollimatedSpecularRadiance[surfaceNormal,lightSource,albedo]; irradiance _ SimpleFilmIrradiance[radiance,omegaAperture]; }; END. ΨFile: ShadingImpl.mesa Last edited by Bier on May 31, 1984 3:52:21 pm PDT Author: Eric Bier on February 18, 1987 6:27:52 pm PST Contents: A camera model for shading surfaces, given surface type, lighting conditions and aperture size. No attempt is made to provide finite depth of field or other artifacts of a real camera. Frank Crow added Utah-style highlights on September 23, 1982 12:22 pm Scale sum to max. value to avoid desaturation at bright spots. Collimated light source at lightSource. Specular surface with given albedo oriented by given surfaceNormal. vector from surface to light source scaleFactor _ MAX[colorSum[1], colorSum[2], colorSum[3]]; Scale sum to max. value to avoid desaturation at bright spots. IF scaleFactor > 1.0 THEN colorSum _ Scale[colorSum, 1.0/scaleFactor]; completeColor _ ImagerColor.ColorFromRGB[[r,g,b]]; ambientScalar _ DotProduct[surfaceNormal,[0,1,0]]; -- overhead ambient light scaleFactor _ MAX[colorSum[1], colorSum[2], colorSum[3]];-- scale sum to max. value to avoid IF scaleFactor > 1.0 THEN colorSum _ Scale[colorSum, 1.0/scaleFactor];-- desaturation at bright spots completeColor _ ImagerColor.ColorFromRGB[[r,g,b]]; Solid angle is just Acos(theta)/r^2, where r is the distance from surface point to aperture (at [0,0,0], A is the areaAperture, and theta is the angle between the aperture normal [0,0,-1] and the line from surfacePoint to [0,0,0]; A convenience routine which combines CollimatedSpecularRadiance and SimpleFilmIrradiance. Κξ– "cedar" style˜Iheadšœ™Jšœ2™2Jšœ5™5JšœΓ™ΓJšœE™EJ˜J˜šΟk ˜ JšœZ˜Z—J˜šœ  ˜Jšœ5˜™>—Lšœœ˜šœœ˜Lšœ8˜8L˜—Lšœ*˜*L˜—˜L˜—š žœœœ=œœ œ˜šLšœl™l—L˜š žœœœcœ œ˜Lšœ ˜Lšœ œ˜LšœJ˜JLšœ˜L˜Lšœœ˜-Lšœ#œœ˜0Lšœ;œ˜]Lšœ˜Lšœ*Οc&˜PL˜šœœœœ˜ILšœ7 ˜N—L˜Lšœ6œœ ˜bš˜Lšœœ˜1Lšœ˜Lšœ@˜@Lšœ#™#Lšœ8 ˜QLšœœ "˜KLšœ/ %˜TLšœ=˜=Lšœ˜Lšœ) "˜K—Lšœ˜L˜šœœ(™9Lšœ>™>—Lšœœ-™FLšœ˜Lšœ˜Lšœ˜Lšœ2™2Lšœ˜L˜—š žœœ œvœ œ˜ΑLšœ ˜Lšœœ˜LšœC˜CLšœ3˜3Lšœ˜L˜Lšœ#˜#Lšœ#œœ˜0LšœU˜ULšœ˜Lšœ* &˜PL˜LšœL™Lšœœœœ˜ILšœ6˜6—L˜Lšœ6œœ ˜bš˜Lšœ'˜'Lšœ˜LšœA &˜gLšœ8 ˜QLšœœ "˜JLšœ. %˜SLšœ=˜=Lšœ˜Lšœ3˜3Lšœ9˜9Lšœ4 ˜KLšœœ˜+Lšœ/ (˜[Lšœ˜Lšœ˜šœ *˜1LšœO˜O—Lšœ˜!Lšœ˜Lšœ# "˜E—Lšœ˜L˜Lšœœ( #™\Lšœœ- ™eLšœ˜Lšœ˜Lšœ˜Lšœ2™2Lšœ˜—L˜L˜šžœœœœ œœ œ˜MLšœ˜Lšœœœ˜Lšœ˜Lšœ˜Lšœ˜L˜—šžœœ œ œœœœ˜kLšœ$˜$Lšœ˜L˜—š ž œœ œ'œœœ˜jLšœζ™ζLšœ/ 3˜bLšœœ/˜6Lšœ œ˜-Lšœ.˜.Lšœ˜L˜—šžœœ œ=œœœœ˜žšœY™YL˜Lšœ œ@˜NLšœ:˜:Lšœ˜—L˜—L˜Lšœ˜—…—8 ώ