Compute Shaders: Grass Rendering
This is a grass rendering system that I have worked on for some time. I wanted to make something that looked like the grass in ‘Zelda-Breath of the Wild’. Although the end result is not quite as fancy, I’m still pretty happy with it. I’ll try to briefly explain how its made in this post. You can find all the source code in the bottom of this post, along with sources for the different techniques.
The main setup is explained in the image below. A number of trample structs (containing a position and a move direction) is send to a compute shader. The compute shader calculates the grass trample direction and amount, and stores the information in a render texture.
The full grass mesh is then created in a geometry shader. This mesh is distorted by the output texture of the compute shader. Wind movement in the grass is also added by moving the straws with a fourier transform function (using the grass straw position as input).
Geometry shader
The geometry shader will build one grass object per vertex (v0). It will base this geometry on a first position above v0 (v1). When you then move v1 (by trampling and/or wind), the rest of the geometry will follow. See https://developer.nvidia.com/gpugems/GPUGems/gpugems_ch07.html for more information this technique.
Right now the grass base mesh is generated when you start the scene. This is achieved by raycasting downwards and building the mesh from the raycast hits on the ground. This process could be skipped. You could instead create a mesh in e.g. Maya and pass that to the geometry shader straight away.
Compute shader
The compute shader runs one thread per pixel in the grass distortion texture. Each pixel will therefore contain information on how the grass in that particular position is affected by all trampler objects. The output of the compute shader is shown below (although somewhat misleading since the values has to be packed from the range -1,1 to the range 0,1, making some directions have a black color).
Other scripts
There are two other scripts in this system which are important, GrassPointCloudRenderer.cs and GrassPhysics.cs. The first one creates the base mesh used by the geometry shader. The other assigns values to, and dispatches the compute shader.
Source code
Sources
- NVidia GPU gems:
- Grass rendering series by World of Zero on youtube:
https://www.youtube.com/watch?v=0H1FVOphmIo&list=PLEwYhelKHmigG2uo6zW-LNKtmYUHpC5z4