This preview shows page 1. Sign up to view the full content.
Unformatted text preview: CS51 Assignment 6: Raytracer (75 points, including 10 points for style) Design due: Tuesday, April 8th, 2008 at 5:00 PM Code due: Friday, April 11th, 2008 at 5:00 PM The goals of this assignment are: To give you some experience designing, implementing and using a class hierarchy. You will develop this class hierarchy in the context of a raytracer. To give you experience writing crucial components of a simple raytracer and the opportunity to produce gorgeous images for a contest! 0. Overview Raytracing creates an image by essentially simulating the physics of sight. In the real world, rays from light sources (such as the sun or a florescent light) hit different objects, reflect and refract until they hit the eye and are rendered by the brain. In our raytracer, we will optimize this process. While we could follow every ray emitted from a light source, most of these rays will never hit the eye and represent wasted computation. Instead, we solve the problem backwards. We shoot only the rays we need, from the eye, or camera, into the scene. We follow the ray as it hits (or doesn't hit) different shapes and update the color that would result as if it had originated from a light source. We can think of our final image as a window between our camera and the scene. Each pixel in the final image is determined by the result of the ray that goes from the camera, through the image, and into the scene. To find the color of a ray, we first determine which shapes intersect the ray. If no shape in the scene intersects the ray, we simply set the corresponding pixel to the default background color. From the set of intersection points, we find the intersection that is closest to the camera (since this is the shape that you will actually see). We then determine the color at the point of intersection given the properties of the shape (such as its color or its reflectivity) and the position of the lights in the scene. 1. What we have provided We have provided a substantial amount of code for this assignment. It is located in ~lib51/pub/assigns/asst6. Basic types Vec3, Ray, Light, Color, and Camera o Privately stores information as doubles o Vector functions to calculate the dot product, cross product of vectors, the distance between vectors, and the ability to normalize a vector. Texture o Describes the basic coloring of a shape and is composed of a base color and an ambient coefficient (a double between 0 to 1) o The ambient coefficient determines how much of the base color will always show A value of 1 means that the color will always show regardless of lighting (glows) A value of 0 means that the shape will only show if lit by other light sources Abstract type Shape o Represents a shape to be rendered in the scene o Requires a Texture o Exports the functions GetIntersect and GetNormal o GetIntersect accepts a ray, and returns either a positive distance of how far down the ray one must travel from the initial point before intersecting the shape or a negative value if the ray does not intersect the shape. o GetNormal accepts a point that lies on the shape and returns the normal of the shape at that point. o Two derived types, Plane and Triangle Image o Constructor supports the creation of a bitmap image of a given width and height o Uses SetPixel to set the color of a specific pixel o Can write out the image to a given filename using Output Scene o Provides the CreateRays function which creates the necessary rays given a camera and a final image size o Provides the GetColor function which takes a specific shape, a ray that will intersect the shape, and the distance along the ray that determines that the intersection happens and then returns the color of a shape at a specific point after taking into account factors such as lighting and shading Raytracer o Here is where you will create all the parts of your scene and finally render it to create an ouput bitmap image. 2. Let's get to work The assignment is separated into three stages, between which you will be able to write small test programs and compare your output against our solution. You will first write the basic render function which will shoot and trace the rays. When this is finished, you will be able to create images with planes and triangles. You will then implement circles, spheres, cubes, and groups of shapes. When this is finished, you will be able to incorporate these shapes into your images. The last component is implementing reflection. (Note that this section is not required.) Design [Due Tuesday!] Please put the answers to these questions in answers.txt. (a) [2 points] How does Triangle implement GetIntersect and GetNormal? What other shape does it rely on to make these functions easier? (b) [2 points] Given only the position and the direction to look at, how does Camera determine which the direction up and right? Which function in Camera requires these two directions? (c) [2 points] How does CreateRays in Scene work? Given an image with a resolution of 300x200, how many rays would it return? What is the ordering of the rays returned? (d) [2 points] How does GetColor determine if the intersection point is shadowed? What happens if the point is shadowed (not directly illuminated)? (e) [2 points] How does Image create a bitmap file? You may only explain generally. You do not need to explain every element of the header. Before you write any code, have a firm understanding of Shape, Image and the CreateRays and GetColor functions in Scene. (f) [10 points] You should write complete design document for this assignment covering how you plan on completing the Render task and the Shapes task in design.txt. Email both answers.txt and design.txt to your TF by Tuesday at 5pm. Render (a) [2 points] Scene has a vector that holds lights in it. Provide a public function to add additional lights into a scene. (b) [2 points] Scene has a vector that holds shapes in it. Provide a public function to add additional shapes into a scene. (c) (d) (e) (f) [1 points] Provide Scene with a method to set the camera to a new one provided by the user of the class. [2 points] Provide Scene class with a destructor. Make sure that it will free all allocated memory on exit. [10 points] Write the Render function of Scene. It must take in a desired resolution and output filename. Render will need to create a new Image and the required rays using CreateRays. Render will then need to "shoot" each ray into the scene (into each shape), and find the shape that returns the shortest intersection distance. Render will then need to find the color of the closest shape at the intersection point using GetColor and set the corresponding pixel in the created image using SetPixel. Finally, after all the pixels have been properly set, Render should output the resultant image. [3 points] Create a scene containing: Camera(Vec3(0, 2, 10), Vec3()) Light(Vec3(10, 20, 0), 1) Plane(Vec3(0, 1, 0), Vec3(0, 1, 0), Texture(Color(0, 0.5, 0), 0)) Triangle(Vec3(0, 0, 3), Vec3(2, 0, 0), Vec3(2, 0, 0), Texture(Color(1, 0, 0), 0)) It should look like the figure below: Render your scene with the resolution set at 800x600 and save it as part1test1.bmp. Create an additional nontrivial test image that demonstrates correct lighting and rendering of planes and triangles and save it as part1test2.bmp. Shapes (a) [3 points] Implement Circle. The constructor will take a center, a radius, and a normal. Make sure that Circle properly derives from Shape. Hint: look at how Triangle is implemented. (b) [4 points] Implement Sphere. The constructor will take a center and a radius. Given a point on the sphere, the normal at that point is simply the normalized vector from the center to the point. To determine the point of intersection: Create a vector RayCenter from the originating point of the ray towards the center of the sphere. Calculate RayCenter's dot product with the direction of the ray. This value is the projection and checks if the ray is directed towards the sphere at all. If the projection is negative, there is no intersection. Sum the square of the sphere's radius and the square of the projection. From this value, subtract the dot product of RayCenter with itself. This value, t, is the square of the difference between the distance from the initial point of the ray to the intersection point and the projection. If this value t is negative, there is no intersection. Otherwise there is an intersection. The point of intersection is exactly the difference between the projection value and the square root of the value t. (c) [4 points] Implement Cube. The constructor will take a collection of eight points. Hint: you may want to use a collection of Triangles. You may assume that Render or GetColor will never call GetNormal for a ray without first making a corresponding call to GetIntersect. This may help optimize the performance of your implementation. (d) [6 points] Implement Group. Group represents a collection of shapes all to be rendered together. It must support the Shape abstraction and therefore must export the GetIntersect and GetNormal functions. For GetIntersect, given a ray, it must determine if any of its constituent shapes intersect it, and return the distance of the closest intersection. For GetNormal, you may assume that the intersection point passed in lies on the same shape for which you returned the intersection distance in the most recent call to GetIntersect (you will need to store this information somehow between calls) and then return the normal of that shape at the given point. Remember to implement the necessary methods and a destructor if you need one. (g) [3 points] Create a scene containing: Camera(Vec3(5, 5, 10), Vec3()); Light(Vec3(10, 20, 20), 1); Plane(Vec3(0, 1, 0), Vec3(0, 1, 0), Texture(Color(0, 0.5, 0), 0)); Circle(Vec3(0, 2, 5), Vec3(0, 0, 1), 3.5, Texture(Color(1, 0, 0), 0)); Sphere(Vec3(3.5, 0, 0), 1.2, Texture(Color(0, 0, 1), 0)); vector<Vec3> cubeVecs; cubeVecs.push_back(Vec3(1, 1, 1)); cubeVecs.push_back(Vec3( 1, 1, 1)); cubeVecs.push_back(Vec3( 1, 1, 1)); cubeVecs.push_back(Vec3(1, 1, 1)); cubeVecs.push_back(Vec3(1, 1, 1)); cubeVecs.push_back(Vec3( 1, 1, 1)); cubeVecs.push_back(Vec3( 1, 1, 1)); cubeVecs.push_back(Vec3(1, 1, 1)); Cube(cubeVecs, Texture(Color(0, 1, 1), 0)); It should look like the figure below: : Render your sc cene with the e resolution set at 800x600 0 and save it as part2test1.bmp. Creat te the ame image bu ut instead of adding the in ndividual shap pes, add it as part of a grou up. Render yo our sa sc cene with the e resolution se et at 800x600 0 and save it a as part2test2.bmp. Creat te an addition nal no ontrivial test t image that d demonstrates s correct light ting and rend dering of circle es, spheres, c cubes an nd groups and save it as part2test3.bm mp. Note: Th he reflectio on section b below is no ot required. This is a n new problem m set, and we aren't su ure how lon ng it will ta ake. We en ncourage yo ou to try it, because w we think it's s fun and a co ool extensio on. (It will also make your conte est.bmp ima age, described after the Reflectio on section, more excit ting!) Please note tha at this is no ot extra cred dit--you w will not get a any points if you do it t! There are more tasks below th his section, , so please don't sto op reading here! Reflecti ion In our bas sic implement tation withou ut reflection, we simply use information n about the p position of the e lights and d shading to d determine a d diffuse coeffic cient, a double between 0 and 1. Our co olor at any po oint on the sha ape is then produced by th he equation: diffu useColor = (am mbientCoeffic cient + diffuse eCoefficient * * (1 ambien ntCoefficient)) * baseColor r However, we can easily extend our model to sup pport the crea ation of more e complex images. Instead d of only determining the c color based on properties of the shape and lighting, we can use in nformation gathered from shooting another ray, specifically the ray that would result from the original ray (from the camera) reflecting off the surface of our shape. If we determine the color of this new ray being shot into the scene, we can combine it with our previous information to create reflection. We use a value called the reflection coefficient to determine how "mirrorlike" we want our shape to be. Our new equation for the color of a specific point is then: finalColor = reflectiveCoefficient * reflectiveColor + diffuseColor (a) [0 points] Extend Texture so that it also has a reflective coefficient. Create the proper constructors and functions to get/set this variable. (b) [0 points] Write the function GetReflectColor in Scene. This should, given a ray, return the color from shooting that ray into the scene. This function will need to recurse. (c) [0 points] Include a call to GetReflectColor in GetColor. Modify GetReflectColor's output with the reflective coefficient and combine it with the previous nonreflective color to create the final output of GetColor. (d) [0 points] Create a scene containing: Camera(Vec3(5, 5, 10), Vec3()); Light(Vec3(10, 20, 20), 1); Sphere(Vec3(1.5, 0, 0), 1.2, Texture(Color(0, 0, 1), 0, 1.0)); Sphere(Vec3(1.5, 0, 0), 1.2, Texture(Color(1, 1, 1), 0, 1.0)); Sphere(Vec3(0, 2.5, 0), 1.2, Texture(Color(1, 0, 0), 0, 1.0)); It should look like the figure below: Render your scene with the resolution set at 800x600 and save it as part3test1.bmp. Create an additional nontrivial test image that demonstrates correct lighting and rendering of reflective surfaces and save it as part3test2.bmp. Contest! [3 points] Create an image that will make your TF proud. Name this contest.bmp. Feedback [2 point] Write a quick note in feedback.txt answering the following questions: o o o Length: Was this problem set too long, too short, or just right? Difficulty: Was this problem set too easy, too hard, or just right? Other comments? 3. When you are finished Please run make submit when you are finished. ...
View Full Document
This note was uploaded on 04/08/2008 for the course CS 51 taught by Professor Nagpal during the Spring '08 term at Harvard.
- Spring '08