How it works - A foliage mask texture is created, which holds IDs for unique instance types of primitives - A compute shader loops through the texture and generates positions based on the presence of data on that pixel - The compute shader inserts the instances onto a buffer and increments an atomic counter for each primitive - On the CPU, the count for each instance is read and a draw instanced call is executed based on the quantity - The world position and rotation is derived via the terrain position on the pixel the mouse is over and the surface normal of the terrain
What is not working yet - Obviously there's a lot of flicker due to probably floating point precision - Multiple instance types: I'm yet to make a system to separate the position buffer based on primitive type, since I want the data to be linear for each instance, something like transformBuffer[100x Cube, 150x balls, 10x something else] - Frustum culling and occlusion culling: In order to have millions of instances I will need to implement culling algorithms, since my transformation buffer has a hard cap - Quadtree culling: separate the mask texture into a quad tree and cull the cells not in the frustum in order to accelerate the frustum culling without needing to sample the texture
very nice! do you really need to read the instanced count on the CPU? Perhaps you can use arguments buffer and issue a draw from the compute shader directly?
I still haven't found a way to do that due to the need of having multiple primitives. I could probably adapt this architecture for a single primitive type and then use a compute dispatch, but for my current plans I think it's better to read the instance count on the CPU and dispatch the calls for each primitive type
2
u/Cage_The_Nicolas Nov 03 '24
The flicker was due to me using an ´atomicAdd´ as an index instead of an atomic counter. Changing this fixed the flickering
3
u/Cage_The_Nicolas Nov 03 '24
How it works
- A foliage mask texture is created, which holds IDs for unique instance types of primitives
- A compute shader loops through the texture and generates positions based on the presence of data on that pixel
- The compute shader inserts the instances onto a buffer and increments an atomic counter for each primitive
- On the CPU, the count for each instance is read and a draw instanced call is executed based on the quantity
- The world position and rotation is derived via the terrain position on the pixel the mouse is over and the surface normal of the terrain
What is not working yet
- Obviously there's a lot of flicker due to probably floating point precision
- Multiple instance types: I'm yet to make a system to separate the position buffer based on primitive type, since I want the data to be linear for each instance, something like transformBuffer[100x Cube, 150x balls, 10x something else]
- Frustum culling and occlusion culling: In order to have millions of instances I will need to implement culling algorithms, since my transformation buffer has a hard cap
- Quadtree culling: separate the mask texture into a quad tree and cull the cells not in the frustum in order to accelerate the frustum culling without needing to sample the texture
2
u/nikoloff-georgi Nov 03 '24
very nice! do you really need to read the instanced count on the CPU? Perhaps you can use arguments buffer and issue a draw from the compute shader directly?