Project 3: Ray-Tracing and Shadow Feelers

Total Page:16

File Type:pdf, Size:1020Kb

Project 3: Ray-Tracing and Shadow Feelers

User’s Documentation

Project 3: Ray-Tracing and Shadow Feelers

Jeffrey C. Keller

Description: The purpose of this program is to render objects using the method known as ray tracing. The main premise behind a ray-tracing program is that we shoot rays into a scene and determine what it hits. The ray may hit reflective or refractive objects, and if it does it spawns a new ray. The color information from these rays are added and displayed on the screen. This ray-tracing program draws a floor and spheres that can be either matte, reflective, refractive, or a combination of the three. This program also uses a simple shadow-feeler to display shadows.

Execution: Executing the program is straightforward. The executable file name is

‘trace.’ This program has two additional parameters. The first is the maximum recursive depth the program can reach. We need to specify the maximum recursion because the ray can be caught between two reflective objects, and possibly reflect infinitely. The other parameter for this program is the filename that contains the information regarding the spheres to be rendered. For example, in order to render the spheres specified in the file

“data1” at a maximum recursive depth of 10, the command given to the computer would be “trace 10 data1.”

Input: This program requires three files to run correctly. The first file is “floor.dat.”

This file is used to specify the colors present on the floor. The floor is composes of square patches in a checkerboard arrangement, with each line from the file mapped onto a different square. The maximum number of lines that specify color in this file is currently

10. If the file is shorter than 10 lines the program will only draw the amount of colors specified. Each line of the file contains three values—Red, Green, and Blue. Note that a sample floor.dat file is included with the program.

The next file that is necessary for this program to function correctly is named

“viewpoint.loc.” This file specifies, in three-space, where the viewpoint of the viewer is in relation to the scene. This file is comprised of a single line of three spaced decimals.

The first number signifies the x coordinate, the second specifies the y coordinate, and the third specifies the z coordinate. Note that an example viewpoint.loc file is included with the program.

The last file needed for successful execution of the program is the file where the information regarding light sources and spheres are found. The format of the information pertaining to light sources is “L x y z i”, where x, y, z, and i are all doubles. X, y, and z represent the point in 3-space where the light originates, and i is its intensity. Important note: there can be at most five light sources. This was decided for the reason that if we include more light sources the images loose quality and become “washed.”

The format of the lines pertaining to spheres are:

‘S Kar Kag Kab Kdr Kdg Kdb Ks n Krefl Krefr mu’

‘x y z radius’

The first letter (S) is a literal, and all of the other variables are doubles. The value of all of the ‘K’ variables should be between 0.0 and 1.0. The ‘K’ variables are used to signify the different constants used in calculating the color of the sphere, and “n” is the exponent of the specular component. “Krefl” is used to specify the degree to which the sphere is reflective. If the sphere is not reflective then this constant is set to 0.0. “Krefr” is used to specify the degree to which the sphere is refractive. Again, if the sphere is not refractive this constant is set equal to 0.0. Mathematically, adding the reflective and refractive constants and subtracting the sum from 1 gives the matte constant for the sphere. “Mu” signifies the coefficient of refraction, as it is commonly known is physics. X, y, and z represent the center of the sphere in 3-space, and “radius” is the radius of the sphere.

Output: After the data file is read in to memory, the program will open a window and begin to render the images. After the images are rendered, they will stay on the screen until the window is closed by the user.

Ending the Program: To end the program close the window in which the objects are drawn.

Known Issues: As of now there are no known issues with this software, and there have been no bugs reported. If you discover a bug, please report it by sending e-mail to [email protected]. Also, watch barada.canisius.edu/~keller for any updates to this package. Thank you for your purchase. System’s Documentation

Project 3: Ray-Tracing and Shadow Feelers

Jeffrey C. Keller

