Part 1: Basic Ray Tracer
In the first assignment, we are expected to implement a basic ray tracer which supports the following features:
1. XML Parsing & Storing a Scene:
A Scene is provided to the ray tracer as input, which is defined as an XML file. So, the first thing to do is parsing this input XML file and storing the Scene in a convenient way. For XML parsing task, an external library called TinyXML-2 is utilized. For now, a Scene consists of Cameras, Point Lights, Materials, Objects and their related Vertex Data.
2. Simple Perspective Camera Model:
For the first version of the ray tracer, only the simple perspective camera model is supported. In the input files, it is not guaranteed that the camera vectors are provided as orthogonal unit vectors, so they are converted to orthogonal unit vectors by the ray tracer to make sure that the camera parameters are set correctly.
3. Ray-Object Intersections:
Currently, there are 3 types of objects which are Spheres, Triangles and Meshes where a mesh consists of a set of triangles. Ray-object intersections are performed by casting rays from camera to every pixel on the image plane. While intersecting rays with objects in the scene, it is important to take the closest intersection into account for the associated pixel, since the objects behind will not be seen by the camera.
4. Shading Models:
In this version of the ray tracer, Ambient Shading, Diffuse Shading and Specular (Blinn-Phong) Shading are supported. Shading is used for determining the color of a pixel under the lights existing in the scene, depending on the material properties of the object.
5. Shadows:
A point can be in shadow with respect to a light source if an object lies between the light source and the point. To decide whether a point is in shadow or not, shadow rays are casted from the point to the light sources.
6. Writing Scene to PNG File:
Once the RGB values are calculated for each pixel, the only job left is to write these values to a PNG file. For this task, an external library called lodePNG is used.
Environment
The ray tracer is developed in C++ language in an Object Oriented way using Visual Studio Professional 2012. The machine environment is as follows:
OS: Microsoft Windows 10 64-bit
Processor: Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz
RAM: 16GB
Performance and Multi-threading
In this version of the ray tracer, no acceleration structures are utilized. However, since the rendering of the images takes a long time, I tried to speed things up a little bit by enabling the compiler optimizations of Visual Studio (/O2 flag) and introducing multi-threading. Since for each pixel the computations are performed independently, parallelizing the calculations was not so hard. I simply partitioned the image into equal parts horizontally so that each thread works on a number of rows individually. Maybe this is not the smartest way to perform multi-threading, but it helps to reduce the rendering times significantly.
For efficiency reasons, I have precomputed the camera and image plane parameters such as the top left corner of the image plane, since they remain constant for the entire process. Additionally, I computed the normals of the triangles while creating the triangles instead of computing them each time a ray intersects with the triangle.
Problems
While implementing the ray tracer, the most time consuming problem I encountered has produced the following buggy result.
Since the square object is a mesh which is composed of two triangles, I could not understand what caused it to turn out as expected while the little triangle's color is not correct. Since the square is fine, for a long time I thought that the problem was in the shading computations rather than the triangle creation part, and I checked the formulas over and over again. After many hours, I finally managed to realize that I forgot to normalize the normal vectors of the triangles. This has been a little hard to detect for me, because I was computing the normals of the triangles while creating the triangles as mentioned above.
Resulting Images
simple.png (800x800) rendered on 4 threads: 1 second 624 milliseconds 668 microseconds rendered on 1 thread: 2 seconds 5 milliseconds 539 microseconds |
rendered on 4 threads: 14 seconds 29 milliseconds 465 microseconds
rendered on 1 thread: 15 seconds 946 milliseconds 590 microseconds
rendered on 4 threads: 37 seconds 198 milliseconds 931 microseconds
rendered on 1 thread: 1 minute 39 seconds 701 milliseconds 717 microseconds
spheres.png (720x720) rendered on 4 threads: 249 milliseconds 941 microseconds rendered on 1 thread: 780 milliseconds 97 microseconds |
two_spheres.png (800x800) rendered on 4 threads: 46 milliseconds 854 microseconds rendered on 1 thread: 100 milliseconds 689 microseconds |
scienceTree.png (1440x720) rendered on 4 threads: 2 minutes 19 seconds 964 milliseconds 394 microseconds rendered on 1 thread: 5 minutes 35 seconds 228 milliseconds 245 microseconds |
Comments
Post a Comment