For my project, I did a realtime simulation of grass. The simulation of grass shown in the video is running at about 140 FPS on my two-year-old 11" Macbook Air. At fullscreen it runs at about 90 FPS.

The grass is rendered using GLSL vertex, geometry, and fragment shaders. The program determines where to place "seeds" based on a density constant and a random number. It passes each seed as a vertex into a vertex buffer object. This vertex buffer object represents a small square patch of seeds. In the video above, each patch contains 64 seeds.

Based on the view frustum, the program will create a model transformation matrix for each patch of seeds that needs to be rendered into grass. For each model transformation matrix, a patch of seeds is rendered.

The first GLSL shader used is the vertex shader. The vertex shader is responsible for translating each patch of seeds and for determining the height of each seed based on the terrain. The vertex shader passes the new location for each vertex to a geometry shader.

The geometry shader is run once for each vertex. The role of the geometry shader here is to take one input vertex and produce a triangle strip. Most of the calculations for the grass are done in the geometry shader, including the lighting, the wind, and the level of detail.

The geometry shader is what enables this demo to have such good performance. Above, 12,800 blades of grass are being rendered at a time. Each blade of grass has between 4 and 14 vertices depending on how close it is to the camera. The CPU would not be able to simulate the positions of 100,000 vertices, add them to a VBO, and send that VBO to the graphics card at 140 FPS on my MacBook Air.

Inspiration and help came from Realistic Real-Time Grass Rendering