I’m currently taking a computer graphics course at my university, and it’s considered to be one of the hardest courses offered on campus. One of course’s assignments is implementation of a full-scale raytracer. If you have no idea what raytracing is, you can read about it here. Basically, it is one of the ways to create very realistic 3D imagery on a computer.
I’ve written a simple testimonial about my implementation of the assignment. I’m quite proud out of the outcome, and I want to share with you my journey towards it.
Below is the final image. Read on to find out how I got to it.

CS488 – Raytracer Assignment
Anton Lopyrev’s Testimonial – Spring 2009
It seems like it’s popular to have testimonials about this assignment, so I decided to have one of my own. Here we go…
I’ve just the read the description…
This one Don’t know where to start. I’m
so f**ked…
It’s gonna be a fabulous Saturday night.
OK. Just got some water, put on my headphones. Let’s get into the zone and look at the provided code…
Looked through the code. I wanna throw up…
Creating the background might be the most reasonable thing to do.
Damn, I can’t do anything tonight. Screw it, I need a drink, i’m going out.
Woke up, mind – nice and clear, time to work…
Got my first image with my nice lime background (thank you Ian for the colour combo)

Now it’s time to cast rays. I assume the next step is to be able for each pixel to determine its 3D position. Time to write some math.
I coded that up. It seems to be working. I might post the formulas for that later.
Next step:
sphere intesection, but first – I need food.
Sweeeeeeetttt… My sphere intersection seems to be working. Well, at least partially. I can see the outline of the spheres from simple.lua, but the
image is flipped and cropped on the right side. Maybe I screwed up my ray casting. Gonna have to check on the math.

Yep, I messed up in the calculation of the pixel 3D coordinates. I also forgot that the image’s 0,0 is in the top left corner and not the bottom left. That’s why the image was flipped.
The depth calculation also seems to be working – I colour coded the spheres’ surfaces by depth.

I’m probably gonna try to do lighting next, but I think i’m done for today.
I’m about to start doing lighting. Let’s see how that goes.
Ok… so I coded the lighting and it’s clearly wrong… no freaking clue what happened there…

Damn. found one bug. Being an idiot that I’m, I misinterpreted the Phong formula. It looks better, but I think something is still messed up.
Meanwhile, I also implemented shadows, at least they show up correctly

After 2 hours of pointless debugging, I realized that the the image above is actually correct since it matches the sample test image. I’m such a dumbass.
Three hours and lots of math later, I finally implemented the ray-box intersection using intersection-of-halfspaces approach in 3D. My first test gives me this. Pretty, but SO wrong
.

After quickly checking the code, I find that I only initialized 1 of the box’s planes, which ends up covering the entire image. I fix that and ta-da,
we’ve got a box. So much math and I get it on the second try. I’m so AWESOME. Time to go to sleep.

Alright, after a couple of days break I’m back at it. I decided to at least implement stochastic supersampling as one of my extra features. Let’s see how
it goes..
Well, that was pretty easy and the image quality has been definitely improved as you could see below (the image on the right has anti aliasing on). The only thing is that the raytracer got 9 times slower with stochastic supersampling. I’m gonna make it an optional flag, so it don’t have to do it all the time when i’m testing.


On SNAP, I guess i’m done with my extra features and I’ve just implemented recursive ray tracing and, therefore, reflections. That looks just awesome!

I took a week break to write a proposal for my class project. Now i’m back at it. It’s time to try to implement intersections with polygonal meshes.
First things I get don’t look so good. I turned off reflections and antialiasing for now to speed up testing.


Damn… after 5 or so hours of painful debugging, I realized that I was using the intersection-of-halfspaces algorithms incorrectly.
I finally have my meshes show up correctly. Thank god, cuz I was slowly going insane.


After starting implementing a hierarchical aspects of the raytracer last night, I finally completed them. 5 hours and everything looks nice. One thing is left – instancing.

While US is celebrating its independence day, i’m working on my raytracer. Very exciting, I know. Anyways, after a couple of more hours, I’ve implemented support for instancing. This was a bit tricky, since I flatten the scene transformation tree, but I got it done. For each node, I maintain a hash map of flattened inverse transformation matrices for each instance. Keys are a hash codes for each instance.
Here is the result:


With global reflections and anti-aliasing on, it took 1 hour, 27 minutes and 28 seconds to generate the last image. I think I need a
speed-up. But w/e, for now I need to come up with a unique scene.
Gimme a drum roll…. .. cuz
after over 80 hours of coding and around 20 hours of modelling I’m finally done. Below is my final image for the assignment. It’s a gold model of Toronto’s downtown placed on a wooden table under a lamp.
All building models were created in Autodesk 3ds Max 2010. It took forever, believe me.
Especially the CN tower and the TD bank tower, but I think it was worth it. I’m quite satisfied. As you can assume, my extra features are stochastic anti-aliasing and mirror reflections.

I will likely post my models for the buildings here as well at some point. If you want them, you can also email me: anton at lopyrev dot com.
Contact me, if you have any questions of comments as well.