Wednesday, April 25, 2012

Improving a Ray Tracer



Here is a low-res look at a pretty ray-traced environment I'm working on.

It utilizes the nice lighting formulas from the still-frame ray-tracer I posted earlier.  More importantly, at its core it's a revamped version of my old ray tracer world from high school and uses the same speedup techniques, and as such, it's suitable as a physics environment.

This scene just shows some static particles that are centered in their bounding cubes. Pause it at some key moments and notice the reflections and refractions through everything.

All particles have continuous motions and spatial placements, but I'm not going to demonstrate that here until I fix a bug in my display function.

During late high school when I was getting better at code, I wanted to make a physics sandbox world where you could make or break anything. Using the idea that physics and light just reduce to a bunch of vector math, I built a ray-tracer, not really knowing or caring about how more common polygon-based graphics work. I made it work in real time, which is a rare thing for ray tracing. It wasn't the prettiest thing at this point, but all that was missing to make it pretty was a little lighting math - the ray tracing part (even reflections, in a later version that I lost) worked.

You can see here what it was capable of:



To avoid the inevitably slow computations of "what touches what" every timestep, I decided to use a voxel subdivision (think 3D pixels) to trivialize the problems of noticing collisions and casting out light rays into things. But I also realized that a voxel grid alone wouldn't suffice for physics interactions - not accurarely anyway, when your discretization error is as big around as your objects' details and vectors of motion.  So here, its evident that I made the voxels an invisible "behind the scenes" way to speed things up, with all objects being instead made out of particles that flow around and between these invisible grid cells.

To achieve elastic deformations, I applied Lennard-Jones like forces to stick particles together, and used the Forward Euler method for timestepping. I didn't know that either of these had real names, so of course I was confused when I hit the limits of that method's numerical stability - in this video you can see when I group particles together that my mesh is very stiff, and so not long after it deforms you can watch it go unstable.

Looking back on this code even now I have a hard time wrapping my head around how it all worked - it's the most impressive effort I've ever undertaken considering what little I had to work with (one high school physics course), and many months of thought were poured into its design.  I'll continue adapting its functionality into my newer virtual world.