Video showcase: https://www.youtube.com/watch?v=pJSKUQJqBUs
- GrassInstancer.cs is using Unitys DrawMeshInstanced function which needs an array of Matrix4x4 to render the grass with a maximum batch size of 1023
- This one is slower but has some dummy frustum culling
- GrassInstancerIndirect.cs is using Unitys DrawMeshInstancedIndirect function which uses compute buffers and has basically a unlimited batch size
- This one is way faster (about 20x times with my setup) but has no frustum culling (yet)
- 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
- Drag the script and the shader into your project
- Create an empty transform and attach the script
- Adjust the settings
- Add a spriterenderer
- with this simple trick we can get some frustum culling for free and don't have to implement it ourselves. Not the best solution but it works alright.
- Create a material with the shader (or your own shader)
- Draw Gizmos - Will draw a bounding box inside OnDrawGizmos() for debugging
- Batch Size - The size you want your batches to be. Unity's max is 1023
- Instances - The amount of grass blades or other meshes
- Range - Range of the bounding box where rays for mesh positions will be tested
- Scale min/max - You can scale your meshes randomly between a min and max value
- Steepness - Limit the steepness your meshes can be spawned on
- Rotate to ground normal - Rotates the mesh towards the ground
- Random Y axis rotation - Rotates the mesh randomly on the Y axis between a negative and positive value
- Max Y rotation - Max random Y rotation
- Recieve shadows - Depends on your material
- Terrain/Ground layer - You can define layers where your meshes can be spawned
- Material - The material you want your meshes to have
- Meshes array
- Set the mesh and shadow option for each LOD individually
The script will create a box where it shoots down raycasts to detect possible mesh positions
I got the best results with overlapping volumes
The grass does not always bend in the correct wind direction inside the shader
My approach on grass rendering isn't that optimized. You might want to have a look at Acerola's channel, he has also uploaded his code to Github: https://www.youtube.com/c/Acerola_t
Be sure to check GPU instancing on your material or it can't be instanced
For those of you who don't want to use shadergraph, here are some screenshots of how the shader works. With this you can basically rebuild it with plain code.
- Drag the script and the GrassIndirect.shader file into your project
- Create an empty transform and attach the script
- Adjust the settings
- Create a material with the shader (or your own shader)
- Draw Gizmos - Will draw a bounding box inside OnDrawGizmos() for debugging
- Instances - The amount of grass blades or other meshes
- True Instance Count - Displays the amount of instances that were actually instanced
- Range - Range of the bounding box where rays for mesh positions will be tested
- Scale min/max - You can scale your meshes randomly between a min and max value
- Steepness - Limit the steepness your meshes can be spawned on
- Rotate to ground normal - Rotates the mesh towards the ground
- Random Y axis rotation - Rotates the mesh randomly on the Y axis between a negative and positive value
- Max Y rotation - Max random Y rotation
- Recieve shadows - Depends on your material
- Terrain/Ground layer - You can define layers where your meshes can be spawned
- Material - The material you want your meshes to have
- Main Light - The main light transform of your scene
- Meshes array
- Set the mesh and shadow option for each LOD individually
The script will also create a box where it shoots down raycasts to detect possible mesh positions.
For this approach I recommend using one big volume
Approximately 2 million grass blades at 60 FPS
This approach on grass rendering needs some frustum culling still. For this, you might want to have a look at Acerola's channel, he has also uploaded his code to Github: https://www.youtube.com/c/Acerola_t
I've made a custom shader which is basically a recreation of the shadergraph. You can use your shadergraph if you are using Unity 2021.2 or higher, otherwise you won't have access to the InstanceID.