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();