From 843b407bf559a3f3e713a5c2633edd784f54d79a Mon Sep 17 00:00:00 2001 From: Josef Date: Fri, 18 Jul 2025 16:45:23 +0200 Subject: [PATCH] Foliage Renderer Quality Settings --- .../Rendering/Assets/Foliage/FoliageData.cs | 2 + .../Assets/Foliage/FoliageQualitySettings.cs | 102 ++++++++++++++++++ .../Foliage/FoliageQualitySettings.cs.uid | 1 + .../Assets/Foliage/FoliageRenderLayer.cs | 19 ++-- .../Assets/Foliage/FoliageRenderer.cs | 6 ++ Runtime/Tools/Lists.cs | 55 +++++++++- 6 files changed, 176 insertions(+), 9 deletions(-) create mode 100644 Runtime/Rendering/Assets/Foliage/FoliageQualitySettings.cs create mode 100644 Runtime/Rendering/Assets/Foliage/FoliageQualitySettings.cs.uid diff --git a/Runtime/Rendering/Assets/Foliage/FoliageData.cs b/Runtime/Rendering/Assets/Foliage/FoliageData.cs index 8aba7a4..77c28bb 100644 --- a/Runtime/Rendering/Assets/Foliage/FoliageData.cs +++ b/Runtime/Rendering/Assets/Foliage/FoliageData.cs @@ -45,6 +45,8 @@ namespace Rokojori [Export] public int renderPriority; + [Export] + public FoliageQualitySettings[] qualitySettings; [Export] diff --git a/Runtime/Rendering/Assets/Foliage/FoliageQualitySettings.cs b/Runtime/Rendering/Assets/Foliage/FoliageQualitySettings.cs new file mode 100644 index 0000000..3850a20 --- /dev/null +++ b/Runtime/Rendering/Assets/Foliage/FoliageQualitySettings.cs @@ -0,0 +1,102 @@ +using System.Collections; +using System.Collections.Generic; +using Godot; +using System; +using System.Threading.Tasks; + + + +namespace Rokojori +{ + /** + + + Resource to define foliage data + + + + + + + + */ + + [Tool] + [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Scatterer.svg") ] + public partial class FoliageQualitySettings:Resource + { + [Export( PropertyHint.Range, "0,200")] + public float qualityLevel = 100; + + [Export] + public float cellSizeMultiply = 1f; + + [Export] + public float visibilityRangeMultiply = 1f; + + + public static float GetCellSize( float quality, FoliageQualitySettings[] all, FoliageQualitySettings[] own, float ownValue ) + { + if ( own != null && own.Length > 0 ) + { + return ComputeCellSize( quality, all, ownValue ); + } + + if ( all != null && all.Length > 0 ) + { + return ComputeCellSize( quality, all, ownValue ); + } + + return ownValue; + } + + public static float GetVisibilityRange( float quality, FoliageQualitySettings[] all, FoliageQualitySettings[] own, float ownValue ) + { + if ( own != null && own.Length > 0 ) + { + return ComputeVisibilityRange( quality, all, ownValue ); + } + + if ( all != null && all.Length > 0 ) + { + return ComputeVisibilityRange( quality, all, ownValue ); + } + + return ownValue; + } + + static Func getQualityyLevel = ( fqs ) => fqs.qualityLevel; + + protected static float ComputeCellSize( float quality, FoliageQualitySettings[] settings, float value ) + { + if ( settings.Length == 1 ) + { + return settings[ 0 ].cellSizeMultiply * value; + } + + var closest = settings.ClosestIndex( quality, getQualityyLevel ); + var second = settings.SecondClosestIndex( closest, quality, getQualityyLevel ); + + var a = settings[ closest ]; + var b = settings[ second ]; + + return value * MathX.RemapClamped( quality, a.qualityLevel, b.qualityLevel, a.cellSizeMultiply, b.cellSizeMultiply ); + } + + protected static float ComputeVisibilityRange( float quality, FoliageQualitySettings[] settings, float value ) + { + if ( settings.Length == 1 ) + { + return settings[ 0 ].visibilityRangeMultiply * value; + } + + var closest = settings.ClosestIndex( quality, getQualityyLevel ); + var second = settings.SecondClosestIndex( closest, quality, getQualityyLevel ); + + var a = settings[ closest ]; + var b = settings[ second ]; + + return value * MathX.RemapClamped( quality, a.qualityLevel, b.qualityLevel, a.visibilityRangeMultiply, b.visibilityRangeMultiply ); + } + } +} \ No newline at end of file diff --git a/Runtime/Rendering/Assets/Foliage/FoliageQualitySettings.cs.uid b/Runtime/Rendering/Assets/Foliage/FoliageQualitySettings.cs.uid new file mode 100644 index 0000000..d9aa733 --- /dev/null +++ b/Runtime/Rendering/Assets/Foliage/FoliageQualitySettings.cs.uid @@ -0,0 +1 @@ +uid://bdcpb8ug5evdx diff --git a/Runtime/Rendering/Assets/Foliage/FoliageRenderLayer.cs b/Runtime/Rendering/Assets/Foliage/FoliageRenderLayer.cs index eb34cc2..7186efc 100644 --- a/Runtime/Rendering/Assets/Foliage/FoliageRenderLayer.cs +++ b/Runtime/Rendering/Assets/Foliage/FoliageRenderLayer.cs @@ -48,14 +48,19 @@ namespace Rokojori { gpuFoliageShaderMaterial.cameraPosition.Set( renderer.GetAssignedCamera().GlobalPosition ); - var sizeInt = Mathf.CeilToInt( data.visibilityRange / data.cellSize ) * 2; + - if ( _lastCellSize != data.cellSize || _lastMaxVisibility != data.visibilityRange ) + var cellSize = FoliageQualitySettings.GetCellSize( renderer.quality, renderer.qualitySettingsAll, data.qualitySettings, data.cellSize ); + var visibilityRange = FoliageQualitySettings.GetVisibilityRange( renderer.quality, renderer.qualitySettingsAll, data.qualitySettings, data.visibilityRange ); + + var sizeInt = Mathf.CeilToInt( visibilityRange / cellSize ) * 2; + + if ( _lastCellSize != cellSize || _lastMaxVisibility != visibilityRange ) { - _lastCellSize = data.cellSize; - _lastMaxVisibility = data.visibilityRange; + _lastCellSize = cellSize; + _lastMaxVisibility = visibilityRange; - gpuFoliageShaderMaterial.cellSize.Set( data.cellSize ); + gpuFoliageShaderMaterial.cellSize.Set( cellSize ); @@ -66,8 +71,8 @@ namespace Rokojori } - var hideStart = data.visibilityRange - ( data.visibilityRange * data.visibilityFadeRelative + data.visibilityFadeAbsolute ); - gpuFoliageShaderMaterial.hideMax.Set( data.visibilityRange ); + var hideStart = visibilityRange - ( visibilityRange * data.visibilityFadeRelative + data.visibilityFadeAbsolute ); + gpuFoliageShaderMaterial.hideMax.Set( visibilityRange ); gpuFoliageShaderMaterial.hideStart.Set( hideStart ); gpuFoliageShaderMaterial.hideOffset.Set( data.visibilityFadeHidingOffset ); diff --git a/Runtime/Rendering/Assets/Foliage/FoliageRenderer.cs b/Runtime/Rendering/Assets/Foliage/FoliageRenderer.cs index f063712..0e5004a 100644 --- a/Runtime/Rendering/Assets/Foliage/FoliageRenderer.cs +++ b/Runtime/Rendering/Assets/Foliage/FoliageRenderer.cs @@ -33,6 +33,12 @@ namespace Rokojori [Export] public FoliageData[] foliage = []; + [Export( PropertyHint.Range, "0, 200" )] + public float quality = 100; + + [Export] + public FoliageQualitySettings[] qualitySettingsAll; + List renderLayers = []; [Export] diff --git a/Runtime/Tools/Lists.cs b/Runtime/Tools/Lists.cs index 2899305..9ecb5fc 100644 --- a/Runtime/Tools/Lists.cs +++ b/Runtime/Tools/Lists.cs @@ -213,7 +213,7 @@ namespace Rokojori return index; } - public static int SecondClosestIndex( List data, int closest, float compareValue, Func getValue, bool sort = false ) + public static int SecondClosestIndex( this List data, int closest, float compareValue, Func getValue, bool sort = false ) { if ( sort ) { @@ -249,7 +249,39 @@ namespace Rokojori return closest + 1; } - public static int ClosestIndex( List data, float compareValue, Func getValue ) + public static int SecondClosestIndex( this T[] data, int closest, float compareValue, Func getValue ) + { + + if ( data.Length == 1 ) + { + return 0; + } + + if ( closest == 0 ) + { + return closest + 1; + } + + if ( closest == data.Length - 1 ) + { + return data.Length - 2; + } + + var before = data[ closest - 1 ]; + var after = data[ closest + 1 ]; + + var bD = Mathf.Abs( getValue( before ) - compareValue ); + var aD = Mathf.Abs( getValue( after ) - compareValue ); + + if ( bD < aD ) + { + return closest - 1 ; + } + + return closest + 1; + } + + public static int ClosestIndex( this List data, float compareValue, Func getValue ) { var index = -1; var distance = float.MaxValue; @@ -268,6 +300,25 @@ namespace Rokojori return index; } + public static int ClosestIndex( this T[] data, float compareValue, Func getValue ) + { + var index = -1; + var distance = float.MaxValue; + + for ( int i = 0 ; i < data.Length; i++ ) + { + var d = Mathf.Abs( getValue( data[ i ] ) - compareValue ); + + if ( d < distance ) + { + index = i; + distance = d; + } + } + + return index; + } + public static List CollectIndices( List list, Func evaluator ) { var output = new List();