- It's slow, using an unnecessary and expensive x * y * z loop
- No support for per-voxel color based on a texture lookup
- There are mathematical mistakes that cause inaccuracy, and the math has to be perfect
My solution addresses these problems and only uses an x * y loop to generate the voxels. It does this by identifying the major (largest magnitude) axis of the triangle normal and using the other two axes for the X and Y axis, then finding the Z position of the triangle at each grid point along the surface.
In previous screenshots, you could see some black faces that were caused by geometry that lies outside the bounds of the voxel geometry. Some of this was caused because I was voxelizing the mesh in local space and then transforming the resulting voxels to world space. That doesn't work, because the voxel position can end up rounding off to a different coordinate than the triangle it's supposed to enclosed. The best solution is to have a low-res LOD model that is used to generate the voxel data. (It's important to make sure the voxel geometry still contains the full-resolution model.)
In the shot below you can see every single surface has a voxel to retrieve the color from. There are no texture lookups being performed in this shot, just colored voxels that were generated by reading the image pixel at each voxel position and then stored in a GPU buffer.
This means we can safely calculate which lights are visible at each voxel and store those light IDs in a texture to be retrieved instead of performing a shadowmap lookup. It also means we can calculate global illumination at each voxel, store it in a texture, and just do a single texture lookup to grab the GI lighting when the actual model is rendered, instead of calculating GI each frame.
Onwards and upwards!