$29
1. Read the assignment carefully! Pay attention to every instruction to save time.
2. Starting early and implementing it part-by-part as we discuss in class is the key to finishing this assignment on time and enjoying it!
This write-up provides guidelines for Assignment 7 and 8 with clear boundaries for each. In Assignment 7 you will implement a basic ray-tracing program. This program will be capable of rendering a 3D scene made of boxes and spheres with shading effects and textures. In Assignment 8 you will extend this program to include shadows, and reflective and transparent objects.
Step 1: Laying the foundation:
It would be useful to have the following small helper classes in your program to perform frequent operations:
1. 3D ray: contains a starting 3D point and a direction as a 3D vector.
2. HitRecord: Stores all the information that you will need to determine the closest object that was hit, and information about that object to calculate shading. More specifically, it will contain (a) the time ‘t’ on the ray where it intersects an object (b) the 3D point of intersection in view coordinates (c) the 3D normal of the object at that point in view coordinates (d) The material properties. (e) Texture coordinates and a Texture object, if applicable.
3. Create small scenes with single or a few objects for testing purposes. Do not try to test directly on a big scene!
You should begin by creating the above classes before proceeding.
Step 2: Setting up the basic ray tracing:
Modify your Assignment 6 program so that it switches between OpenGL and raytracing modes, possibly with a keypress. This will allow you to view a scene in OpenGL before ray tracing it. The output of the ray tracer should go to an image, not on the screen window.
2.1 raytrace(int w,int h,modelview stack)
Write a raytrace function that creates and exports an image file, as an output to ray tracing (look at the design of your program to see where your raytracer, and this function would fit well). The modelview stack currently contains the camera transform that is set in the View::draw method (as with the OpenGL rendering). It should do the following:
For every pixel:
1. Compute the ray starting from the eye and passing through this pixel in view coordinates.
2. Pass the ray to a function called “raycast” that returns information about ray casting.
3. Write the color to the appropriate place in the array.
2.2 raycast()
Create the function raycast(…) that takes the following parameters: the ray to be cast in the view coordinate system and the modelview stack. This function will compute the resulting color. It returns true/false depending on whether the ray hit some object in the scene or not.
It does the following:
1. Pass on the ray and the modelview stack to the root of the scenegraph.
2. If the ray did hit anything, call a function shade and pass to it all the relevant information from the hit record that the root returns, that will be useful in calculating the color of this pixel.
3. If the ray did not hit anything, return the background color.
Step 3: Computing the ray-object intersections:
1. Add a method to your node classes that will determine and compute the intersection of a ray with various nodes. It should also populate the HitRecord with the nearest point of intersection, the normal at that point (in the view coordinate system), material and texture properties.
Define this function:
a. For the leaf node, identify the object associated with the leaf (Box or Sphere) and process the ray accordingly.
b. For the Group and Transform nodes, it merely passes everything to each of its children after altering the modelview suitably.
When this function returns from the root, it should have information about the closest intersection, and other relevant information.
How to test:
Start with a very simple scene (one solid, untransformed) and place the camera on the Z-axis looking directly at it. If the raycast returns true, write a white pixel. This will allow you to test whether your intersection code works by allowing you to step through and calculate expected answers manually. Now move the camera and test, and finally add several objects to test.
Step 4: Shade function
Write a shade function that takes all appropriate parameters necessary for it to do lighting. It must perform the same lighting as the shader you used in Assignment 6 (point/directional and spot light sources, ambient, diffuse and specular lighting), but without texturing. This involves essentially replicating your lighting shader.
The easiest way to test whether this is working is to switch between OpenGL and ray tracing modes and verify that the pictures are identical. You may find it better to test only ambient first, followed by ambient+diffuse and finally all three effects.
Step 5: Textures:
The intersect functions of the respective objects should also return the appropriate texture coordinates for the point of intersection in the HitRecord. Use the TextureImage object to determine the pixel color from the texture.
Assignment 7 ends here.
What to submit: Submit your IntelliJ/Qt project with input model files. Also submit:
1. An image showing the final rendering (the best output) of your ray tracer (at least 800x800).
2. An image showing the OpenGL rendering of the same scene and the same camera position as your final raytraced image above. This will allow us to quickly verify that everything works correctly.
3. An image showing that your ray tracing works for spheres (a black and white image, or the final rendering)
4. An image showing that your ray tracing works for boxes (a black and white image, or the final rendering)
5. An image showing that lighting works (a suitable image, or the final rendering)
6. An image showing that your texture mapping works (a suitable image, or the final rendering)