Vegetation Shaders
Vegetation Shaders
Section titled “Vegetation Shaders”Shaders for realistic wind animation on instanced vegetation including grass, trees, and bushes.
Available Shaders
Section titled “Available Shaders”import { grassWindVertexShader, treeWindVertexShader,} from '@strata-game-library/shaders';Grass Wind Shader
Section titled “Grass Wind Shader”Wind animation for grass instances:
Uniforms
Section titled “Uniforms”| Uniform | Type | Description |
|---|---|---|
uTime | float | Animation time |
uWindSpeed | float | Wind animation speed |
uWindStrength | float | Wind bend amount |
uWindDirection | vec3 | Wind direction |
uWindNoiseScale | float | Noise pattern scale |
uWindTurbulence | float | Turbulence intensity |
Usage with InstancedMesh
Section titled “Usage with InstancedMesh”import { grassWindVertexShader } from '@strata-game-library/shaders';
const grassMaterial = new THREE.ShaderMaterial({ vertexShader: grassWindVertexShader, fragmentShader: ` varying vec3 vColor; void main() { gl_FragColor = vec4(vColor, 1.0); } `, uniforms: { uTime: { value: 0 }, uWindSpeed: { value: 1 }, uWindStrength: { value: 0.3 }, uWindDirection: { value: new THREE.Vector3(1, 0, 0.5).normalize() }, uWindNoiseScale: { value: 0.05 }, uWindTurbulence: { value: 0.2 }, },});
const grassGeometry = createGrassBladeGeometry();const grassMesh = new THREE.InstancedMesh(grassGeometry, grassMaterial, 10000);Tree Wind Shader
Section titled “Tree Wind Shader”More complex wind for trees with branch hierarchy:
Uniforms
Section titled “Uniforms”| Uniform | Type | Description |
|---|---|---|
uTime | float | Animation time |
uWindSpeed | float | Wind animation speed |
uWindStrength | float | Wind bend amount |
uWindDirection | vec3 | Wind direction |
uTrunkStiffness | float | Trunk resistance to wind |
uBranchStiffness | float | Branch resistance |
uLeafStiffness | float | Leaf resistance |
import { treeWindVertexShader } from '@strata-game-library/shaders';
const treeMaterial = new THREE.ShaderMaterial({ vertexShader: treeWindVertexShader, fragmentShader: standardFragmentShader, uniforms: { uTime: { value: 0 }, uWindSpeed: { value: 0.5 }, uWindStrength: { value: 0.15 }, uWindDirection: { value: new THREE.Vector3(1, 0, 0).normalize() }, uTrunkStiffness: { value: 0.9 }, uBranchStiffness: { value: 0.5 }, uLeafStiffness: { value: 0.2 }, },});GLSL Code Samples
Section titled “GLSL Code Samples”Simple Grass Wind
Section titled “Simple Grass Wind”vec3 grassWind(vec3 position, float time, vec3 windDir, float strength) { // Height-based influence (more at top) float heightFactor = position.y;
// Wind noise float noise = sin(position.x * 0.5 + time) * cos(position.z * 0.5 + time * 0.7);
// Apply wind vec3 offset = windDir * noise * strength * heightFactor;
return position + offset;}Layered Grass Wind
Section titled “Layered Grass Wind”vec3 layeredGrassWind(vec3 position, vec3 worldPos, float time) { float heightFactor = position.y;
// Primary wind wave float primaryWave = sin(worldPos.x * uWindNoiseScale + time * uWindSpeed); primaryWave += sin(worldPos.z * uWindNoiseScale * 0.7 + time * uWindSpeed * 0.8); primaryWave *= 0.5;
// Secondary turbulence float turbulence = sin(worldPos.x * uWindNoiseScale * 3.0 + time * uWindSpeed * 2.0); turbulence *= uWindTurbulence;
// Combine float totalWind = (primaryWave + turbulence) * uWindStrength * heightFactor;
vec3 windOffset = uWindDirection * totalWind;
return position + windOffset;}Tree Branch Wind
Section titled “Tree Branch Wind”vec3 treeBranchWind(vec3 position, vec3 worldPos, float time, float stiffness) { // Distance from trunk (using vertex color or UV) float distanceFromTrunk = length(position.xz);
// Reduce effect near trunk float influence = smoothstep(0.0, 1.0, distanceFromTrunk) * (1.0 - stiffness);
// Multi-frequency wind float wind = sin(worldPos.x * 0.1 + time * uWindSpeed) * 0.5; wind += sin(worldPos.z * 0.15 + time * uWindSpeed * 0.7) * 0.3; wind += sin(time * uWindSpeed * 2.0 + distanceFromTrunk) * 0.2; // Branch flutter
vec3 offset = uWindDirection * wind * uWindStrength * influence;
return position + offset;}Leaf Flutter
Section titled “Leaf Flutter”vec3 leafFlutter(vec3 position, vec3 normal, float time, float leafStiffness) { // Random flutter per vertex float flutter = sin(time * 10.0 + position.x * 50.0) * cos(time * 8.0 + position.z * 50.0); flutter *= (1.0 - leafStiffness);
// Flutter along normal vec3 offset = normal * flutter * 0.02;
return position + offset;}Integration with Instancing
Section titled “Integration with Instancing”Per-Instance Wind Offset
Section titled “Per-Instance Wind Offset”// In vertex shader with instanceMatrixattribute vec3 instanceOffset; // Per-instance world position
void main() { // Get instance world position vec3 worldPos = (instanceMatrix * vec4(0.0, 0.0, 0.0, 1.0)).xyz;
// Apply wind based on world position vec3 windedPosition = layeredGrassWind(position, worldPos, uTime);
// Transform vec4 mvPosition = modelViewMatrix * instanceMatrix * vec4(windedPosition, 1.0); gl_Position = projectionMatrix * mvPosition;}Wind Zones
Section titled “Wind Zones”Support for multiple wind sources:
uniform vec3 uWindZones[4]; // Positionuniform float uWindZoneStrength[4]; // Strengthuniform float uWindZoneRadius[4]; // Radius
vec3 calculateWindZones(vec3 worldPos) { vec3 totalWind = uWindDirection * uWindStrength; // Base wind
for (int i = 0; i < 4; i++) { float dist = length(worldPos - uWindZones[i]); float influence = 1.0 - smoothstep(0.0, uWindZoneRadius[i], dist); vec3 zoneDir = normalize(worldPos - uWindZones[i]); totalWind += zoneDir * uWindZoneStrength[i] * influence; }
return totalWind;}Related
Section titled “Related”- Vegetation System - High-level components
- Terrain Shaders - Terrain rendering