From 60e61535708edce07eb6e82cf3c78edb97cf2976 Mon Sep 17 00:00:00 2001 From: Victor Giers Date: Sat, 2 May 2026 10:52:00 +0200 Subject: [PATCH] Enhance foliage rendering with quality controls and update view synchronization across hosts --- src/app/App.tsx | 10 ++++++++++ src/foliage/foliage-instanced-renderer.ts | 1 + src/runtime-three/runtime-host.ts | 5 ++++- src/viewport-three/viewport-host.ts | 5 ++++- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/app/App.tsx b/src/app/App.tsx index 4ff6c6b5..54d29b45 100644 --- a/src/app/App.tsx +++ b/src/app/App.tsx @@ -194,6 +194,11 @@ import { ADVANCED_RENDERING_SHADOW_MAP_SIZES, ADVANCED_RENDERING_SHADOW_TYPES, ADVANCED_RENDERING_TONE_MAPPING_MODES, + FOLIAGE_QUALITY_SHADOW_MODES, + MAX_FOLIAGE_QUALITY_DENSITY_MULTIPLIER, + MAX_FOLIAGE_QUALITY_MAX_DISTANCE_MULTIPLIER, + MIN_FOLIAGE_QUALITY_DENSITY_MULTIPLIER, + MIN_FOLIAGE_QUALITY_MAX_DISTANCE_MULTIPLIER, areWorldSettingsEqual, changeWorldBackgroundMode, cloneWorldSettings, @@ -211,6 +216,7 @@ import { type AdvancedRenderingShadowMapSize, type AdvancedRenderingShadowType, type AdvancedRenderingToneMappingMode, + type FoliageQualityShadowMode, type WorldShaderSkySettings, type WorldSettings } from "../document/world-settings"; @@ -1150,6 +1156,10 @@ function readUnitIntervalNumberDraft(source: string, label: string): number { return value; } +function clampNumber(value: number, min: number, max: number): number { + return Math.min(max, Math.max(min, value)); +} + function assertAdvancedRenderingDistanceFogRange( distanceFog: AdvancedRenderingDistanceFogSettings ) { diff --git a/src/foliage/foliage-instanced-renderer.ts b/src/foliage/foliage-instanced-renderer.ts index 7db3e27f..d0e846f0 100644 --- a/src/foliage/foliage-instanced-renderer.ts +++ b/src/foliage/foliage-instanced-renderer.ts @@ -142,6 +142,7 @@ function scaleFoliageLayerRegistryDensities( function createRenderViewFromCamera(camera: Camera): FoliageRenderView { camera.updateMatrixWorld(); + camera.matrixWorldInverse.copy(camera.matrixWorld).invert(); const cameraPosition = new Vector3(); camera.getWorldPosition(cameraPosition); const projectionViewMatrix = new Matrix4().multiplyMatrices( diff --git a/src/runtime-three/runtime-host.ts b/src/runtime-three/runtime-host.ts index 0d433096..80da7830 100644 --- a/src/runtime-three/runtime-host.ts +++ b/src/runtime-three/runtime-host.ts @@ -5030,8 +5030,10 @@ export class RuntimeHost { this.foliageRenderer.sync({ terrains: runtimeScene.foliage.terrains, foliageLayers: runtimeScene.foliage.layers, - foliagePrototypes: runtimeScene.foliage.prototypes + foliagePrototypes: runtimeScene.foliage.prototypes, + quality: runtimeScene.world.advancedRendering.foliage }); + this.foliageRenderer.updateView(this.camera); } private disposeUniqueMaterials(materials: Material[]) { @@ -5363,6 +5365,7 @@ export class RuntimeHost { } this.updateTerrainLodVisibility(); + this.foliageRenderer.updateView(this.camera); this.updateUnderwaterSceneFog(); this.syncCelestialShadowState(); diff --git a/src/viewport-three/viewport-host.ts b/src/viewport-three/viewport-host.ts index 7bb103f4..50e047c8 100644 --- a/src/viewport-three/viewport-host.ts +++ b/src/viewport-three/viewport-host.ts @@ -6657,8 +6657,10 @@ export class ViewportHost { this.foliageRenderer.sync({ terrains: document.terrains, foliageLayers: document.foliageLayers, - foliagePrototypes: document.foliagePrototypes + foliagePrototypes: document.foliagePrototypes, + quality: document.world.advancedRendering.foliage }); + this.foliageRenderer.updateView(this.getActiveCamera()); } private createTerrainRenderObjects(terrain: Terrain): TerrainRenderObjects { @@ -11569,6 +11571,7 @@ export class ViewportHost { this.updateGridPositioning(); this.updateTransformGizmoPose(); this.updateTerrainLodVisibility(); + this.foliageRenderer.updateView(this.getActiveCamera()); this.volumeTime += dt; for (const uniform of this.volumeAnimatedUniforms) {