DIRECTORY Imager, ImagerColor, ImagerColorPrivate, RealFns, Shading, SV3d, SVModelTypes, SVVector3d; ShadingImpl: PROGRAM IMPORTS ImagerColor, ImagerColorPrivate, RealFns, SVVector3d EXPORTS Shading = BEGIN Color: TYPE = Imager.Color; Vector: TYPE = SV3d.Vector; Point3d: TYPE = SV3d.Point3d; LightSource: TYPE = SVModelTypes.LightSource; LightSourceList: TYPE = SVModelTypes.LightSourceList; CollimatedSpecularRadiance: PUBLIC PROCEDURE [surfaceNormal: Vector, lightSource: LightSource, albedo: REAL _ 1] RETURNS [radiance: REAL] = {radiance _ 180}; DiffuseReflectance: PUBLIC PROCEDURE [surfaceNormal: Vector, surfacePt: Point3d, surfaceColor: Color, lightSources: LightSourceList] RETURNS [completeColor: Color] = { OPEN SVVector3d; r, g, b, intensity: REAL; scaleFactor: REAL; surfaceToLight, surfaceClr, surfaceClrTemp, liteClr, ambientClr: Vector; colorSum: Vector _ [0,0,0]; r _ ImagerColorPrivate.ComponentFromColor[NARROW[surfaceColor], $Red]; g _ ImagerColorPrivate.ComponentFromColor[NARROW[surfaceColor], $Green]; b _ ImagerColorPrivate.ComponentFromColor[NARROW[surfaceColor], $Blue]; IF lightSources.first.type # ambient THEN ERROR; ambientClr[1] _ ImagerColorPrivate.ComponentFromColor[NARROW[lightSources.first.color], $Red]; ambientClr[2] _ ImagerColorPrivate.ComponentFromColor[NARROW[lightSources.first.color], $Green]; ambientClr[3] _ ImagerColorPrivate.ComponentFromColor[NARROW[lightSources.first.color], $Blue]; 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 _ ImagerColorPrivate.ComponentFromColor[NARROW[lite.first.color], $Red]; g _ ImagerColorPrivate.ComponentFromColor[NARROW[lite.first.color], $Green]; b _ ImagerColorPrivate.ComponentFromColor[NARROW[lite.first.color], $Blue]; 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; scaleFactor _ MAX[colorSum[1], colorSum[2], colorSum[3]]; IF scaleFactor > 1.0 THEN colorSum _ Scale[colorSum, 1.0/scaleFactor]; r _ colorSum[1]; g _ colorSum[2]; b _ colorSum[3]; completeColor _ ImagerColor.ColorFromRGB[[r,g,b]]; }; DiffuseAndSpecularReflectance: PUBLIC PROCEDURE [eyePoint: Point3d, surfaceNormal: Vector, surfacePt: Point3d, surfaceColor: Color, lightSources: LightSourceList] RETURNS [completeColor: Color] = { OPEN SVVector3d; r, g, b, intensity, hilitValue: REAL; scaleFactor: REAL; surfaceToLight, surfaceToEye, surfaceClr, surfaceClrTemp: Vector; ambientClr, finalClr, halfAngle, liteClr: Vector; colorSum: Vector _ [0,0,0]; r _ ImagerColorPrivate.ComponentFromColor[NARROW[surfaceColor], $Red]; g _ ImagerColorPrivate.ComponentFromColor[NARROW[surfaceColor], $Green]; b _ ImagerColorPrivate.ComponentFromColor[NARROW[surfaceColor], $Blue]; IF lightSources.first.type # ambient THEN ERROR; ambientClr[1] _ ImagerColorPrivate.ComponentFromColor[NARROW[lightSources.first.color], $Red]; ambientClr[2] _ ImagerColorPrivate.ComponentFromColor[NARROW[lightSources.first.color], $Green]; ambientClr[3] _ ImagerColorPrivate.ComponentFromColor[NARROW[lightSources.first.color], $Blue]; 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 _ ImagerColorPrivate.ComponentFromColor[NARROW[lite.first.color], $Red]; g _ ImagerColorPrivate.ComponentFromColor[NARROW[lite.first.color], $Green]; b _ ImagerColorPrivate.ComponentFromColor[NARROW[lite.first.color], $Blue]; 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; 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 r _ colorSum[1]; g _ colorSum[2]; b _ colorSum[3]; completeColor _ ImagerColor.ColorFromRGB[[r,g,b]]; }; 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: Vector _ 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: Vector, 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 August 5, 1985 4:20:54 pm PDT 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 Collimated light source at lightSource. Specular surface with given albedo oriented by given surfaceNormal. vector from surface to light source Scale sum to max. value to avoid desaturation at bright spots. ambientScalar _ DotProduct[surfaceNormal,[0,1,0]]; -- overhead ambient light 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šœ2™2JšœΓ™ΓJšœE™EJ˜J˜šΟk ˜ Jšœ˜J˜ J˜Jšœ˜J˜J˜Jšœ ˜ Jšœ ˜ —J˜Jšœ œœ6œ ˜cJš˜˜Jšœœ˜Jšœœ˜Jšœ œ˜Jšœ œ˜-Jšœœ ˜5Iproc˜—L˜L˜š Οnœœ œ;œœ œ˜Lšœl™l—L˜šžœœ œaœ˜§Lšœ ˜Lšœœ˜Lšœ œ˜LšœH˜HLšœ˜L˜Lšœ+œ˜GLšœ+œ˜ILšœ+œ˜HLšœ#œœ˜0Lšœ6œ"˜^Lšœ6œ$˜`Lšœ6œ#˜_Lšœ˜Lšœ*Οc&˜PL˜šœœœœ˜ILšœ7Ÿ˜N—L˜Lšœ6œœŸ˜bš˜Lšœ+œ˜KLšœ+œ˜MLšœ+œ˜LLšœ˜Lšœ@˜@Lšœ#™#Lšœ8Ÿ˜QLšœœŸ"˜KLšœ/Ÿ%˜TLšœ=˜=Lšœ˜Lšœ)Ÿ"˜K—Lšœ˜L˜šœœ(˜9Lšœ>™>—Lšœœ-˜FLšœ˜Lšœ˜Lšœ˜Lšœ2˜2Lšœ˜L˜—šžœœ œtœ˜ΖLšœ ˜Lšœ œ˜%Lšœ œ˜LšœA˜ALšœ1˜1Lšœ˜L˜Lšœ+œ˜GLšœ+œ˜ILšœ+œ˜HLšœ#œœ˜0Lšœ6œ"˜^Lšœ6œ$˜`Lšœ6œ#˜_Lšœ˜Lšœ*Ÿ&˜PL˜LšœL™Lšœœœœ˜ILšœ6˜6—L˜Lšœ6œœŸ˜bš˜Lšœ+œ˜KLšœ+œ˜MLšœ+œ˜LLšœ˜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˜`Lšœœ/˜6Lšœ œ˜-Lšœ.˜.Lšœ˜L˜—šžœœ œ;œœœœ˜œšœY™YL˜Lšœ œ@˜NLšœ:˜:Lšœ˜—L˜—L˜Lšœ˜—…—Κ#Γ