#Your terrain. Your scene. Our blades.
You pass a height function and bounds. The grass bakes them once, then adds three instanced ring meshes to your scene. grass.update(dt) runs the offscreen passes, and your render loop stays renderer.render(scene, camera).
addTrampler(ball, 0.95). The blades flatten along its path, lean the way it rolled, and spring back over a few seconds.- blades drawn on high
- ~0.48 M
- blades drawn on ultra
- ~0.96 M
- LOD rings, one draw call each
- 3
- presets, one file each
- 7
#What's in the box
- Chunked LOD grass
Three rings of tiles follow the camera: full blades near, low-poly wide blades far. Each chunk is culled on the CPU and each ring is one instanced draw.
- Any terrain
heightAt(x, z),bounds, an optionalmaskfor paths, beaches and water, and an optionalcolorAttint. Baked once to textures. - One wind field
Gust fronts roll downwind across the field.
wind.patchMaterial()makes trees, flowers and your own meshes sway with the same gusts. - GPU trampling
A 160 m buffer follows the camera.
addTrampler(object, radius)flattens and pushes the grass, and it springs back. - Scatter
Streamed, deterministic trees, bushes, rocks and flowers, or your own meshes with
addLayer(). They fade out at distance and share wind and trampling. - Fireflies
Blinking additive points that hover over the terrain around a focus point. Fade them in with your night factor.
#Seven looks, ready to load
Every preset is a plain object in src/config/presets/: a grass section, a wind section, and staging hints the demo uses.
meadowMid-morning spring grass, light fog, a scatter of flowers.goldenLow sun at 17:36 behind the blades, stronger translucency.windyTall grass on steep hills, strong gusts and gust sheen.autumnRusset grass, orange leaves and falling-leaf drift.savannaSparse, clumped dry grass, warm haze and flat acacias.night22:30 under the moon, with fireflies over the field.#A field in a few lines
import * as THREE from 'three';
import { GrassSystem } from 'naturegl-grass';
const heightAt = (x, z) => 1.5 * Math.sin(x * 0.08) * Math.cos(z * 0.06);
const terrain = { heightAt, bounds: [-100, -100, 100, 100] };
const grass = await GrassSystem.create({ renderer, scene, camera, terrain, preset: 'meadow' });
grass.bindLights(sun, hemi); // sun, ambient and the sun's shadow map
grass.patchTerrainMaterial(groundMat); // turf colour on your ground, no LOD ring
grass.addTrampler(player, 0.8);
renderer.setAnimationLoop(() => {
grass.update(timer.getDelta());
renderer.render(scene, camera);
});#Gusts you can see
windy: wind speed 1.6, gust 1.2. Bent blades show their paler side, so each gust front reads as a wave of light moving downwind.#Part of the NatureGL series
NatureGL Grass takes its light from NatureGL Sky and hands its wind and terrain to the rest of the series. NatureGL Island builds its meadows with it.