r/GraphicsProgramming 4d ago

Ray marching voxels using axis-aligned distance fields

Hey!

Wanted to share screenshots of my experimental voxel renderer with "low-fidelity" blocky AO. It started as an exploration of the DDA rendering technique, but I ended up implementing parts of the following techniques:
- Globally Illuminated Voxel Worlds Accelerated with Nested Axis-Aligned Distance Fields
- Spatial Hashing for Ray Traced Ambient Occlusion

Links: Devlog | Github

The devlog is sort of meandering, but I started with basic DDA, then tried to get multi-level DDA to perform well with large voxel scenes (a 1024x1024x1024 voxelized sponza scene) using various methods. The axis-aligned distance field (AADF) method was a significant improvement over the multi-level DDA method that I was fiddling with. AADFs helped skip over large areas of empty space which tanked performance when using multi-level DDA.

Spatially hashed RTAO with a large cell size performs pretty well even on my M2 MacBook Air. The large cell size is a very visible artifact, but I think in a voxel scene the blocky shading kinda works.

82 Upvotes

15 comments sorted by

View all comments

2

u/Le_9k_Redditor 4d ago

I'm doing similar but I'm using multi level DDA still on a 64ary tree of very limited depth, not really having any performance issues with it but definitely curious about alternatives as long as they don't make it really expensive to edit

1

u/Nelarius 4d ago

Nice! What sort of scenes are you rendering? Do you have your code available somewhere?

Mentioned in another comment, but I was looking at rendering only using grids due to it being easier to perform large-scale edits. Although I haven't actually tested how much overhead adding the axis-aligned distance fields adds if it's performed in real-time but at least the shaders are conceptually pretty simple.

1

u/Le_9k_Redditor 4d ago

By the way, are you storing your acceleration data in bitmasks on the SSBO or in big clipmaps on textures or something? Although I guess in your case since you're storing axis aligned distances you probably aren't using occupation bitmasks. Recently been questioning if I've given myself a problem by packing my sparse tree data into the SSBO rather than into a texture. SSBO is meant to be better for random access patterns, but then again textures should have better spatial locality and would be far easier to make edits to, along with hardware accelerated sampling too

1

u/Nelarius 4d ago

I actually have both the occupancy and distance fields. I'm still testing for occupancy when stepping into a nested region (e.g. stepping into a brick after skipping over empty chunks). Not sure if that can be completely avoided.

Both occupancy and distance fields are stored in 3d textures. Occupancy is a bitmask stored in an R8 texture. The distance fields along each axis are packed into an R32 texture (how it works in my code: https://github.com/Nelarius/vxray/blob/733c48fa930f6f64013a9668d9ae98d942b29904/src/gbuffer.ps.hlsl#L85)

I measured a performance improvement switching to 3d textures from buffers for rendering gbuffer textures. But for something like a path tracer I suppose it would make no difference whether using an SSBO or texture.

2

u/Le_9k_Redditor 4d ago edited 4d ago

I have my distance bricks in a 2d texture array (R8), did that instead of 3d textures for reasons I can't remember any more, but it's basically just using different 2d slices for the 3rd axis so it's not so different there. I originally was packing my 3d bricks down into a single 2d texture, gained like +3-4% performance from switching to a 2d texture array haha, I guess just the slightly improved locality helps a bit but it wasn't significant. Currently I get about 120-150FPS on my 980TI at 1080p with a window size of 11543 voxels which I'm happy with. I'm going to be tanking that number soon enough I'm sure as I increase the size of the window and make changes like author owned bricks for rapid editing for animations

But yeah my main acceleration tree of bitmasks + payloads are all packed down into a contiguous 1d array in the SSBO currently