Smallpaint is a renderer program implementing the classic Monte Carlo path tracing global illumination algorithm. Looking at the images above, you may not see what you would expect from a such a ray tracer: it has an interesting look which resembles the viewer of a painting. Please meet smallpaint.
- implementation in ~250 effective lines of code,
- multi-threaded rendering thanks to the OpenMP library,
- some c++11 wizardry (ty CsL!),
- quasi-monte carlo sampling using low-discrepancy Halton series,
- cosine importance sampling,
- faster convergence through next event estimation (currently removed),
- soft shadows, antialiasing by integrating over the screen pixels (path tracing),
- refractions, color bleeding, caustics,
- can be compiled into a binary with less than 4096 bytes (an image of the full binary),
- …and most importantly: a great painterly look. Hence, it is called smallpaint,
- (new) algorithms implemented as of early 2017: path tracing, volumetric path tracing, primary sample space metropolis light transport, progressive photon mapping, 1D multiple importance sampling.
Knobs and switches
- adjust the params[“spp”] to acquire a clearer or grainier picture of your choice,
- pick a refraction index for the glass sphere with params[“refr_index”],
- tinkering around with the rest of the code is completely up to you!
What’s causing this?
The cause of the painterly look is actually a bug – there’s an incorrect usage of the Halton-series with correlating dimensions, and the errors are spread throughout the screen with an equally wrong sampling function. one would wish that every bug could look just as beautiful as this one.
If you take a closer look at the source code, you may notice that smallpaint doesn’t do any kind of tone mapping – it directly writes the measured contributions into the image file. Also, there are some magic constants used as scaling factors here and there.
When doing ray tracing, the goal is to compute the radiance returning to the eye along rays of light through each pixel of an image. As a last step, we map these values to – for example – RGB values for visualization. Trying to measure RGB intensities directly does not make any sense, and is also scientifically unacceptable. The reason for omitting this from smallpaint is solely to save a few lines of code. Your computer graphics professor would probably throw lightning bolts at you for this.
Code walkthrough lecture
Changelog for smallpaint
fixes @ 2010.11.11
- the usage of rand() instead of rand_r() caused performance issues on linux systems.
fixes @ 2013.03.08
- the solution to the sampling problem is added as commented code,
- the fixed version of the path tracer is added to the package,
- slight code cleanup.
fixes @ 2013.05.11
- Christian Hafner adds Schlick’s approximation to the Fresnel equation. It is included in the fixed version of the code. Thank you!
fixes @ 2013.05.18
- Christian Machacek adds Russian Roulette path termination and other code improvements. It is included in the fixed version of the code. Thank you!
fixes @ 2013.07.12
- Christian Machacek adds a pbrt-inspired BVH implementation and lots of various other fixes. Thank you!
fixes @ 2013.07.15
- Jean-Baptiste Kaiser adds a neat implementation of Kelemen et. al’s Primary Sample Space Metropolis Light Transport (PSSMLT) algorithm. Good job, thank you!
improvements @ 2015.01.16
- Georg Sperl adds a volumetric path tracing variant which is now included in the code archive. Thank you!
improvements @ 2015.05.01
- Georg Sperl adds Woodcock-tracking. It can render heterogeneous volumes like this and this. Thank you!
improvements @ 2015.05.26
- I added an implementation of multiple importance sampling for two Monte Carlo estimators in 1D. Kind thanks for Jaroslav Křivánek for pushing a fix as well!
improvements @ 2017.03.21
- Michael Oppitz added a full GUI around smallpaint and a progressive photon mapping implementation. Make sure to have a look at this, it’s super fun to use. Thank you!
Also, make sure to check out Adam Celarek‘s course project as well on path tracing, bidirectional path tracing and photon tracing.
- László Szirmay-Kalos, my former computer graphics advisor,
- Michael Wimmer, my current one,
- Kevin Beason for the inspiring smallpt renderer,
- Jochen Eisner for his remarks about rand_r() and lambda functions,
- the ompf.org forum for all the good people addicted to ray tracing and global illumination,
- my students who have been hard at work to improve smallpaint and to add lots of goodies!