Efficient HDRP/URP terrain detail meshes with compute shaders

Hi all,
here is my attempt at using compute shaders for detail mesh instancing:

Benefits for artists:

  • You only need to attach one script to existing terrain objects and it should “just work”.

  • Fast HDRP grass, for free! You may still want to buy VegetationStudio (and the like) for better support and more features, though…

  • Detail meshes can cast and receive shadows (with a certain FPS drop, of course).

  • All shaders I implemented for HDRP/URP use Shader Graph, so you can easily extend them. The only difference between the shader graphs is the render target.

  • I included a Shader Graph for cute butterflies (to demonstrate how to use per-instance random values).

  • A rudimentary wind Shader Graph is implemented and can be modified easily.

  • Large-scale terrains with many trees and large viewing distances are also possible (see second screenshot, description in the gitlab project linked above).

Benefits for programmers:

  • This is an example project for the use of compute shaders. I was astonished how easy it is to use them, and that there is a stack on the GPU (using append/consume buffers) that can be utilized with thousands of threads. I learned a lot from this CatLikeCoding article.

  • Culling is implemented for the GPU/GPU setting. I am sure it can be improved, but it makes the whole instancing much more efficient already.

  • All code / shaders / models are open source, MIT license.

  • The instancing script can be set to only use the CPU, which means the target hardware does not need to support compute shaders. Obviously, there is a steep FPS drop (about 75% less).

  • I also included an example shader for the standard render pipeline, to test performance in this setting. Interestingly, the pure CPU based version of my code seems to be en par with the old system, and the new GPU version is faster.

  • A per-instance random value is passed to the shader. This is interesting for various reasons, the butterfly is just an example. The existing terrain system in the standard pipeline uses a similar thing to color each mesh slightly differently.

Let me know what you think! I am sure there is a lot that can be improved.
Disclaimer: this is just a hobby project where I learned a lot about compute shaders.

10 Likes

Nice job, I might try it for fun.

pretty cool!
the density only works well with smaller terrains - anything can be done to have it working on 1000x1000 terrains, for example?
thx!

Thanks! The GPU was reinstanced too often, and the detail distance was too small. Now the larger terrains should also work. I included a sample scene with 3*3 terrains, in total 6000m x 6000m.