Raven: The Beginning of My Ray Tracing Journey

Hi everyone, welcome to the first blog of my ray tracing journey. I will introduce you to my ray tracer, “Raven”. Throughout history, ravens have served as messengers, delivering crucial information across distances. Similarly, my ray tracer sends rays through scenes, collecting and processing visual data to create images. I chose the name Raven because it symbolizes the journey from scene to image, just like ravens carried messages between distant places.

Raven Scene: rendering time : 9.45 sec

Implementation

Design and Architecture

We can consider this homework is the foundation of our ray tracing journey. Before I started the homework, I made some design decisions. I know that our ray tracer will grow with each homework, so I need to take some precautions.

I wanted to build the Raven in a clear and structured way to make it easier to maintain and add new features as the project grows. I am currently developing the Raven on the Windows 10 platform, using C++20 as the programming language. It is also compatible with Linux platforms. I am using Premake build system. This setup allows Raven to run on both Windows and Linux systems.

For architectural purposes, there are three projects in the solution.

  • Raven - The core library where the main ray tracer code is implemented.
  • Nest - The main project that utilizes the Raven library to execute ray tracing functionality.
  • Test – This project is dedicated for testing. If I need to test something new on Raven, I use this project.

Raven uses OOP programming language paradigm. For example, for the shape-related classes, it uses inheritance feature of OOP. We have a Shape parent class, and the Sphere and Triangle classes are derived from it. More OOP concepts will be utilized as we proceed. Stay tuned 😜 

For parsing scene files, I use tinyxml for XML files and happly for PLY files. They are header only libraries, and easy to use.

Moreover, Raven has its own profiling system. When a scene rendering starts, it automatically generates a profiler file (in Json format) for specific scene. 

To visualize the profiler json file, you can use any chromium-based web browsers. For example, in Chrome, navigate to chrome://tracing page and load this json file. You can see timing information as shown below. (You can download an example Raven Profiling file from here, and use your chrome to visualize it, if you're curious)

An Example Raven Profiler File Output

Intersection and Shading

I implemented the basic ray sphere intersection and ray triangle intersection (barycentric coordinates) from the course slides. However, I will implement MΓΆller–Trumbore intersection algorithm in our next homework assignment. 

I implemented Blinn- Phong shading model for the specular shading computations.  Also, for Conductor and Dielectric materials, it obeys Fresnel reflection rules. 

Optimization

I did few things for the optimization. I calculated the normal vectors of each shape during construction. Secondly, I simplify the sphere intersection calculation with PeterShirley’s trick. Thirdly, in scene parsing class, I use emplace_back function when I try to insert a new value in std::vector because it moves data without unnecessary copying and allows me to pass parameters directly, constructing the object in place. Finally, I use multithreading to accelerate my rendering time. Since pixels are independent from each other, I divided each image by horizontally, and assigned each part to a thread. 

Issues

I think that implementing a ray tracing is not an easy task. Due to its nature, I faced some issues during my implementation. I list and explain them briefly. 

If you look the problems that I faced, you might say that they don’t look like a big deal. However, believe me, they are big deal πŸ˜… After spending many days, you are wearing blinkers. To take off the blinkers, you need to give yourself a day, and avoid looking the project πŸ˜…


Sphere Intersection Problem

  • This one is very first bug that I faced when I was dealing with the intersection part. I tried to render a sphere but it didn't look like a sphere. The reason was my implementation of lenght_square function in my Vector class was not  correct. I didn't multiply every member of Vector properly. πŸ˜‘ You can see the problem as shown below. I had another problem with my dot function so I decided to use glm library for math calculation. Because I didn't want to waste another day troubleshooting problems caused by my faulty implementation of the Vector class.

Sphere Intersection Problem


    Camera Top and Bottom Value Problem

    •  This one appeared when I tried to implement basic ADS shading. Firstly, I couldn't understand the problem. Because Intersections and ambient shading run properly, but the image was flipped. Becuase I parsed my scene file wrongly. I got Camera's top value as bottom, and bottom as top. πŸ˜‘


    Normalization Problem

    Normalization Problem
    •  This one appeared when I tried to complete ADS shading. I couldn't find this problem for one day. The problem is that I didn't normalize my ray's direction vector.

    Reflect Ray Epsilon Problem

    •  This one appeared when I tried to complete Mirror Reflectance part. I couldn't find this problem for one day. Overall, it looks okay but the noise in the middle scene dont look okay. The problem is that I didn't move my reflect ray by epsilon. 

    After several days of blood, sweat, and tears, I finally identified the source of the issues and resolved them. πŸ˜…

    Scenes

    I created these two scenes in blender and export them with our blender exporter. I also created the scene at the top of my blog post. (Raven scene). I uploaded my scenes on OdtuClass, you can check them out. The triangle information of my scenes as follows: 

    • Raven: 2736 Triangles
    • David: 100,016 Triangles
    • Ceng Mug: 45,232 Triangles


    David Scene: rendering time : 4min 32sec

    Metu Ceng Teapot Scene: rendering time: 1min 43sec

    Science Tree Scene: rendering time 8.4sec

    Benchmarks

    Here's some scene benchmarks for different thread settings. 



    I will do the same comparison when I implement acceleration structure to Raven.


    System Specs:

    CPU: AMD Ryzen 7 5800X, 8-Core/16 Threads, Max Freq 4.7GHz, 36MB Cache

    Memory: 64 GB 3600MHz DDR4 RAM



    Comments

    Popular posts from this blog

    Leveling Up Raven: BVH, Transformations, and Instancing

    Enhancing Raven: Multisampling and Distribution Ray Tracing