Description: The purpose of this program is to render objects using the method known as ray tracing. The main premise behind a ray-tracing program is that we shoot rays into a scene and determine what it hits. The ray may hit reflective or refractive objects, and if it does it spawns a new ray. The color information from these rays are added and displayed on the screen. This ray-tracing program draws a floor and spheres that can be either matte, reflective, refractive, or a combination of the three. This program also uses a simple shadow-feeler to display shadows.

Overall System Design: The basic design of the system is thus: Trace.c++ is the main driver of the program. It first checks the command line arguments and draws the window. Next, the driver opens the data file and reads in all of the light sources contained within. After all of the light sources have been read, the driver closes and opens the file (to reset the file pointer), and begins to read in the spheres. These spheres are stored in an array specified in the beginning of the driver. This array is set to a maximum of 1000 elements. Once all of the spheres have been read from the data file, the driver loops through each pixel in the screen. The screen is specified to be 512X512, at a z location of 0. For each pixel on the screen, the driver shoots a ray. The process of shooting the ray is where the ray tracing and recursion come to bear in this program.

After all of the rays have been shot into the scene, the driver waits for the user to close the display window. The driver also contains the method to shoot the ray. This method will be touched upon later. The other classes are self-explanatory. The light source class handles the light sources by specifying its location in 3-space, the light source’s intensity, and the total intensity generated by all of the lights. The sphere class contains the location of the center of the sphere, its radius, as well as the various constants used in rendering the object via phong shading. The sphere class also contains methods to implement Phong shading, as well as various methods regarding the rays and the various operations performed on them. These algorithms will be discussed in detail later. The ray class handles a ray. This class contains the starting location of the ray, as well as the change vector of the ray. This class also contains the starting components squared to be used in calculations later. The background class handles the drawing of the floor in this project, as well as the shadows on the floor. The floor is a checkerboard pattern, with at most 10 distinct colors specified. As before, the details of the important algorithms are mentioned later.

Data Structure Choices: For this program there were not any issues where the choosing of appropriate data structures came into play. Not including the classes themselves, the only data structures used were static arrays. The driver class has an array that is used to store all of the spheres from the file. The lightsource class contains an array to hold all of the light sources specified in the file. The sphere class utilized static arrays for some of the constants.

Design Details: As mentioned before, trace.c++ is the main driver file of this program. The file first opens the file “viewpoint.loc,” which is where the viewpoint information is stored. Next it obtains from the command line arguments the maximum number of recursive calls, as well as the datafile where the spheres are specified. Then we open the datafile twice. The first time we read in all of the light sources. After this we go through the file looking for spheres and store them into an array. After we have obtained all of the spheres from the file we loop through each of the pixels on the

512X512 screen, shooting a ray at each, collecting the color information from the shootray method, and drawing the pixel with the appropriate color. Then we wait for the window to be closed by the user.

The trace.c++ file also contains the main recursive algorithm used in performing ray tracing. This function is located above the “main” block of code. The main algorithm for this is as follows: The main parameters of this method are the ray, the spheres, the lights, the background, the current recursive level, and a variable indicating whether or not we are outside a sphere. First, we calculate the t-value for the nearest intersection with a sphere. If there is no intersection we proceed to call the getcolor method from the background class. If there is an intersection, we first calculate the local intensity (via the Phong method). Next, decrement the recursive level, and if it is still greater than 0, check to see if the sphere where the intersection occurs has a reflective or refractive component. If it does, calculate the reflective or refractive ray, accordingly, and call the shoot ray method for that ray. When calling the shoot ray method for a refractive ray the “outside” variable must be set to the opposite variable, since a refractive ray enters the sphere.

The sphere class is a little more involved than the trace class. The constructor for this class is pretty straightforward. The phong method in this class calculates the local intensity for a specific point on a sphere. Of special note is that this function also calculates the shadows at the particular point, which is why there are so many parameters.

