Files
beyond/Assets/ThirdParty/OccaSoftware/Altos/Scripts/Runtime/Scriptable Objects/VolumetricCloudsDefinitionScriptableObject.cs
2024-11-20 15:21:28 +01:00

484 lines
17 KiB
C#

using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace OccaSoftware.Altos
{
[CreateAssetMenu(fileName = "Volumetric Cloud Definition", menuName = "Skies/Volumetric Cloud Definition")]
public class VolumetricCloudsDefinitionScriptableObject : ScriptableObject
{
private void OnValidate()
{
planetRadius = GetRadiusFromCelestialBodySelection(celestialBodySelection, planetRadius);
extinctionCoefficient = Mathf.Max(0, extinctionCoefficient);
maxLightingDistance = Mathf.Max(0, maxLightingDistance);
weathermapValueRange.x = Mathf.Clamp(weathermapValueRange.x, 0.0f, 1.0f);
weathermapValueRange.y = Mathf.Clamp(weathermapValueRange.y, 0.0f, 1.0f);
weathermapValueRange.x = Mathf.Min(weathermapValueRange.x, weathermapValueRange.y);
weathermapValueRange.y = Mathf.Max(weathermapValueRange.x, weathermapValueRange.y);
curlTextureInfluence = Mathf.Max(0, curlTextureInfluence);
curlTextureScale = Mathf.Max(0, curlTextureScale);
detail1TextureInfluence = Mathf.Clamp(detail1TextureInfluence, 0f, 1f);
detail1TextureScale = Vector3.Max(Vector3.zero, detail1TextureScale);
if (baseFalloffSelection == FalloffSelection.Custom)
{
baseTextureRGBAInfluence = SetRelativeValues01(ref baseTextureRInfluence, ref baseTextureGInfluence, ref baseTextureBInfluence, ref baseTextureAInfluence);
}
else
{
baseTextureRGBAInfluence = GetInfluenceFromFalloffSelection(baseFalloffSelection);
}
if (detail1FalloffSelection == FalloffSelection.Custom)
{
detail1TextureRGBAInfluence = SetRelativeValues01(ref detail1TextureRInfluence, ref detail1TextureGInfluence, ref detail1TextureBInfluence, ref detail1TextureAInfluence);
}
else
{
detail1TextureRGBAInfluence = GetInfluenceFromFalloffSelection(detail1FalloffSelection);
}
if (detail2FalloffSelection == FalloffSelection.Custom)
{
detail2TextureRGBAInfluence = SetRelativeValues01(ref detail2TextureRInfluence, ref detail2TextureGInfluence, ref detail2TextureBInfluence, ref detail2TextureAInfluence);
}
else
{
detail2TextureRGBAInfluence = GetInfluenceFromFalloffSelection(detail2FalloffSelection);
}
detail1TextureHeightRemap = ClampVec2_01(detail1TextureHeightRemap);
detail1TextureHeightRemap = ClampVec2_01(detail1TextureHeightRemap);
// Cache?
#if UNITY_EDITOR
GetCloudTextureReferenceData(ref textureReference);
baseTexture = GetTexture(baseTextureID, baseTextureQuality);
detail1Texture = GetTexture(detail1TextureID, detail1TextureQuality);
detail2Texture = GetTexture(detail2TextureID, detail2TextureQuality);
#endif
if (detail1Texture == null)
detail1TextureInfluence = 0.0f;
if (detail2Texture == null)
detail2TextureInfluence = 0.0f;
highAltExtinctionCoefficient = Mathf.Max(0, highAltExtinctionCoefficient);
highAltScale1 = Vector2.Max(Vector2.zero, highAltScale1);
highAltScale2 = Vector2.Max(Vector2.zero, highAltScale2);
highAltScale3 = Vector2.Max(Vector2.zero, highAltScale3);
highAltTexInfluence = SetRelativeValues01(ref highAltStrength1, ref highAltStrength2, ref highAltStrength3);
renderScale = GetRenderScalingFromRenderScaleSelection(renderScaleSelection, renderScale);
blueNoise = RoundTo2Decimals(blueNoise);
renderScale = RoundTo2Decimals(renderScale);
HGEccentricityBackward = RoundTo2Decimals(HGEccentricityBackward);
HGEccentricityForward = RoundTo2Decimals(HGEccentricityForward);
HGBlend = RoundTo2Decimals(HGBlend);
cloudiness = RoundTo2Decimals(cloudiness);
cloudinessDensityInfluence = RoundTo2Decimals(cloudinessDensityInfluence);
heightDensityInfluence = RoundTo2Decimals(heightDensityInfluence);
detail1TextureInfluence = RoundTo2Decimals(detail1TextureInfluence);
detail2TextureInfluence = RoundTo2Decimals(detail2TextureInfluence);
highAltCloudiness = RoundTo2Decimals(highAltCloudiness);
}
private void GetCloudTextureReferenceData(ref CloudTextureReferenceData crtd_ref)
{
#if UNITY_EDITOR
List<string> guids = UnityEditor.AssetDatabase.FindAssets("t:CloudTextureReferenceData").ToList();
if (guids.Count <= 0)
{
Debug.Log("No Texture Reference Data configurations present in this project. Unable to find Cloud Volume Texture Data. Exiting.");
return;
}
else
{
string assetPath = UnityEditor.AssetDatabase.GUIDToAssetPath(guids[0]);
CloudTextureReferenceData localCTRD = UnityEditor.AssetDatabase.LoadAssetAtPath<CloudTextureReferenceData>(assetPath);
if (guids.Count > 1)
Debug.Log("There are multiple Texture Reference Data configurations present in this project. Defaulted to the first identified dataset: " + localCTRD);
crtd_ref = localCTRD;
}
#endif
}
private Texture3D GetTexture(TextureIdentifier textureType, TextureQuality qualitySetting)
{
if (textureReference == null)
{
Debug.Log("Missing 3D Texture Reference Data. Trying to fetch.");
GetCloudTextureReferenceData(ref textureReference);
if (textureReference == null)
{
Debug.Log("3D Texture Reference Data not found. Exiting.");
return null;
}
}
if (textureType == TextureIdentifier.None)
return null;
for (int i = 0; i < textureReference.dataset.Count; i++)
{
bool typeMatch = textureReference.dataset[i].TextureTypeIdentifier == textureType ? true : false;
bool qualityMatch = textureReference.dataset[i].TextureQualityDefinition == qualitySetting ? true : false;
if (typeMatch && qualityMatch)
{
return textureReference.dataset[i].TextureFileReference;
}
}
Debug.Log($"Requested texture {textureType} - {qualitySetting} quality could not be found in cloud texture reference dataset.", textureReference);
return null;
}
float RoundTo2Decimals(float input)
{
return (float)System.Math.Round((double)input, 2);
}
Vector2 ClampVec2_01(Vector2 input)
{
return Vector2.Min(Vector2.one, Vector2.Max(Vector2.zero, input));
}
Vector4 SetRelativeValues01(ref float x, ref float y, ref float z, ref float w)
{
Vector4 newIn = new Vector4(x, y, z, w);
newIn = Vector4.Max(Vector4.zero, newIn);
newIn = Vector4.Min(Vector4.one, newIn);
float sum = newIn.x + newIn.y + newIn.z + newIn.w;
if (sum <= 0f)
return newIn;
newIn.x /= sum;
newIn.y /= sum;
newIn.z /= sum;
newIn.w /= sum;
x = newIn.x;
y = newIn.y;
z = newIn.z;
w = newIn.w;
return newIn;
}
Vector3 SetRelativeValues01(ref float x, ref float y, ref float z)
{
Vector3 newIn = new Vector3(x, y, z);
newIn = Vector3.Max(Vector3.zero, newIn);
newIn = Vector3.Min(Vector3.one, newIn);
float sum = newIn.x + newIn.y + newIn.z;
if (sum <= 0f)
return newIn;
newIn.x /= sum;
newIn.y /= sum;
newIn.z /= sum;
x = newIn.x;
y = newIn.y;
z = newIn.z;
return newIn;
}
private CloudTextureReferenceData textureReference = null;
// Move to Editor SO?
#region Editor States
public PageSelection pageSelection = PageSelection.Basic;
public bool lowAltitudeModelingState = false;
public bool lowAltitudeLightingState = false;
public bool lowAltitudeWeatherState = false;
public bool lowAltitudeBaseState = false;
public bool lowAltitudeDetail1State = false;
public bool lowAltitudeDetail2State = false;
public bool lowAltitudeCurlState = false;
#endregion
#region Volumetric Basic Setup
public int stepCount = 32;
public float blueNoise = 1.0f;
public Color sunColor = Color.white;
public float ambientExposure = 1.0f;
public float HGEccentricityForward = 0.6f;
public float HGEccentricityBackward = -0.2f;
public float HGBlend = 0.4f;
public float HGStrength = 1.0f;
public CelestialBodySelection celestialBodySelection;
public int planetRadius = 6378;
public float cloudLayerHeight = 0.6f;
public float cloudLayerThickness = 0.6f;
public float cloudFadeDistance = 30f;
public float fogPower = 2.0f;
public RenderScaleSelection renderScaleSelection = RenderScaleSelection.Half;
public float renderScale = 0.5f;
public bool renderInSceneView = true;
public bool taaEnabled = true;
public float taaBlendFactor = 0.1f;
public DepthCullOptions depthCullOptions = DepthCullOptions.RenderAsSkybox;
public bool subpixelJitterEnabled = true;
#endregion
#region Low Altitude
#region Rendering
public float extinctionCoefficient = 120f;
public int maxLightingDistance = 2000;
public float multipleScatteringAmpGain = 0.5f;
public float multipleScatteringDensityGain = 0.1f;
public int multipleScatteringOctaves = 3;
#endregion
#region Modeling
public float cloudiness = 0.5f;
public float distantCoverageDepth = 30f;
public float distantCoverageAmount = 0.3f;
public float heightDensityInfluence = 0.6f;
public float cloudinessDensityInfluence = 0.6f;
#endregion
#region Weather
public WeathermapType weathermapType = WeathermapType.Procedural;
public Texture2D weathermapTexture = null;
public Vector2 weathermapVelocity = Vector2.zero;
public float weathermapScale = 1.0f;
public Vector2 weathermapValueRange = new Vector2(-1.0f, 1.0f);
#endregion
#region Base Volume Model
public TextureIdentifier baseTextureID = TextureIdentifier.Perlin;
public TextureQuality baseTextureQuality = TextureQuality.Ultra;
public Texture3D baseTexture = null;
public Vector3 baseTextureScale = new Vector3(10f, 10f, 10f);
public Vector3 baseTextureTimescale = new Vector3(10f, -10f, 0f);
public FalloffSelection baseFalloffSelection = FalloffSelection.Linear;
public Vector4 baseTextureRGBAInfluence;
public float baseCurlAdjustment = 0.1f;
public float baseTextureRInfluence = 0.5f;
public float baseTextureGInfluence = 0.25f;
public float baseTextureBInfluence = 0.25f;
public float baseTextureAInfluence = 0.125f;
#endregion
#region Detail 1 Volume Model
public TextureIdentifier detail1TextureID = TextureIdentifier.Worley;
public TextureQuality detail1TextureQuality = TextureQuality.Low;
public Texture3D detail1Texture = null;
public float detail1TextureInfluence = 0.2f;
public Vector3 detail1TextureScale = new Vector3(125f, 125f, 125f);
public Vector3 detail1TextureTimescale = new Vector3(25f, -50f, 30f);
public FalloffSelection detail1FalloffSelection = FalloffSelection.Linear;
public Vector4 detail1TextureRGBAInfluence;
public float detail1TextureRInfluence = 0.4f;
public float detail1TextureGInfluence = 0.2f;
public float detail1TextureBInfluence = 0.2f;
public float detail1TextureAInfluence = 0.2f;
public Vector2 detail1TextureHeightRemap = new Vector2(0.0f, 0.3f);
#endregion
#region Detail 2 Volume Model
public TextureIdentifier detail2TextureID = TextureIdentifier.Worley;
public TextureQuality detail2TextureQuality = TextureQuality.Low;
public Texture3D detail2Texture = null;
public float detail2TextureInfluence = 0.2f;
public Vector3 detail2TextureScale = new Vector3(300f, 300f, 300f);
public Vector3 detail2TextureTimescale = new Vector3(-103f, -123f, -78f);
public FalloffSelection detail2FalloffSelection = FalloffSelection.Linear;
public Vector4 detail2TextureRGBAInfluence;
public float detail2TextureRInfluence = 0.25f;
public float detail2TextureGInfluence = 0.25f;
public float detail2TextureBInfluence = 0.25f;
public float detail2TextureAInfluence = 0.25f;
public Vector2 detail2TextureHeightRemap = new Vector2(0f, 0.5f);
#endregion
#region Detail Curl 2D Model
public Texture2D curlTexture;
public float curlTextureInfluence;
public float curlTextureScale;
public float curlTextureTimescale;
#endregion
#endregion
#region High Altitude
public float highAltExtinctionCoefficient = 0.2f;
public float highAltCloudiness = 0.5f;
public Texture2D highAltTex1 = null;
public Vector2 highAltScale1 = new Vector2(5f, 5f);
public Vector2 highAltTimescale1 = new Vector2(5f, 5f);
public float highAltStrength1 = 0.5f;
public Texture2D highAltTex2 = null;
public Vector2 highAltScale2 = new Vector2(5f, 5f);
public Vector2 highAltTimescale2 = new Vector2(5f, 5f);
public float highAltStrength2 = 0.3f;
public Texture2D highAltTex3 = null;
public Vector2 highAltScale3 = new Vector2(5f, 5f);
public Vector2 highAltTimescale3 = new Vector2(5f, 5f);
public float highAltStrength3 = 0.2f;
public Vector3 highAltTexInfluence;
#endregion
private Vector4 GetInfluenceFromFalloffSelection(FalloffSelection falloffSelection)
{
switch (falloffSelection)
{
case FalloffSelection.Linear:
return new Vector4(0.4f, 0.3f, 0.2f, 0.1f);
case FalloffSelection.Quadratic:
return new Vector4(0.53f, 0.3f, 0.13f, 0.03f);
case FalloffSelection.Cubic:
return new Vector4(0.64f, 0.27f, 0.08f, 0.01f);
case FalloffSelection.Exp:
return new Vector4(0.35f, 0.27f, 0.21f, 0.17f);
case FalloffSelection.Div:
return new Vector4(0.12f, 0.16f, 0.24f, 0.48f);
default:
return new Vector4(0.5f, 0.25f, 0.125f, 0.0625f);
}
}
private int GetRadiusFromCelestialBodySelection(CelestialBodySelection celestialBodySelection, int currentVal)
{
switch (celestialBodySelection)
{
case CelestialBodySelection.Earth:
return 6378;
case CelestialBodySelection.Mars:
return 3389;
case CelestialBodySelection.Venus:
return 6052;
case CelestialBodySelection.Luna:
return 1737;
case CelestialBodySelection.Titan:
return 2575;
case CelestialBodySelection.Enceladus:
return 252;
default:
return Mathf.Max(0, currentVal);
}
}
private float GetRenderScalingFromRenderScaleSelection(RenderScaleSelection renderScaleSelection, float currentVal)
{
switch (renderScaleSelection)
{
case RenderScaleSelection.Full:
return 1.0f;
case RenderScaleSelection.Half:
return 0.5f;
case RenderScaleSelection.Quarter:
return 0.25f;
default:
return Mathf.Max(0.10f, RoundTo2Decimals(currentVal));
}
}
}
public enum TextureIdentifier
{
None,
Perlin,
PerlinWorley,
Worley
}
public enum TextureQuality
{
Low,
Medium,
High,
Ultra
}
public enum PageSelection
{
Basic,
LowAltitude,
HighAltitude
}
public enum FalloffSelection
{
Linear,
Quadratic,
Cubic,
Exp,
Div,
Custom
}
public enum CelestialBodySelection
{
Earth,
Mars,
Venus,
Luna,
Titan,
Enceladus,
Custom
}
public enum RenderScaleSelection
{
Full,
Half,
Quarter,
Custom
}
public enum DepthCullOptions
{
RenderAsSkybox,
RenderLocal
}
public enum WeathermapType
{
Procedural,
Texture
}
}