Sunday, April 28, 2013

Single Pass GPU Voxelization Demo

I've always been very interested in learning about the latest techniques for fast and simple voxelization of polygonal meshes.  In my previous demos I took a simple surface voxelization approach where rasterized fragments from several camera views orbiting around a mesh were projected back into world space and the resulting 3D positions used as voxels.  However this method suffers from requiring multiple render passes.  Cyril Crassin and Simon Green's article, Octree-Based Sparse Voxelization Using the GPU Hardware Rasterizer, in the book OpenGL Insights discusses an approach that uses the GPU rasterizer and the geometry shader to generate voxels from a mesh in a single render pass.  The idea is quite simple.  Each triangle is projected orthographically along the dominant axis of its normal in the geometry shader.  Each fragment rasterized is then written directly to the voxel output, whether that be a 3D texture, a voxel list or a sparse voxel octree.

For this demo I just wanted to demonstrate a very simplistic implementation that was easy to follow and demonstrated only two ideas: (1) triangle reprojection in the geometry shader and (2) conservative rasterization.  As the OpenGL Insights article mentions, conservative rasterization is required to fill any holes that appear due to fragments that intersect a triangle, but whose center is not contained within the triangle, not being rasterized.  This can be toggled on and off in the demo in order to see the difference.  I'm not too happy with how the conservative rasterization causes the final voxel output to look slightly bulkier since every triangle is enlarged indiscriminately.  I'll try implementing an alternative approach that uses the fragment shader to predict whether fragments will cause holes or not and fill them in.  In the images below one can see the different when conservative rasterization is turned off (image on the left) and on (image on the right)


I'm pleasantly surprised with the speed of this single pass voxelization pipeline (even thought I'm not necessarily creating and building up a sparse voxel octree yet).  The voxelization code itself is extremely fast. On my NVIDIA Geforce 660 card I managed to achieve 700 fps and above voxelizing to a 512x512x512 3D texture when ray tracing of the resulting dataset was turned off.  By far the most expensive piece are ray tracing the 3D texture.  But that will obviously speed up when using an acceleration structure.