WASD / arrow keys to walk the capybara · drag to orbit · scroll to zoom · press Esc to exit

ENDLESS PROCEDURAL
GRASS FIELD

By Shane Brumback · · Free Three.js tutorial

Create thousands of animated grass blades with realistic rolling wind using Three.js InstancedMesh and custom GLSL shaders — then drop in a rigged capybara you drive with WASD while the grass regenerates around it, open-world style.

Endless procedural grass field with a rigged capybara, built in Three.js

LIVE DEMO

The dense grass field swaying behind this page is the live demo — tens of thousands of InstancedMesh blades in two grass types (tall field grass + short bright tufts) bending in a GLSL wind shader, with a rigged capybara grazing in it. Launch the full-screen demo and walk the capybara with WASD — the grass regenerates around it as you roam, open-world style. Drag to orbit, scroll to zoom. Scroll to keep reading.

Hides the page so you get it full screen — WASD to walk the capybara, drag to orbit, scroll to zoom, press Esc to exit.

Introduction

One of the most striking effects in a 3D game is a vast field of grass swaying in the wind. From open-world RPGs to calm exploration games, procedural grass adds instant life to a scene — but rendering thousands of blades in a browser without tanking the frame rate takes a couple of specific tricks.

In this tutorial you build an endless grass field with THREE.InstancedMesh and custom GLSL shaders. Here's why instancing matters: if each of the thousands of blades were its own mesh, the GPU would be told about them one at a time every frame — thousands of separate "draw calls" that grind the scene to a halt. InstancedMesh is one object that stamps the same blade shape in many places at once, so the whole field costs about as much as a single blade.

A custom vertex shader then bends each blade with a sine wave keyed to its world position, so a gust rolls across the whole meadow instead of every blade twitching in lockstep. A matching custom depth material makes the moving blades cast shadows that actually match the sway. Learn the pattern once and reuse it for wheat, reeds, fur, or crowds.

What you should know first: this is an intermediate build — you'll get the most from it if you've set up a basic Three.js scene (renderer, camera, a mesh in a render loop) and know roughly what a shader is. If that's new, start with Creating and Animating Simple 3D Objects or Animating 3D Objects with Shaders, then come back. No build tools — everything loads from a CDN.

Frequently Asked Questions

How do you create thousands of grass blades efficiently in Three.js?

Use THREE.InstancedMesh, which renders thousands of identical geometries in a single draw call. Define a simple blade shape (a few tapered triangles), then set each instance's position, rotation, and scale via an instance matrix. This can render tens of thousands of grass blades at 60fps because the GPU is told about the shape once and stamps it everywhere.

How does procedural infinite terrain work in Three.js?

Track the camera or player position and recycle grass instances that fall behind. When a grass blade moves outside the visible area, reposition it ahead of the player with a new random offset. The player perceives an endless field while only a fixed number of instances ever exist in memory.

How do you create realistic wind animation on grass with shaders?

Use a custom vertex shader that displaces the top of each grass blade with a sine wave based on time and the blade's world position. Multiply the displacement by the vertex height (via the UV) so the base stays planted while the tip sways. Reading the world position from the instance matrix makes the gust roll across the whole field instead of every blade moving in lockstep.

How do you make animated grass cast correct shadows?

The visible material and the shadow pass are two different shaders, so if only the visible shader bends the blades the shadows stay stiff and wrong. The fix is a custom depth material that runs the exact same wind displacement, assigned to mesh.customDepthMaterial, so the shadow a blade casts matches the shape you see swaying.

Is this tutorial free?

Yes. The grass field behind this page is a live Three.js demo, and the full single-file source is on the page. Signing in with Google to reveal the code is free — it takes one click and unlocks every free tutorial on the site.

What You'll Learn

  • Build grass-blade geometry from scratch with BufferGeometry — a few fanned, tapered triangles per blade.
  • Make two grass types (tall field grass + short bright tufts) as two InstancedMeshes for a fuller, denser look.
  • Render tens of thousands of blades per type, each in a single draw call, with InstancedMesh.
  • Write a custom GLSL vertex shader for a rolling wind wave keyed to world position.
  • Match the shadows to the sway with a custom customDepthMaterial.
  • Shade blades with a base-to-tip color gradient and simple lighting in the fragment shader.

How It Works

  1. Blade geometry is a handful of tapered triangles fanned around a center, built once as a BufferGeometry with UVs that run 0 at the base to 1 at the tip.
  2. One InstancedMesh stamps that blade thousands of times, each with its own position, random spin, and scale written into an instance matrix — one draw call for the whole field.
  3. A shared uTime uniform drives a wind function that reads each blade's world position from its instance matrix and bends the tip with a sine wave, scaled by the UV height so the base stays planted.
  4. A custom depth material runs the exact same wind function, so the shadows the blades cast match the shape you see swaying instead of staying stiff.
  5. The fragment shader blends a dark base color to a brighter tip and adds a little directional light and ambient occlusion for depth.
  6. The render loop advances uTime every frame so the blades and their shadows sway together.
  7. Two grass types for a fuller field — a tall, thin, dark field grass and a shorter, wider, brighter tuft grass, each its own InstancedMesh with its own geometry and colors (the same two-layer trick Super Soldier Battle uses). Both run tens of thousands of dense blades.
  8. A rigged capybara drives the field — WASD moves a player group, and every frame any blade of either type that falls more than half a field behind the capybara is wrapped to the far side (and the flat ground slides with it), so the dense meadow is endless and always surrounds the player, open-world style. The Walk and Idle clips crossfade through an AnimationMixer.

What To Try Next

  • Recycle blades ahead of the camera as it moves to turn the fixed patch into a truly endless field that follows the player.
  • Add a second, higher-frequency sine wave to the wind for gusty, less uniform motion.
  • Tint the base-to-tip gradient toward yellow for wheat, or blue-green for reeds.
  • Scatter flowers or rocks as extra InstancedMeshes using the same recycle trick.
  • Drive the wind strength from a game value — weather, a passing vehicle, an explosion shockwave.