Apart - Grass shader

This page presents the grass shader I made for Apart, my last year's student project.

Final version of the grass shader, including color and height variation, wind simulation, color blending with terrain and player interaction.

Initial Intention

Concept art by Aude Cazottes

The objective was to create a grass shader that would reproduce the beauty of the Alps' landscapes, with its lush and abundant grass.

For that, we set several points we wanted for the grass :
- Grass patches of different colors (with variations within them)
- Cloud shadows simulation
- Characters leaving a trail when moving in the grass
- Flowery tall grass
- Wind simulation
- Size variation, with transition between tall and small grass

Color and Height Variation

For the color variation, it's a variation in each blade of grass, darkening the top of the blade following a gradient based on the color of the bottom.

To make the height variations, I add, or subtract to the object's position in the y axis based on a noise. 

To clearly spot the tall grass patches, there is another color gradient for the tall grass that is darker.

The shader is unlit, so the shadows are simulated in the shader with a custom HLSL node.

Wind Simulation

The wind simulation is separated in two parts :
- Basic grass swaying vertex displacement made with a scrolling noise
- Wind waves simulations, with vertex displacement and color change

Blending with ground

This part was added after the initial intention, a color blending between the ground and the base of the grass blades.

To achieve that, an orthographic camera captures a render texture of the ground, which is then sent into the shader and sampled with the good tiling to give the grass blades the right color depending on the ground underneath it.

Player Interaction

There are two different interactions with the grass, when the characters walk on grass :
- The tall grass bends away from them
- The rest of the grass is flattened, and takes it normal shape back after a few seconds

The flattening is simply done with a remap of the object's position to scale it down, while the bending is calculated with nodes based on the characters' position.

To get their position, we use another render texture, with a camera that renders particle systems attached to the characters for the flattening and set a shader variable to the player's position for the bending.