4 minutes
Custom Ray Tracer in C++
Ray Tracer - Day 1 & 2
Introduction:
It is September of 2018, I am in my Undergrad Era, Kimi Raikkonen has stuck it on pole at Monza for Ferrari, Eminem’s Kamikaze is all the rage and breaking records and NVIDIA is ready to make Ray Tracing mainstream. Ray Tracing had existed before the RTX series of consumer grade gaming graphics card were announded but real-time ray tracing had always been seen as computationally intense workload that didn’t make sense on consumer grade hardware. A swanky presentation with swathes of gameplay videos of every surface looking like it got dipped in oil later, ray tracing had arrived and soon became the talk of the town.
As an avid gamer you best believe I was on the internet trying to look up every upcoming title that would give me all the oil dipped eye candy I desired. I had accepted that ray tracing was computationally intensive - hence you take a performance hit when you have ray tracing on and the fact without the rt cores in the RTX cards. Real-time ray tracing wasn’t even a thing that made sense to put in games. I accepted it, but, why exactly? I was taught in middle school how light rays bounces (reflects) and bends (refracts). The equations governing that behaviour don’t seem all that daunting yet, it is computationally expensive that special hardware features are required to enable it? Assignments and getting ready to build my new RTX PC made it that this thought just remained a thought and I never really explored it. That is until now. It is 2025 I am working at my dream job and I don’t have nearly enough time to keep up with the latest ray traced titles. But, what I do have is some time to catch up on old things I always wanted to explore and this week I am looking at implementing a custom ray tracer.
The ray tracer described here is from the very famous post Ray Tracing in One weekend from Peter Shirley.
Day 1 - Project Setup and Vector Implementation
I have been dabbling a lot in CMake a lot lately, it is an amazing tool and when it works it just works but, there is just so much customisability and granularity that comes with it that you really have to devote some serious time to get a feeling for the best patterns and practices to work with CMake. To bake in some well established good practices I used cmake-init. Please do check the project out if you too are feeling slightly overwhelmed by CMake.
CMake out of the way now we can start writing our ray tracer. The first thing I wrote this day was rendering a gradient
square. We pipe the output of stdout
to a .ppm
file and that becomes our image. Hence, producing a gradient square
was trivial - essentially you just iterate over the rows and columns setting an RGB value for each of the squares based
on their position. Next came implementing the vector class and aliasing it to color
and point3
, so it could be used
when we are trying to work with colors and points, both of which as you can imagine come handy when dealing with a ray
tracer.
A cool insight that you get when working on projects like these are how is the code structured in the industry and what practices are used. I was picking up on how this project was taking shape, the patterns of making libraries out of utilities like vector etc. that can then be consumed by the main seemed like a sensible approach to promote separation of concerns and decoupling different parts of the program.
Basic scene renderer and defining a ray
We now start by adding some Physics into the mix and talk about what a ray actually is. A ray, in its most basic mathematical sense has a fixed starting point and a direction. It can be extended infinitely in its direction but the initial point or origin of the ray remains fixed. Hopefully, you can see how vectors emerge as a perfect representation of our concept of a ray.
We choose to define a ray by the following (Ray = A + tB)
Day 2 - Rendering my first object (The graphics programming Hello World)
724 Words
2025-04-22 01:00