Voxel Cone Step Tracing - Cascaded Volumes
I had to spend several weeks just eliminating light leaks and other artifacts, and getting the results I wanted in a variety of scenes. The results are looking good. Everyone who tries implementing this technique has problems with light leaks but I have fortunately been able to avoid this with careful planning:
Now that I have nice results with a single volume texture centered at the origin, it's time to add additional stages. The idea is to have a cascading series of volume textures around the camera, where each volume is twice the dimensions (and eight times the volume) of the previous one. This allows us to cover a large area of the scene, while using lower-resolution data for parts of the scene that are further away from the camera:
Putting this into practice, in this shot you can see some ambient occlusion and reflections in the trench. (The metalness is turned up really high to make it more easily visible, so don't worry about the bright white specs.)
A little bit further from the center of the scene, we see another trench. This appears in the second GI volume with half the voxel resolution of the previous image, so it has some small artifacts. However, this will also appear further from the camera so they won't be noticeable:
The transition between stages is good enough. If you look carefully at the floor between stage 0 and 1, the reflection of the window is lost in the lower-resolution stage 1. On the wall in between stage 1 and 2 the boundary is visible. However, the camera is going to be further away so those artifacts won't be as apparent as they are now.
From the outside, we can see four 64x64x64 volume textures can be used to cover the entire train station, with a base voxel size of 12.5 centimeters.
To cover the same area with a single volume texture we would need a 512x512x512 texture. Using several cascaded volume textures brings our memory usage down to less than 1% what it would be otherwise:
64*64*64*4 = 1048576
512*512*512 = 134217728
1048576 / 134217728 * 100 = 0.78125%
There is still a lot of room for optimization. We can perform the voxelization step for all four stages in one single pass using multi-target rendering, like the pointlight shadow shader does. We could also distribute the GI stage updates so that only one gets drawn each frame, since even objects in motion probably won't cause a change in the voxelized result every single frame. Right now I am just focusing on optimizing the shader and rendering everything each frame, so I can deal with a worst case scenario before I start adding techniques that will make it harder to measure performance.
Without doing any performance tests, the rendering seems quite fast. I am not even using this in a real-time application right now, but I definitely get a feel for how responsive the viewport rendering is to mouse movement, and it seems to be very snappy so far. I can definitely bog it down if I turn up the settings too high.
There are a lot of settings that are very scalable for performance / quality such as voxel resolution, number of cascaded stages, maximum ray steps, and number of light bounces.
I've done some initial tests trying to make the volumes move around with the camera, and that produced a lot of new and strange artifacts I didn't anticipate. So I think we can expect a few more weeks of slow but steady progress as I dive into this even deeper.
There's a lot of academic papers and demos out there that show this technique, but delivering a complete solution that produces good results for any scene is quite a challenge, and I've been working on this for four years, with the last three months spent pretty much full-time, just on this feature!
But I am glad to do this, because my love for you is so great and I want you to be happy.
- 6
- 1
2 Comments
Recommended Comments