Thursday, June 28, 2012

The bare necessities

I just reached the second big milestone - the first one being rendering anything coherent - for my (still unnamed) ray tracer: A reasonable Cornell box. I modelled (although the metaphor of the analog counterpart kind of breaks when you’re hard coding vertex coordinates and topology) a scene based on the “official” Cornell standard -, to see if my engine could produce anything close to the real deal. After fixing up some fireflies (it’s easy to forget lights are geometry too) and a bug where I wasn’t accounting for the solid angle of the area light geometry when evaluating a brdf, I’m actually getting results that are pretty reasonable.

There are still one or two fireflies my render - those would be rays that are hitting the tiny gap between the area light and the ceiling, and getting radiosity values of about 99% of the light source energy, (so absurdly high) but without a light source pdf for MIS to kick in and balance it out. Other differences are: My ray tracer being color based, while the reference was rendered with a spectral renderer, so the temperature of my light source behaves somewhat differently. My surface albedo values are also slightly off compared to theirs due to eyeballing the wavelength to color conversion, so my side walls are a bit brighter and more saturated, and my white material is probably off by some factor as well. Also, mine is noisy, of course, and doesn’t have as many light bounces, because my engine is still extremely slow.

Here’s another render, with a white environment light instead of the area light inside the box.

Now that I’ve reached this point it’s time to take a small step back and look at the bigger picture. There are a couple of design choices that I don’t really like, and I ended up taking a few shortcuts towards the end to get the cornell box render out faster (as in less time to write the code, not faster rendering unfortunately), so next week I’ll be refactoring most of the source. I want an interface for setting up a scene by parsing an external scene description in some human-friendly format/language rather than needing to hard code the scene into the engine itself. I also want a better separation between the front end (parsing, primitive management, dicing and building the acceleration structure) and the back end (light transport, ray intersections) so I can have a nice and abstract structure for the first, and an optimized, faster structure for the latter without the two concepts conflicting. The code base is still relatively small, so it shouldn’t be too much work.


Sunday, June 24, 2012

It's about time

I did something incredibly stupid. Again. I’ll probably be paying for this one for a long time. I started writing a ray tracer. From scratch. In c++.

Half to close at least a fraction of the knowledge gap between myself and the guys I work with, half because I’ve been wanting to do this for a while now and half to see if I could. Much like when buying that first box set of Lost season 1 I have no idea what I’m getting myself into. In any case it was about time to raise the bar from writing “Ci = Ln.Nn” and patting myself on the back as the renderer kindly popped a picture out of a black box for me. There’s something immensely satisfying about seeing that first sphere materializing on screen after days of debugging matrix operations, writing squiggly trig problems in my notebook and cursing the compiler for not spoon feeding me answers like I’m used to. It’s sort of like that feeling you get when you realize you’ve gone from being that spoiled kid with a squeaky voice to reaching manhood, except it’s absolutely meaningless and instead of getting attention from girls you have to write about it on the internet.

Stick around for updates on my struggles through the world of light transport and monte carlo optimization.

Here’s a sphere and a bunny.