metaverse-vegetation
v0.1.0
Published
ES module Three.js point-based vegetation rendering with PBR instanced sprite parts for grasses, flowers, shrubs, trees, firs, and bamboo
Maintainers
Readme
metaverse-vegetation
Three.js vegetation rendering for points in space. You provide positions; the library efficiently batches diverse grasses, flowers, understory plants, bushes, broadleaf trees, autumn trees, fir trees, and bamboo into instanced transparent sprite parts.
This package does not assume a terrain implementation. A terrain, navmesh, biome system, hand-authored scatter map, or server stream can all produce the same simple VegetationPoint[] input.
Install
npm install metaverse-vegetation threeRequires three >= 0.160. The module imports three/addons/utils/BufferGeometryUtils.js.
Usage
import * as THREE from 'three';
import { VegetationLayer } from 'metaverse-vegetation';
const scene = new THREE.Scene();
const points = [
{ x: 0, y: 0, z: 0, kind: 'pine', scale: 1.6 },
{ x: 3, y: 0, z: -2, kind: 'bush' },
{ x: -1, y: 0, z: 4, kind: 'flower', color: 0xff77aa },
{ position: [2, 0, 5], kind: 'grass', rotation: Math.PI * 0.25 },
];
const vegetation = new VegetationLayer({ scene, points }).init();
vegetation.setSunDirection([0.35, 0.8, 0.45]).setWind(25, 0.08);
function animate(time) {
vegetation.update(time / 1000); // optional wind sway
renderer.render(scene, camera);
requestAnimationFrame(animate);
}Sun And Wind
The API mirrors the companion terrain and sky packages:
vegetation.setSunDirection(sunLight.position);
vegetation.setWindDirection([1, 0.3]);
vegetation.setWindSpeed(0.08);
vegetation.setWind(25, 0.12); // degrees plus speedsunDirection affects sprite-part shading. windDirection and windSpeed drive grass/leaf sway in the vertex shader.
Points
Each point can be an object or a [x, y, z] array.
type VegetationPoint = {
x?: number;
y?: number;
z?: number;
position?: [number, number, number];
kind?: 'grass' | 'flower' | 'bush' | 'tree' | 'pine' | string;
scale?: number;
rotation?: number;
leanX?: number;
leanZ?: number;
color?: THREE.ColorRepresentation;
};Generating Points
Use your own placement code, or start with the included helpers.
import { createVegetationPoints, createVegetationPointsFromHeightMap } from 'metaverse-vegetation';
const meadow = createVegetationPoints({
count: 2000,
area: 120,
mix: [
{ kind: 'grass', weight: 5, height: [0.35, 0.9], width: [0.7, 1.2] },
{ kind: 'whiteFlower', weight: 1, height: [0.55, 1.1] },
{ kind: 'shrub', weight: 0.25, height: [0.8, 1.6], width: [1.0, 1.8] },
],
sample: (x, z) => ({ y: getGroundHeight(x, z) }),
});
const terrainPoints = createVegetationPointsFromHeightMap({
heightMap,
samples: 257,
regionSize: 256,
count: 3000,
filter: ({ y }) => y > waterLevel + 0.5,
});mix items support kind, weight, density, height, width, scale, lean, and color. height is interpreted as an approximate target height in world units/meters for that plant kind. width controls horizontal spread, so the same plant kind can become short beach scrub, waist-high understory, or tall rainforest growth.
PBR Materials
Plant parts use THREE.MeshStandardMaterial by default, so they participate in PBR lighting, shadows, fog, and environment lighting. Tune the shared material response per layer:
new VegetationLayer({
scene,
points,
material: {
roughness: 0.88,
metalness: 0,
envMapIntensity: 1.0,
},
}).init();Transparent Sprite Edges
Vegetation textures default to cutout-friendly sampling to reduce pale halos around alpha edges:
new VegetationLayer({
scene,
points,
alphaTest: 0.42,
textureFiltering: 'cutout', // disables mipmaps and premultiplies alpha
}).init();Use textureFiltering: 'mipmap' if distant minification matters more than crisp cutout edges for your scene.
The repo also includes scripts/process-textures.py for maintainers. It trims transparent PNG bounds and bleeds nearby RGB colors into transparent texels to reduce halos from filtered alpha edges.
Textures
The package ships generated transparent PNG sprite parts in textures/:
| File | Use |
|------|-----|
| textures/leaf-cluster.png | Realistic deciduous tree canopies and bushes |
| textures/branch.png | Realistic trunk and branch planes |
| textures/grass-blades.png | Basic grass and flower stems |
| textures/meadow-grass.png | Mixed meadow grass with seed heads |
| textures/dry-grass.png | Dry prairie/desert grass |
| textures/fern.png | PNW understory fern clusters |
| textures/flower-stems.png | Flower stems and small leaves |
| textures/flower-head.png | Pink flower blossoms |
| textures/flower-white.png | White flower blossoms |
| textures/flower-purple.png | Purple flower blossoms |
| textures/shrub.png | Dense leafy shrubs |
| textures/shrub-base.png | Woody shrub bases/root crowns |
| textures/berries.png | Berry bush accents |
| textures/autumn-leaves.png | Orange/red deciduous foliage |
| textures/broadleaf-canopy.png | Summer broadleaf canopy clusters |
| textures/pine-needles.png | Douglas fir / pine needle clusters for PNW conifers |
| textures/bamboo-stalks.png | Segmented bamboo stalk clusters |
| textures/bamboo-leaves.png | Bamboo leaf clusters |
By default, VegetationLayer loads ./textures/..., which is correct when the package is served from its root. In examples or bundlers, pass explicit URLs if needed:
new VegetationLayer({
scene,
points,
textureUrls: {
leaf: new URL('./textures/leaf-cluster.png', import.meta.url).href,
branch: new URL('./textures/branch.png', import.meta.url).href,
grass: new URL('./textures/grass-blades.png', import.meta.url).href,
meadowGrass: new URL('./textures/meadow-grass.png', import.meta.url).href,
flower: new URL('./textures/flower-head.png', import.meta.url).href,
pine: new URL('./textures/pine-needles.png', import.meta.url).href,
},
}).init();Custom Kinds
Kinds define which sprite parts are built at each point. Each role is instanced and batched across all matching points.
import { VegetationLayer, VEGETATION_KINDS } from 'metaverse-vegetation';
const kinds = {
...VEGETATION_KINDS,
reed: {
roles: [{ role: 'grass', texture: 'grass', width: 0.35, height: 1.8, y: 0.82, planes: 3 }],
color: 0x9aa857,
scale: [0.8, 1.4],
castShadow: false,
},
};
new VegetationLayer({ scene, points, kinds }).init();Exports
| Export | Purpose |
|--------|---------|
| VegetationLayer | Instanced renderer for vegetation points |
| createVegetationPoints | Simple seeded random point helper |
| createVegetationPointsFromHeightMap | Optional adapter for heightmap-based placement |
| VEGETATION_KINDS | Default grass, flower, plant, bush, tree, fir, and bamboo definitions |
| DEFAULT_TEXTURE_URLS | Default sprite texture URLs |
| DEFAULT_VEGETATION_OPTIONS | Defaults for seed, textures, alpha test, wind |
Demo
cd metaverse-vegetation
python3 -m http.server 8080Open http://localhost:8080/example/simple/.
License
MIT — Richard Anaya. See LICENSE.
