[ LiB ] |
You can now upgrade your application so it can handle shadow rays. The application is going to trace a ray backwards from the point of intersection to the light source to determine whether anything is obstructing the line of sight. If the line of sight is obstructed, the color black RGB(0,0,0) will be assigned to the pixel and returned as the shade . This in essence creates the shadow. If the line of sight isn't obstructed, the point is shaded normally.
The first thing you need in order to simulate shadows is a method similar to Find Closest Object() , but one that determines whether the line of sight between a point to the light source (two vectors) is blocked. The method cycles through each object in the scene, testing for points of interaction. If the ray intersects a point on an object, it returns true . If not, it signals that the ray isn't obstructed and should be shaded normally.
Here is the method:
bool cScene::Is_It_Blocked( cRay Ray, float LightDistance ) { int iFoundObject; for(int i = 0; i < this->nObjectCount; i++) { if( pObjectList[ i ].Default_Primitive != OBJECT_NOTHING) { iFoundObject = pObjectList[i].Find_Hitpoint( &Ray ); if( iFoundObject && ( Ray.distance <= LightDistance ) ) return true; } } return false; } Here is the logic: Shade Point( point, normal ) Color = black For each light source If not Shadow Ray Color = Color + direct illumination Return Color
You can now update the ShadePoint() method to accommodate the shadow ray functionality. If the line of sight is blocked from the point of intersection to the light source, the value for black is returned. The new code is listed in bold:
color3 cScene::ShadePoint(cVector3 hit_point, cVector3 normal, int iObject) { //Get normal cVector3 From_Light_To_Hitpoint, Shininess; int i; float fLen, fAngle; // color is black by default color3 color; // set color to black color = color3::Black; // for each light for( i = 0; i < this->nLightCount; i++ ) { // is light okay to use? if( pLightList[i].bActive ) { // from light to hit point From_Light_To_Hitpoint = pLightList[ i ].vPosition - hit_point; fLen = From_Light_To_Hitpoint.Mag(); From_Light_To_Hitpoint.Normalize(); // find angle between surface normal and light direction fAngle = ( From_Light_To_Hitpoint * normal ); // if visible from lightsource to surface if( fAngle > 0.0f ) { // Check to see if anything is blocking this ray to the object if( !Is_It_Blocked( cRay( hit_point, From_Light_To_Hitpoint ), fLen ) ) { // do diffuse interaction if(RenderSetting.use_diffuse_shading && pObjectList[iObject].fDiffuseFactor> 0.0f ) { color.r += ( fAngle * pLightList[ i ].Color.r ) * pLightList[ i ].fWattage * pObjectList[iObject].fDiffuseFactor ; color.g += ( fAngle * pLightList[ i ].Color.g ) * pLightList[ i ].fWattage * pObjectList[iObject].fDiffuseFactor ; color.b += ( fAngle * pLightList[ i ].Color.b ) * pLightList[ i ].fWattage * pObjectList[iObject].fDiffuseFactor ; } // do specular highlight if(RenderSetting.use_specular_hightlights && pObjectList[iObject].fShininess > 0.0f ) { Shininess = ( normal * ( 2.0f * fAngle )) From_Light_To_Hitpoint; float Dot = ( Shininess * this->Viewing_Direction); if( Dot > 0.0f ) color += pLightList[i].Color * ( (float)pow( Dot, pObjectList[iObject].fSpecularExponent ) * pObjectList[iObject].fShininess ); } } // is light blocked } // end visible } // end light on } // end number of lights return color; }
To use this program, follow the same instructions as for using the previous two examples. The folder /Ray Tracer 3 contains another folder called /Scenes . The files included in this folder are the input scene files you will type into the program.
This /Common folder contains the basic classes required to set up a 3D rendering environment. The folder that includes the required classes for this program is in /Book Code/Chapter 09/Ray Tracer 3/Common .
The files in this folder are:
12/21/2002 04:48p 1,381 cLight.h 12/21/2002 04:38p 5,127 cObject.cpp 12/21/2002 04:58p 4,667 cObject.h 12/21/2002 04:39p 442 Color3.cpp 12/04/2002 12:33p 4,476 Color3.h 12/21/2002 04:39p 23 cRay.cpp 12/21/2002 04:59p 2,043 cRay.h 12/21/2002 04:39p 22,499 cScene.cpp 12/21/2002 04:59p 3,324 cScene.h 12/19/2002 05:29p 1,991 cVector3.cpp 12/21/2002 04:47p 5,171 cVector3.h 12/21/2002 04:59p 1,060 MathTools.h 12/21/2002 04:39p 1,108 PPM.cpp 12/21/2002 04:49p 154 PPM.h
When you run it using the procedure described earlier, the program will prompt you to enter the path for the scene definition file. When it asks "Enter Information:", you enter one of the following:
/scenes/shadow1.txt /scenes/shadow2.txt
The program starts the ray-tracing process and then again will prompt you to enter the output path for the rendered file stored on the image plane. When it asks "Please Enter output Path and Filename:", enter one of the following:
/scenes/myoutput1.ppm /scenes/myoutput2.ppm
You can then browse to that path and open the file in IrfanView. I have created the exported files for you and placed them in the following folder:
/Book Code/Chapter 09/Ray Tracer 3/Output
The files in this folder are:
10/13/2002 03:30p 3,200,805 shadow1.ppm 10/13/2002 03:43p 3,131,109 shadow2.ppm
[ LiB ] |