Awesome
Unity Grass Instancer
Contains C# scripts and shaders for GPU instanced grass (or any other mesh)
Made with Unity 2020.3.4f1 and HDRP 10.4.0
Also tested with Unity 2022.3.40f1 and URP 14.0.11
Video showcase: https://www.youtube.com/watch?v=3SGxhRqzCm8
Project contains 5 approaches
(Performance increases every step)
- (old) Plain instanced rendering using
DrawMeshInstanced
andDrawMeshInstancedIndirect
without any optimizations (click here to read more) - Frustum culled approach (click here to read more)
- Frustum culled approach with chunking (click here to read more)
- Occlusion culled approach with frustum culling and chunking (click here to read more)
- High performance approach that extends all others (click here to read more)
Requirements
- Any render pipeline (only URP and simple HDRP shader provided)
- A terrain
- SRP Batcher needs to be disabled
- Enable GPU instancing on the material
Setup
- Drag the 3D Model + the scripts of any approach into your project
- Adjust the 3D model
scale factor
in the import settings to100
- Create a new material and assign the shader
- Attach the script to an empty game object
- enable draw gizmos
- position it at the center of your terrain
- configure the range so it fits your terrain size
Important settings
Note: some settings don't apply to all approaches.
Instances
- The amount of grass blades that can be instanced. Works best with powers of 2True instance count
- Will be set by the script. Contains the true count of instances since some can be skipped. For example if the terrain is to steep.Visible instance count
- Will be set by the script. Contains the amount of instances currently visible and thus being rendered.Scale min and scale max
- Used to create a random size for each grass bladeGround layer
- The layer of your terrain.Chunk size
- The size in meters of a chunk. Works best with powers of 2.Threads chunk render
- The amount of thread groups set in the compute shader. Has to match this setting. This also works best with powers of 2.Depth bias
- value that will be subtracted from the sampled depth texture. Used to fine tune the culling of occluded chunks.
FAQ
Why can't I see any instances?
This can have numerous reasons.
First be sure to check the requirements and setup sections. Make sure the mesh is scaled correctly.
Adjust the scale factor
in the import settings to your needs or use 100
if you are using the provided 3D model.
Your mesh could also be not placed or rotated correctly:
Why are all instances invisible or black?
This may happend, because you're placing the objects with the material by hand. This does not work because the shader needs and instance ID which is only provided by calling DrawMeshInstanced
and DrawMeshinstancedIndirect
for rendering. Also the _trsBuffer
which contains all the data for the instances is only initialized at start and it's needed for rendering.
Another reason could be that the shader is not compatible with your render pipeline. I currently only provide a shader for URP and a shadergraph for HDRP. The HDRP shadergraph only works with Unity 2021.2
or higher since the instance ID node does not exist in earlier versions.
If you have more issues, please open an issue here on Github.
What's next/TODOs
- New shader for HDRP
- New shader for default render pipeline
- Improve the readme files
Resources
- I got started with this project by this great video about GPU instancing: https://www.youtube.com/watch?v=eyaxqo9JV4w
- I found a lot of information about grass rendering on Acerola's youtube channel: https://www.youtube.com/c/Acerola_t
-
I'm also using his 3D-Models in my showcase
-
Glossary (terms I often use)
TRS
: Transformation, rotation and scale matrix._trsBuffer
: a compute buffer which holds allTRS matrices
for the instances and can be accessed like an array inside shaders_argsBuffer
: buffer that holds information about what mesh and how many to render forDrawMeshInstancedIndirect
batch
: a collection oftransformation matrices
forDrawMeshInstanced