From 57498b9bb12e9a909a0caa1139711bc9dce6e1cd Mon Sep 17 00:00:00 2001 From: Tom Boullay Date: Thu, 28 May 2026 01:08:33 +0200 Subject: [PATCH] tune(environment): rebalance procedural grass zones --- src/world/grass/GrassPatch.tsx | 9 ++++++--- src/world/grass/grassConfig.ts | 9 ++++++--- src/world/grass/grassShaders.ts | 26 ++++++++++++++++++-------- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/world/grass/GrassPatch.tsx b/src/world/grass/GrassPatch.tsx index 53c3e09..e1a6c68 100644 --- a/src/world/grass/GrassPatch.tsx +++ b/src/world/grass/GrassPatch.tsx @@ -153,14 +153,17 @@ function createGrassMaterial( uClumpThreshold: { value: GRASS_CONFIG.clumpThreshold }, uClumpSoftness: { value: GRASS_CONFIG.clumpSoftness }, uZoneFrequency: { value: GRASS_CONFIG.zoneFrequency }, + uNoGrassZoneThreshold: { value: GRASS_CONFIG.noGrassZoneThreshold }, uSparseZoneThreshold: { value: GRASS_CONFIG.sparseZoneThreshold }, - uTallZoneThreshold: { value: GRASS_CONFIG.tallZoneThreshold }, + uMediumZoneThreshold: { value: GRASS_CONFIG.mediumZoneThreshold }, uZoneSoftness: { value: GRASS_CONFIG.zoneSoftness }, + uNoGrassZoneHeight: { value: GRASS_CONFIG.noGrassZoneHeight }, uSparseZoneHeight: { value: GRASS_CONFIG.sparseZoneHeight }, - uLowZoneHeight: { value: GRASS_CONFIG.lowZoneHeight }, + uMediumZoneHeight: { value: GRASS_CONFIG.mediumZoneHeight }, uTallZoneHeight: { value: GRASS_CONFIG.tallZoneHeight }, + uNoGrassZoneDensity: { value: GRASS_CONFIG.noGrassZoneDensity }, uSparseZoneDensity: { value: GRASS_CONFIG.sparseZoneDensity }, - uLowZoneDensity: { value: GRASS_CONFIG.lowZoneDensity }, + uMediumZoneDensity: { value: GRASS_CONFIG.mediumZoneDensity }, uTallZoneDensity: { value: GRASS_CONFIG.tallZoneDensity }, uMaxBendAngle: { value: GRASS_CONFIG.maxBendAngle }, uMaxBladeHeight: { value: GRASS_CONFIG.maxBladeHeight }, diff --git a/src/world/grass/grassConfig.ts b/src/world/grass/grassConfig.ts index eaaaca5..fa6a805 100644 --- a/src/world/grass/grassConfig.ts +++ b/src/world/grass/grassConfig.ts @@ -17,14 +17,17 @@ export const GRASS_CONFIG = { clumpThreshold: 0.18, clumpSoftness: 0.45, zoneFrequency: 0.035, + noGrassZoneThreshold: 0.2, sparseZoneThreshold: 0.4, - tallZoneThreshold: 0.8, + mediumZoneThreshold: 0.65, zoneSoftness: 0.08, + noGrassZoneHeight: 0, sparseZoneHeight: 0.08, - lowZoneHeight: 0.45, + mediumZoneHeight: 0.45, tallZoneHeight: 1, + noGrassZoneDensity: 0, sparseZoneDensity: 0.08, - lowZoneDensity: 0.72, + mediumZoneDensity: 0.72, tallZoneDensity: 1, maxBendAngle: 14, } as const; diff --git a/src/world/grass/grassShaders.ts b/src/world/grass/grassShaders.ts index 02d6f9f..dbbb527 100644 --- a/src/world/grass/grassShaders.ts +++ b/src/world/grass/grassShaders.ts @@ -26,14 +26,17 @@ export const grassVertexShader = /* glsl */ ` uniform float uClumpThreshold; uniform float uClumpSoftness; uniform float uZoneFrequency; + uniform float uNoGrassZoneThreshold; uniform float uSparseZoneThreshold; - uniform float uTallZoneThreshold; + uniform float uMediumZoneThreshold; uniform float uZoneSoftness; + uniform float uNoGrassZoneHeight; uniform float uSparseZoneHeight; - uniform float uLowZoneHeight; + uniform float uMediumZoneHeight; uniform float uTallZoneHeight; + uniform float uNoGrassZoneDensity; uniform float uSparseZoneDensity; - uniform float uLowZoneDensity; + uniform float uMediumZoneDensity; uniform float uTallZoneDensity; uniform float uMaxBendAngle; uniform float uMaxBladeHeight; @@ -88,16 +91,23 @@ export const grassVertexShader = /* glsl */ ` float clumpNoise = texture2D(uNoiseTexture, clumpUv).r; float clumpMask = smoothstep(uClumpThreshold, uClumpThreshold + uClumpSoftness, clumpNoise); float zoneNoise = texture2D(uNoiseTexture, worldPos.xz * uZoneFrequency).r; - float sparseZone = 1.0 - smoothstep(uSparseZoneThreshold, uSparseZoneThreshold + uZoneSoftness, zoneNoise); - float tallZone = smoothstep(uTallZoneThreshold, uTallZoneThreshold + uZoneSoftness, zoneNoise); - float midZone = clamp(1.0 - sparseZone - tallZone, 0.0, 1.0); + float noGrassZone = 1.0 - smoothstep(uNoGrassZoneThreshold, uNoGrassZoneThreshold + uZoneSoftness, zoneNoise); + float sparseZone = + smoothstep(uNoGrassZoneThreshold, uNoGrassZoneThreshold + uZoneSoftness, zoneNoise) * + (1.0 - smoothstep(uSparseZoneThreshold, uSparseZoneThreshold + uZoneSoftness, zoneNoise)); + float mediumZone = + smoothstep(uSparseZoneThreshold, uSparseZoneThreshold + uZoneSoftness, zoneNoise) * + (1.0 - smoothstep(uMediumZoneThreshold, uMediumZoneThreshold + uZoneSoftness, zoneNoise)); + float tallZone = smoothstep(uMediumZoneThreshold, uMediumZoneThreshold + uZoneSoftness, zoneNoise); float zoneHeight = + noGrassZone * uNoGrassZoneHeight + sparseZone * uSparseZoneHeight + - midZone * uLowZoneHeight + + mediumZone * uMediumZoneHeight + tallZone * uTallZoneHeight; float zoneDensity = + noGrassZone * uNoGrassZoneDensity + sparseZone * uSparseZoneDensity + - midZone * uLowZoneDensity + + mediumZone * uMediumZoneDensity + tallZone * uTallZoneDensity; float bladeVisibility = step(random(worldPos.xz), zoneDensity); float heightModifier = uMaxBladeHeight * mix(0.35, 1.0, heightNoiseAverage) * uHeightNoiseAmplitude;