The general algorithm is as follows: First the normal at the specified point is calculated and normalized. Then if we are currently on the inside of the sphere the normal is negated. Next we go through the lights, and for each light we check to see if there is a sphere in the path between the current sphere and the light. If there is, then the light does not get included in the intensity calculation. If there is nothing between the light and the sphere, then the various Phong calculations are performed and the specular and diffuse variables are updated. Once we have run through all of the lights, we then set the three color components and multiply them by the matte constant for the sphere. It is in this way that the method not only achieves the Phong intensity, but also shadows and accommodation for the matte constant. Note that this method of detecting shadows is commonly referred to as a “shadow feeler.”

The closesetintersect method in the sphere class returns the t-value of the closest intersection point when given a ray. Of special note is that the pass-by-reference variable

“good_intersect” must be checked, as if this is set to 0 after the method is called then the returned value is not valid. The main formula utilized in this formula is the quadratic formula t=(-b-\+sqrt(b2-4ac))/2a. The equations for “b” and “c” are in the code and are pretty straightforward. As “a” is assumed to be 1, so we can disregard this variable. If the value under the square root sign is negative we can return out of the function immediately after setting “good_intersect” to 0 because the intersection is not valid.

Else, we need to find the smallest positive t-value and pass this back from the method.

The other two main methods in the sphere class are the methods that calculate the reflected and refracted rays. These formulas are based mainly on physics. The equation for calculating a reflected ray is 2N(-I % N)+I, where “%” signals the dot product. “N” represents the normal, and “I” represents the change value of the incoming ray. This method calculates the normal (again if we are inside negate it), performs the above calculation, and returns the reflected array. The refracted method is a little more complex. The formula for calculating a refracted ray is muI+(cos(theta) -mu cos(phee))N, where cos(theta) is given by sqrt(1-mu2(1-cos2(phee))), and cos(phee) is given by –I%N. Again, “%” specifies the dot product and the symbols are the same, except for mu, which is the refraction coefficient as specified in the datafile. In the refraction method we first calculate the normal. If we are inside the sphere, we again negate the normal, else we set the mu to 1/mu. After this we plug the correct values in the correct places. Before we can return the refracted ray we must check to make sure the value beneath the square root is positive. If it is not then the refracted ray is not valid and the method returns a 0. Else, carry on with the calculations and return the ray.

The other classes that comprise this program are more straightforward than the sphere and trace classes. The ray class handles the implementation of a ray. The method in this class that is of interest is getpoint, which passes back via reference the point along a ray at the specified t-value. This method multiplies the change value by the t-value and adds it to the startpoint of the ray. The background class contains code that stores information about the background and floor. The getcolor method takes in a ray and checks to see if it strikes the floor. If it does, the function passes back the color information after it has accounted for shadows (which is a process that closely models that found in the sphere class). If the ray does not strike the floor, the equivalent of the color “black” is passed back from the function via reference. Of special note is that the floor is located in 3-space at ((0-512), 0, (0-512)). If the y component of the change part of the ray is >= 0, then the ray cannot hit the floor and we return black early. Else, we find the t value where y=0 (by using parametric equations), calculate the point where the ray intersects the floor, and return the color value proportional to the amount of light hitting that point. The only class remaining is lightsource, which is composed of mainly accessor methods.

Compiling Instructions: To compile simply use the makefile included with the program. To use this file type “make.” That should be sufficient. Depending on the location of the standard libraries in your system you may have to make some minor modifications to the makefile. After the makefile is executed, to run the program follow the instructions outlined. The files needed for compilation are as follows: trace.c++

Sphere.h and sphere.c++

Vector.h and vector.c++

Lightsource.h and lightsource.c++

Ray.h and ray.c++

DisplayWindow.h and displayWindow.c++

Errors and Limitations: There are no known issues/errors, and no bugs have been reported. The only limitation of this program is that there can be at most five light sources.

Suggested Improvements: There are no suggested improvements at this time.

Testing Information: This product was tested with multiple data files. Some of these data files have been included in the boxed product for the user to experiment. The first functionality of this program to be tested was the Phong shading and the shadows.

Next, the floor was tested. Last, the reflective and refractive components were added and tested. All of these test cases were compared to known output and passed, so the correctness of the program can be ascertained to be adequate.

Recommended publications