diff --git a/src/world/grass/GrassPatch.tsx b/src/world/grass/GrassPatch.tsx index dd8657f..53c3e09 100644 --- a/src/world/grass/GrassPatch.tsx +++ b/src/world/grass/GrassPatch.tsx @@ -152,6 +152,16 @@ function createGrassMaterial( uClumpFrequency: { value: GRASS_CONFIG.clumpFrequency }, uClumpThreshold: { value: GRASS_CONFIG.clumpThreshold }, uClumpSoftness: { value: GRASS_CONFIG.clumpSoftness }, + uZoneFrequency: { value: GRASS_CONFIG.zoneFrequency }, + uSparseZoneThreshold: { value: GRASS_CONFIG.sparseZoneThreshold }, + uTallZoneThreshold: { value: GRASS_CONFIG.tallZoneThreshold }, + uZoneSoftness: { value: GRASS_CONFIG.zoneSoftness }, + uSparseZoneHeight: { value: GRASS_CONFIG.sparseZoneHeight }, + uLowZoneHeight: { value: GRASS_CONFIG.lowZoneHeight }, + uTallZoneHeight: { value: GRASS_CONFIG.tallZoneHeight }, + uSparseZoneDensity: { value: GRASS_CONFIG.sparseZoneDensity }, + uLowZoneDensity: { value: GRASS_CONFIG.lowZoneDensity }, + uTallZoneDensity: { value: GRASS_CONFIG.tallZoneDensity }, uMaxBendAngle: { value: GRASS_CONFIG.maxBendAngle }, uMaxBladeHeight: { value: GRASS_CONFIG.maxBladeHeight }, uRandomHeightAmount: { value: GRASS_CONFIG.randomHeightAmount }, diff --git a/src/world/grass/grassConfig.ts b/src/world/grass/grassConfig.ts index 93e039e..eaaaca5 100644 --- a/src/world/grass/grassConfig.ts +++ b/src/world/grass/grassConfig.ts @@ -3,7 +3,7 @@ export const GRASS_CONFIG = { patchSize: 30, bladeCount: 32000, bladeWidth: 0.08, - maxBladeHeight: 0.36, + maxBladeHeight: 0.56, randomHeightAmount: 0.25, surfaceOffset: 0.025, heightTextureSize: 128, @@ -16,6 +16,16 @@ export const GRASS_CONFIG = { clumpFrequency: 2.6, clumpThreshold: 0.18, clumpSoftness: 0.45, + zoneFrequency: 0.035, + sparseZoneThreshold: 0.4, + tallZoneThreshold: 0.8, + zoneSoftness: 0.08, + sparseZoneHeight: 0.08, + lowZoneHeight: 0.45, + tallZoneHeight: 1, + sparseZoneDensity: 0.08, + lowZoneDensity: 0.72, + tallZoneDensity: 1, maxBendAngle: 14, } as const; diff --git a/src/world/grass/grassShaders.ts b/src/world/grass/grassShaders.ts index 2488616..02d6f9f 100644 --- a/src/world/grass/grassShaders.ts +++ b/src/world/grass/grassShaders.ts @@ -25,6 +25,16 @@ export const grassVertexShader = /* glsl */ ` uniform float uClumpFrequency; uniform float uClumpThreshold; uniform float uClumpSoftness; + uniform float uZoneFrequency; + uniform float uSparseZoneThreshold; + uniform float uTallZoneThreshold; + uniform float uZoneSoftness; + uniform float uSparseZoneHeight; + uniform float uLowZoneHeight; + uniform float uTallZoneHeight; + uniform float uSparseZoneDensity; + uniform float uLowZoneDensity; + uniform float uTallZoneDensity; uniform float uMaxBendAngle; uniform float uMaxBladeHeight; uniform float uRandomHeightAmount; @@ -77,9 +87,23 @@ export const grassVertexShader = /* glsl */ ` vec2 clumpUv = (worldPos.xz / uPatchSize) * uClumpFrequency; 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 zoneHeight = + sparseZone * uSparseZoneHeight + + midZone * uLowZoneHeight + + tallZone * uTallZoneHeight; + float zoneDensity = + sparseZone * uSparseZoneDensity + + midZone * uLowZoneDensity + + tallZone * uTallZoneDensity; + float bladeVisibility = step(random(worldPos.xz), zoneDensity); float heightModifier = uMaxBladeHeight * mix(0.35, 1.0, heightNoiseAverage) * uHeightNoiseAmplitude; heightModifier += random(terrainUv) * (uRandomHeightAmount * 0.1); heightModifier = clamp(heightModifier, 0.0, uMaxBladeHeight); + heightModifier *= zoneHeight * bladeVisibility; float edgeDistanceX = abs(origin.x) / halfPatchSize; float edgeDistanceZ = abs(origin.z) / halfPatchSize; @@ -99,7 +123,7 @@ export const grassVertexShader = /* glsl */ ` float sideFactor = (color.r == 0.1) ? 1.0 : (color.b == 0.1) ? -1.0 : 0.0; float tipFactor = color.g; - float width = smoothstep(0.02, uMaxBladeHeight * 0.85, heightModifier) * uBladeWidth; + float width = smoothstep(0.02, uMaxBladeHeight * 0.85, heightModifier) * uBladeWidth * bladeVisibility; transformed += aYaw * (width / 2.0) * sideFactor; vec3 textureColor = texture2D(uDiffuseMap, terrainUv * 10.0).rgb;