An attempt to implement relevant raytracing techniques.
I do not claim ownership of any content in this project. Its sole purpose is replicating and learning relevant raytracing techniques. There are parts that were simply copy-pasted from elsewhere for convenience.
Most importantly, I was inspired by Kevin Beason's smallpt which bundles together many relevant raytracing techniques in an impressive 99 lines of C++ code. In this project here, I basically replicated smallpt step by step in my own way of coding by closely analyzing smallpt and with other sources all listed below.
Anti-Aliasing via Supersampling with Importance-Sampled Tent Distribution, from smallpt and the presentation slides about smallpt by David Cline
Russian Roulette, from this answer and smallpt
Importance Sampling of a Cosine-Weighted Hemisphere, from rorydriscoll.com
Gamma Correction, from smallpt (and the German Wikipedia has short and good explanations here)
Uniform Sampling of a Hemisphere, from scratchapixel.com
Monte Carlo Path Tracing, from scratchapixel.com and smallpt
Phong Shading, known from my studies in advance
Ray-Sphere Intersection, from scratchapixel.com
10.09.17 - diff
Added supersampling as done in smallpt as an anti-aliasing technique. This significantly improved the image quality by smoothing all edges. Note that I also added a black front side to the room in this step (as done in smallpt) which basically limits/decreases the room depth, but this is a minor detail.
| without supersampling | with supersampling |
|---|---|
![]() |
![]() |
08.09.17 - diff
Added Russian Roulette to randomly terminate a traced path. This makes the Monte Carlo integration (mathematically) unbiased (source). Ultimately, this technique allows a raytracer to include more (meaningful) radiance contributions in a traced path without much extra computational costs. Achieved improvements are shown below.
| fixed path termination after 5 bounces | random path termination with Russian Roulette |
|---|---|
![]() |
![]() |
The differences are subtle but important nonetheless. In a close side by side comparison, you can see that the shadows are generally a bit brighter with Russian Roulette, because of the increased number of radiance contributions in each traced path. Also, for the same reason, the shadows below the balls received more reflected radiance from nearby surfaces and the surfaces' respective color is more visible at these areas.
02.09.17 - diff
Added the gamma correction of 2.2 from smallpt. Finally, my images are as bright as smallpt's, I've been wondering why they weren't.
Added importance sampling with a cosine-weighted hemisphere. This is a pretty big step. First, I finally understood why smallpt does not include Lambert's cosine law or a PDF explicitly. Both coefficients are included, of course, but the terms cancel each other out pretty nicely in the Monte Carlo integration. Then, rendering with the same amount of samples leads to significantly better results. This is the main advantage of choosing importance sampling over uniform sampling. The table below shows the achieved improvements.
| # samples per pixel | with uniform sampling | with importance sampling |
|---|---|---|
| both 100 | ![]() |
![]() |
| both 1000 | ![]() |
![]() |
| 10000 vs 5000 | ![]() |
![]() |
Importance sampling achieves significantly less noise with the same number of samples. Also, 5000 samples per pixel with importance sampling generate an image similar to, or even better than, 10000 samples per pixel with uniform sampling in terms of visual quality. Ultimately, it saves half the computation time in this case.
01.09.17 - diff
After quite a lot of experimenting and analyzing the implementations of smallpt and scratchapixel.com, I feel confident in understanding the practice of Monte Carlo path tracing. Multiple ray bounces allow for indirect lighting and adding explicit direct or ambient lighting is no longer necessary. Also, they make rendering ideal specular surfaces pretty simple. The image below was again rendered with 10000 samples per pixel and each sample ray bounced 5 times after it hit a diffuse surface for the first time. As expected, rendering this image was about 5 times slower than rendering the image before, since the runtime is pretty much linear in the number of ray bounces.
22.08.17 - diff
Managed to render the smallpt scene with an area light source. This setup uses very basic Monte Carlo path tracing where the rays only bounce once. Still, it generates soft shadows visible on the floor in the image below which was rendered with 10000 samples per pixel.
20.08.17 - diff
Managed to render the smallpt scene with a point light source (instead of an area light source) and diffuse lighting plus hard shadows as a start. Most of this practice was known from my studies in advance.










