summaryrefslogtreecommitdiff
path: root/DeepSky.Haze
diff options
context:
space:
mode:
Diffstat (limited to 'DeepSky.Haze')
-rw-r--r--DeepSky.Haze/DS_HazeContext.cs154
-rw-r--r--DeepSky.Haze/DS_HazeContextAsset.cs14
-rw-r--r--DeepSky.Haze/DS_HazeContextItem.cs173
-rw-r--r--DeepSky.Haze/DS_HazeCore.cs218
-rw-r--r--DeepSky.Haze/DS_HazeLightVolume.cs604
-rw-r--r--DeepSky.Haze/DS_HazeView.cs1120
-rw-r--r--DeepSky.Haze/DS_HazeZone.cs105
-rw-r--r--DeepSky.Haze/DS_LightFalloff.cs7
-rw-r--r--DeepSky.Haze/DS_SamplingQuality.cs9
9 files changed, 2404 insertions, 0 deletions
diff --git a/DeepSky.Haze/DS_HazeContext.cs b/DeepSky.Haze/DS_HazeContext.cs
new file mode 100644
index 0000000..2294526
--- /dev/null
+++ b/DeepSky.Haze/DS_HazeContext.cs
@@ -0,0 +1,154 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace DeepSky.Haze;
+
+[Serializable]
+[AddComponentMenu("")]
+public class DS_HazeContext
+{
+ [SerializeField]
+ public List<DS_HazeContextItem> m_ContextItems;
+
+ [SerializeField]
+ private int m_SoloItem = -1;
+
+ public int Solo => m_SoloItem;
+
+ public DS_HazeContext()
+ {
+ m_ContextItems = new List<DS_HazeContextItem>();
+ DS_HazeContextItem item = new DS_HazeContextItem
+ {
+ m_Name = "Default"
+ };
+ m_ContextItems.Add(item);
+ }
+
+ public void DuplicateContextItem(int index)
+ {
+ if (index >= 0 && index < m_ContextItems.Count)
+ {
+ DS_HazeContextItem dS_HazeContextItem = new DS_HazeContextItem();
+ dS_HazeContextItem.CopyFrom(m_ContextItems[index]);
+ dS_HazeContextItem.m_Name += "_Copy";
+ m_ContextItems.Add(dS_HazeContextItem);
+ }
+ }
+
+ public void RemoveContextItem(int index)
+ {
+ if (index >= 0 && index < m_ContextItems.Count && m_ContextItems.Count != 1)
+ {
+ m_ContextItems.RemoveAt(index);
+ if (m_SoloItem != -1 && m_SoloItem == index)
+ {
+ m_SoloItem = -1;
+ }
+ }
+ }
+
+ public void MoveContextItemUp(int index)
+ {
+ if (index < 1 || index >= m_ContextItems.Count)
+ {
+ return;
+ }
+ DS_HazeContextItem item = m_ContextItems[index];
+ m_ContextItems.RemoveAt(index);
+ m_ContextItems.Insert(index - 1, item);
+ if (m_SoloItem != -1)
+ {
+ if (m_SoloItem == index)
+ {
+ m_SoloItem--;
+ }
+ else if (m_SoloItem == index - 1)
+ {
+ m_SoloItem++;
+ }
+ }
+ }
+
+ public void MoveContextItemDown(int index)
+ {
+ if (index < 0 || index >= m_ContextItems.Count - 1)
+ {
+ return;
+ }
+ DS_HazeContextItem item = m_ContextItems[index];
+ m_ContextItems.RemoveAt(index);
+ m_ContextItems.Insert(index + 1, item);
+ if (m_SoloItem != -1)
+ {
+ if (m_SoloItem == index)
+ {
+ m_SoloItem++;
+ }
+ else if (m_SoloItem == index + 1)
+ {
+ m_SoloItem--;
+ }
+ }
+ }
+
+ public DS_HazeContextItem GetContextItemBlended(float time = -1f)
+ {
+ DS_HazeContextItem dS_HazeContextItem = new DS_HazeContextItem();
+ dS_HazeContextItem.CopyFrom(m_ContextItems[0]);
+ if (m_ContextItems.Count == 1)
+ {
+ return dS_HazeContextItem;
+ }
+ time = Mathf.Clamp01(time);
+ float num = 0f;
+ for (int i = 1; i < m_ContextItems.Count; i++)
+ {
+ num = m_ContextItems[i].m_Weight.Evaluate(time);
+ dS_HazeContextItem.Lerp(m_ContextItems[i], num);
+ }
+ return dS_HazeContextItem;
+ }
+
+ public DS_HazeContextItem GetItemAtIndex(int index)
+ {
+ if (index < 0 || index >= m_ContextItems.Count)
+ {
+ return null;
+ }
+ return m_ContextItems[index];
+ }
+
+ public void CopyFrom(DS_HazeContext other)
+ {
+ if (m_ContextItems.Count > 0)
+ {
+ m_ContextItems.Clear();
+ }
+ for (int i = 0; i < other.m_ContextItems.Count; i++)
+ {
+ DS_HazeContextItem dS_HazeContextItem = new DS_HazeContextItem();
+ dS_HazeContextItem.CopyFrom(other.m_ContextItems[i]);
+ m_ContextItems.Add(dS_HazeContextItem);
+ }
+ }
+
+ public DS_HazeContextAsset GetContextAsset()
+ {
+ DS_HazeContextAsset dS_HazeContextAsset = ScriptableObject.CreateInstance<DS_HazeContextAsset>();
+ dS_HazeContextAsset.Context.CopyFrom(this);
+ dS_HazeContextAsset.Context.m_SoloItem = -1;
+ return dS_HazeContextAsset;
+ }
+
+ public string[] GetItemNames()
+ {
+ string[] array = new string[m_ContextItems.Count];
+ for (int i = 0; i < m_ContextItems.Count; i++)
+ {
+ array[i] = m_ContextItems[i].m_Name;
+ }
+ return array;
+ }
+}
diff --git a/DeepSky.Haze/DS_HazeContextAsset.cs b/DeepSky.Haze/DS_HazeContextAsset.cs
new file mode 100644
index 0000000..5e4e9da
--- /dev/null
+++ b/DeepSky.Haze/DS_HazeContextAsset.cs
@@ -0,0 +1,14 @@
+using System;
+using UnityEngine;
+
+namespace DeepSky.Haze;
+
+[Serializable]
+[AddComponentMenu("")]
+public class DS_HazeContextAsset : ScriptableObject
+{
+ [SerializeField]
+ private DS_HazeContext m_Context = new DS_HazeContext();
+
+ public DS_HazeContext Context => m_Context;
+}
diff --git a/DeepSky.Haze/DS_HazeContextItem.cs b/DeepSky.Haze/DS_HazeContextItem.cs
new file mode 100644
index 0000000..d9208c9
--- /dev/null
+++ b/DeepSky.Haze/DS_HazeContextItem.cs
@@ -0,0 +1,173 @@
+using System;
+using System.Reflection;
+using UnityEngine;
+
+namespace DeepSky.Haze;
+
+[Serializable]
+[AddComponentMenu("")]
+public class DS_HazeContextItem
+{
+ public enum Multiplier
+ {
+ OneTenth,
+ OneFifth,
+ OneHalf,
+ One,
+ Two,
+ Five,
+ Ten,
+ OneHundredth
+ }
+
+ [SerializeField]
+ public string m_Name;
+
+ [SerializeField]
+ public AnimationCurve m_Weight;
+
+ [SerializeField]
+ [Range(0f, 8f)]
+ public float m_AirScatteringScale = 1f;
+
+ [SerializeField]
+ public Multiplier m_AirScatteringMultiplier = Multiplier.One;
+
+ [SerializeField]
+ [Range(0.0001f, 0.1f)]
+ public float m_AirDensityHeightFalloff = 0.001f;
+
+ [SerializeField]
+ [Range(0f, 8f)]
+ public float m_HazeScatteringScale = 1f;
+
+ [SerializeField]
+ public Multiplier m_HazeScatteringMultiplier = Multiplier.One;
+
+ [SerializeField]
+ [Range(0.0001f, 0.1f)]
+ public float m_HazeDensityHeightFalloff = 0.003f;
+
+ [SerializeField]
+ [Range(-0.99f, 0.99f)]
+ public float m_HazeScatteringDirection = 0.8f;
+
+ [SerializeField]
+ [Range(0f, 1f)]
+ public float m_HazeSecondaryScatteringRatio = 0.8f;
+
+ [SerializeField]
+ [Range(0f, 1f)]
+ public float m_FogOpacity = 1f;
+
+ [SerializeField]
+ [Range(0f, 8f)]
+ public float m_FogScatteringScale = 1f;
+
+ [SerializeField]
+ [Range(0f, 8f)]
+ public float m_FogExtinctionScale = 1f;
+
+ [SerializeField]
+ public Multiplier m_FogExtinctionMultiplier = Multiplier.One;
+
+ [SerializeField]
+ [Range(0.0001f, 1f)]
+ public float m_FogDensityHeightFalloff = 0.01f;
+
+ [SerializeField]
+ [Range(0f, 1f)]
+ public float m_FogStartDistance;
+
+ [SerializeField]
+ [Range(-0.99f, 0.99f)]
+ public float m_FogScatteringDirection = 0.7f;
+
+ [SerializeField]
+ [Range(-10000f, 10000f)]
+ public float m_FogStartHeight;
+
+ [SerializeField]
+ public Color m_FogAmbientColour = Color.white;
+
+ [SerializeField]
+ public Color m_FogLightColour = Color.white;
+
+ public DS_HazeContextItem()
+ {
+ m_Name = "New";
+ m_Weight = new AnimationCurve(new Keyframe(0.25f, 0f), new Keyframe(0.5f, 1f), new Keyframe(0.75f, 0f));
+ }
+
+ public static float MultiplierAsFloat(Multiplier mult)
+ {
+ return mult switch
+ {
+ Multiplier.OneTenth => 0.1f,
+ Multiplier.OneFifth => 0.2f,
+ Multiplier.OneHalf => 0.5f,
+ Multiplier.One => 1f,
+ Multiplier.Two => 2f,
+ Multiplier.Five => 5f,
+ Multiplier.Ten => 10f,
+ Multiplier.OneHundredth => 0.01f,
+ _ => 1f,
+ };
+ }
+
+ public static float ParamWithMultiplier(float param, Multiplier mult)
+ {
+ return mult switch
+ {
+ Multiplier.OneTenth => param * 0.1f,
+ Multiplier.OneFifth => param * 0.2f,
+ Multiplier.OneHalf => param * 0.5f,
+ Multiplier.One => param * 1f,
+ Multiplier.Two => param * 2f,
+ Multiplier.Five => param * 5f,
+ Multiplier.Ten => param * 10f,
+ Multiplier.OneHundredth => param * 0.01f,
+ _ => param * 1f,
+ };
+ }
+
+ public void Lerp(DS_HazeContextItem other, float dt)
+ {
+ if (other != null)
+ {
+ dt = Mathf.Clamp01(dt);
+ float num = 1f - dt;
+ m_AirScatteringScale = m_AirScatteringScale * num + other.m_AirScatteringScale * dt;
+ m_AirDensityHeightFalloff = m_AirDensityHeightFalloff * num + other.m_AirDensityHeightFalloff * dt;
+ m_HazeScatteringScale = m_HazeScatteringScale * num + other.m_HazeScatteringScale * dt;
+ m_HazeDensityHeightFalloff = m_HazeDensityHeightFalloff * num + other.m_HazeDensityHeightFalloff * dt;
+ m_HazeScatteringDirection = m_HazeScatteringDirection * num + other.m_HazeScatteringDirection * dt;
+ m_HazeSecondaryScatteringRatio = m_HazeSecondaryScatteringRatio * num + other.m_HazeSecondaryScatteringRatio * dt;
+ m_FogOpacity = m_FogOpacity * num + other.m_FogOpacity * dt;
+ m_FogScatteringScale = m_FogScatteringScale * num + other.m_FogScatteringScale * dt;
+ m_FogExtinctionScale = m_FogExtinctionScale * num + other.m_FogExtinctionScale * dt;
+ m_FogDensityHeightFalloff = m_FogDensityHeightFalloff * num + other.m_FogDensityHeightFalloff * dt;
+ m_FogStartDistance = m_FogStartDistance * num + other.m_FogStartDistance * dt;
+ m_FogScatteringDirection = m_FogScatteringDirection * num + other.m_FogScatteringDirection * dt;
+ m_FogStartHeight = m_FogStartHeight * num + other.m_FogStartHeight * dt;
+ m_FogAmbientColour = m_FogAmbientColour * num + other.m_FogAmbientColour * dt;
+ m_FogLightColour = m_FogLightColour * num + other.m_FogLightColour * dt;
+ }
+ }
+
+ public void CopyFrom(DS_HazeContextItem other)
+ {
+ if (other != null)
+ {
+ Type type = GetType();
+ Type type2 = other.GetType();
+ FieldInfo[] fields = type.GetFields();
+ foreach (FieldInfo fieldInfo in fields)
+ {
+ FieldInfo field = type2.GetField(fieldInfo.Name);
+ fieldInfo.SetValue(this, field.GetValue(other));
+ }
+ m_Weight = new AnimationCurve(m_Weight.keys);
+ }
+ }
+}
diff --git a/DeepSky.Haze/DS_HazeCore.cs b/DeepSky.Haze/DS_HazeCore.cs
new file mode 100644
index 0000000..30b3486
--- /dev/null
+++ b/DeepSky.Haze/DS_HazeCore.cs
@@ -0,0 +1,218 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace DeepSky.Haze;
+
+[ExecuteInEditMode]
+[AddComponentMenu("DeepSky Haze/Controller", 51)]
+public class DS_HazeCore : MonoBehaviour
+{
+ public enum HeightFalloffType
+ {
+ Exponential,
+ None
+ }
+
+ public enum NoiseTextureSize
+ {
+ x8 = 8,
+ x16 = 0x10,
+ x32 = 0x20
+ }
+
+ public enum DebugGUIPosition
+ {
+ TopLeft,
+ TopCenter,
+ TopRight,
+ CenterLeft,
+ Center,
+ CenterRight,
+ BottomLeft,
+ BottomCenter,
+ BottomRight
+ }
+
+ public static string kVersionStr = "DeepSky Haze v1.4.0";
+
+ private static int kGUIHeight = 180;
+
+ private static DS_HazeCore instance;
+
+ [SerializeField]
+ [Range(0f, 1f)]
+ [Tooltip("The time at which Zones will evaluate their settings. Animate this or set in code to create time-of-day transitions.")]
+ private float m_Time;
+
+ [SerializeField]
+ [Tooltip("The height falloff method to use globally (default Exponential).")]
+ private HeightFalloffType m_HeightFalloff;
+
+ [SerializeField]
+ private List<DS_HazeZone> m_Zones = new List<DS_HazeZone>();
+
+ [SerializeField]
+ private DebugGUIPosition m_DebugGUIPosition;
+
+ private HashSet<DS_HazeLightVolume> m_LightVolumes = new HashSet<DS_HazeLightVolume>();
+
+ [SerializeField]
+ private Texture3D m_NoiseLUT;
+
+ [SerializeField]
+ private bool m_ShowDebugGUI;
+
+ private Vector2 m_GUIScrollPosition;
+
+ private int m_GUISelectedView = -1;
+
+ private bool m_GUISelectionPopup;
+
+ private DS_HazeView m_GUIDisplayedView;
+
+ public static DS_HazeCore Instance
+ {
+ get
+ {
+ if (instance == null)
+ {
+ instance = Object.FindObjectOfType<DS_HazeCore>();
+ }
+ return instance;
+ }
+ }
+
+ public float Time
+ {
+ get
+ {
+ return m_Time;
+ }
+ set
+ {
+ m_Time = Mathf.Clamp01(value);
+ }
+ }
+
+ public Texture3D NoiseLUT => m_NoiseLUT;
+
+ public HeightFalloffType HeightFalloff
+ {
+ get
+ {
+ return m_HeightFalloff;
+ }
+ set
+ {
+ m_HeightFalloff = value;
+ SetGlobalHeightFalloff();
+ }
+ }
+
+ private void SetGlobalHeightFalloff()
+ {
+ switch (m_HeightFalloff)
+ {
+ case HeightFalloffType.Exponential:
+ Shader.DisableKeyword("DS_HAZE_HEIGHT_FALLOFF_NONE");
+ break;
+ case HeightFalloffType.None:
+ Shader.EnableKeyword("DS_HAZE_HEIGHT_FALLOFF_NONE");
+ break;
+ }
+ }
+
+ private void OnTransformChildrenChanged()
+ {
+ m_Zones.Clear();
+ DS_HazeZone[] componentsInChildren = GetComponentsInChildren<DS_HazeZone>(includeInactive: true);
+ m_Zones.AddRange(componentsInChildren);
+ }
+
+ private void Awake()
+ {
+ if (instance == null)
+ {
+ instance = this;
+ }
+ else if (instance != this)
+ {
+ Debug.LogError("DeepSky::DS_HazeCore:Awake - There is more than one Haze Controller in this scene! Disabling " + base.name);
+ base.enabled = false;
+ }
+ }
+
+ private void OnEnable()
+ {
+ SetGlobalHeightFalloff();
+ Shader.SetGlobalTexture("_SamplingOffsets", m_NoiseLUT);
+ }
+
+ private void Reset()
+ {
+ OnTransformChildrenChanged();
+ }
+
+ public void SetGlobalNoiseLUT()
+ {
+ Shader.SetGlobalTexture("_SamplingOffsets", m_NoiseLUT);
+ }
+
+ public void AddLightVolume(DS_HazeLightVolume lightVolume)
+ {
+ RemoveLightVolume(lightVolume);
+ m_LightVolumes.Add(lightVolume);
+ }
+
+ public void RemoveLightVolume(DS_HazeLightVolume lightVolume)
+ {
+ m_LightVolumes.Remove(lightVolume);
+ }
+
+ public void GetRenderLightVolumes(Vector3 cameraPosition, List<DS_HazeLightVolume> lightVolumes, List<DS_HazeLightVolume> shadowVolumes)
+ {
+ foreach (DS_HazeLightVolume lightVolume in m_LightVolumes)
+ {
+ if (lightVolume.WillRender(cameraPosition))
+ {
+ if (lightVolume.CastShadows)
+ {
+ shadowVolumes.Add(lightVolume);
+ }
+ else
+ {
+ lightVolumes.Add(lightVolume);
+ }
+ }
+ }
+ }
+
+ public DS_HazeContextItem GetRenderContextAtPosition(Vector3 position)
+ {
+ List<DS_HazeZone> list = new List<DS_HazeZone>();
+ for (int i = 0; i < m_Zones.Count; i++)
+ {
+ if (m_Zones[i].Contains(position) && m_Zones[i].enabled)
+ {
+ list.Add(m_Zones[i]);
+ }
+ }
+ if (list.Count == 0)
+ {
+ return null;
+ }
+ if (list.Count == 1)
+ {
+ return list[0].Context.GetContextItemBlended(m_Time);
+ }
+ list.Sort((DS_HazeZone z1, DS_HazeZone z2) => (!(z1 < z2)) ? 1 : (-1));
+ DS_HazeContextItem contextItemBlended = list[0].Context.GetContextItemBlended(m_Time);
+ float num = 0f;
+ for (int j = 1; j < list.Count; j++)
+ {
+ num = list[j].GetBlendWeight(position);
+ contextItemBlended.Lerp(list[j].Context.GetContextItemBlended(m_Time), num);
+ }
+ return contextItemBlended;
+ }
+}
diff --git a/DeepSky.Haze/DS_HazeLightVolume.cs b/DeepSky.Haze/DS_HazeLightVolume.cs
new file mode 100644
index 0000000..1a9928e
--- /dev/null
+++ b/DeepSky.Haze/DS_HazeLightVolume.cs
@@ -0,0 +1,604 @@
+using System;
+using UnityEngine;
+using UnityEngine.Rendering;
+
+namespace DeepSky.Haze;
+
+[ExecuteInEditMode]
+[RequireComponent(typeof(Light))]
+[AddComponentMenu("DeepSky Haze/Light Volume", 2)]
+public class DS_HazeLightVolume : MonoBehaviour
+{
+ private static int kConeSubdivisions = 16;
+
+ private static Shader kLightVolumeShader;
+
+ private Light m_Light;
+
+ private Mesh m_ProxyMesh;
+
+ private Matrix4x4 m_LightVolumeTransform;
+
+ private CommandBuffer m_RenderCmd;
+
+ private Material m_VolumeMaterial;
+
+ private Vector3 m_DensityOffset = Vector3.zero;
+
+ [SerializeField]
+ private DS_SamplingQuality m_Samples = DS_SamplingQuality.x16;
+
+ [SerializeField]
+ private DS_LightFalloff m_Falloff;
+
+ [SerializeField]
+ private bool m_UseFog;
+
+ [SerializeField]
+ [Range(0f, 100f)]
+ private float m_Scattering = 1f;
+
+ [SerializeField]
+ [Range(0f, 1f)]
+ private float m_SecondaryScattering = 0.1f;
+
+ [SerializeField]
+ [Range(-1f, 1f)]
+ private float m_ScatteringDirection = 0.75f;
+
+ [SerializeField]
+ private Texture3D m_DensityTexture;
+
+ [SerializeField]
+ [Range(0.1f, 10f)]
+ private float m_DensityTextureScale = 1f;
+
+ [SerializeField]
+ [Range(0.1f, 3f)]
+ private float m_DensityTextureContrast = 1f;
+
+ [SerializeField]
+ private Vector3 m_AnimateDirection = Vector3.zero;
+
+ [SerializeField]
+ [Range(0f, 10f)]
+ private float m_AnimateSpeed = 1f;
+
+ [SerializeField]
+ private float m_StartFade = 25f;
+
+ [SerializeField]
+ private float m_EndFade = 30f;
+
+ [SerializeField]
+ [Range(0.01f, 1f)]
+ private float m_FarClip = 1f;
+
+ private LightType m_PreviousLightType = LightType.Point;
+
+ private float m_PreviousAngle = 45f;
+
+ private LightShadows m_PreviousShadowMode;
+
+ public Light LightSource => m_Light;
+
+ public LightType Type => (!(m_Light != null)) ? LightType.Point : m_Light.type;
+
+ public bool CastShadows => (m_Light.shadows != 0) ? true : false;
+
+ public CommandBuffer RenderCommandBuffer => m_RenderCmd;
+
+ public DS_SamplingQuality Samples
+ {
+ get
+ {
+ return m_Samples;
+ }
+ set
+ {
+ m_Samples = value;
+ }
+ }
+
+ public DS_LightFalloff Falloff
+ {
+ get
+ {
+ return m_Falloff;
+ }
+ set
+ {
+ m_Falloff = value;
+ }
+ }
+
+ public bool UseFog
+ {
+ get
+ {
+ return m_UseFog;
+ }
+ set
+ {
+ m_UseFog = value;
+ }
+ }
+
+ public float Scattering
+ {
+ get
+ {
+ return m_Scattering;
+ }
+ set
+ {
+ m_Scattering = Mathf.Clamp01(value);
+ }
+ }
+
+ public float ScatteringDirection
+ {
+ get
+ {
+ return m_ScatteringDirection;
+ }
+ set
+ {
+ m_ScatteringDirection = Mathf.Clamp(value, -1f, 1f);
+ }
+ }
+
+ public Texture3D DensityTexture
+ {
+ get
+ {
+ return m_DensityTexture;
+ }
+ set
+ {
+ m_DensityTexture = value;
+ }
+ }
+
+ public float DensityTextureScale
+ {
+ get
+ {
+ return m_DensityTextureScale;
+ }
+ set
+ {
+ m_DensityTextureScale = Mathf.Clamp01(m_DensityTextureScale);
+ }
+ }
+
+ public Vector3 AnimateDirection
+ {
+ get
+ {
+ return m_AnimateDirection;
+ }
+ set
+ {
+ m_AnimateDirection = value.normalized;
+ }
+ }
+
+ public float AnimateSpeed
+ {
+ get
+ {
+ return m_AnimateSpeed;
+ }
+ set
+ {
+ m_AnimateSpeed = Mathf.Clamp01(value);
+ }
+ }
+
+ public float StartFade
+ {
+ get
+ {
+ return m_StartFade;
+ }
+ set
+ {
+ m_StartFade = ((!(value > 0f)) ? 1f : value);
+ }
+ }
+
+ public float EndFade
+ {
+ get
+ {
+ return m_EndFade;
+ }
+ set
+ {
+ m_EndFade = ((!(value > m_StartFade)) ? (m_StartFade + 1f) : value);
+ }
+ }
+
+ private void CreateProxyMeshCone(Mesh proxyMesh)
+ {
+ Vector3[] array = null;
+ int[] array2 = null;
+ float num = Mathf.Tan(m_Light.spotAngle / 2f * ((float)Math.PI / 180f)) * m_FarClip;
+ array = new Vector3[kConeSubdivisions + 2];
+ array2 = new int[kConeSubdivisions * 6];
+ float num2 = (float)Math.PI * 2f / (float)kConeSubdivisions;
+ float num3 = 0f;
+ for (int i = 0; i < kConeSubdivisions; i++)
+ {
+ ref Vector3 reference = ref array[i];
+ reference = new Vector3(Mathf.Sin(num3) * num, Mathf.Cos(num3) * num, m_FarClip);
+ num3 += num2;
+ }
+ ref Vector3 reference2 = ref array[kConeSubdivisions];
+ reference2 = new Vector3(0f, 0f, m_FarClip);
+ ref Vector3 reference3 = ref array[kConeSubdivisions + 1];
+ reference3 = new Vector3(0f, 0f, -0.1f);
+ for (int j = 0; j < kConeSubdivisions; j++)
+ {
+ array2[j * 3] = kConeSubdivisions;
+ array2[j * 3 + 1] = ((j != kConeSubdivisions - 1) ? (j + 1) : 0);
+ array2[j * 3 + 2] = j;
+ array2[kConeSubdivisions * 3 + j * 3] = j;
+ array2[kConeSubdivisions * 3 + j * 3 + 1] = ((j != kConeSubdivisions - 1) ? (j + 1) : 0);
+ array2[kConeSubdivisions * 3 + j * 3 + 2] = kConeSubdivisions + 1;
+ }
+ proxyMesh.vertices = array;
+ proxyMesh.triangles = array2;
+ proxyMesh.hideFlags = HideFlags.HideAndDontSave;
+ m_PreviousAngle = m_Light.spotAngle;
+ }
+
+ public bool ProxyMeshRequiresRebuild()
+ {
+ if (m_Light == null)
+ {
+ return false;
+ }
+ if (m_ProxyMesh == null || (m_Light.type == LightType.Spot && m_Light.spotAngle != m_PreviousAngle))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public bool LightTypeChanged()
+ {
+ if (m_Light == null)
+ {
+ return false;
+ }
+ return m_Light.type != m_PreviousLightType;
+ }
+
+ public void UpdateLightType()
+ {
+ m_VolumeMaterial.DisableKeyword("POINT_COOKIE");
+ m_VolumeMaterial.DisableKeyword("SPOT_COOKIE");
+ if (m_Light.type == LightType.Point)
+ {
+ m_VolumeMaterial.EnableKeyword("POINT");
+ m_VolumeMaterial.DisableKeyword("SPOT");
+ }
+ else
+ {
+ if (m_Light.type != 0)
+ {
+ Debug.LogError("DeepSky::DS_HazeLightVolume: Unsupported light type! " + base.gameObject.name + " will not render volumetrics.");
+ base.enabled = false;
+ return;
+ }
+ m_VolumeMaterial.EnableKeyword("SPOT");
+ m_VolumeMaterial.DisableKeyword("POINT");
+ }
+ RebuildProxyMesh();
+ m_PreviousLightType = m_Light.type;
+ }
+
+ public void RebuildProxyMesh()
+ {
+ switch (m_Light.type)
+ {
+ case LightType.Point:
+ if (m_PreviousLightType != LightType.Point)
+ {
+ UnityEngine.Object.DestroyImmediate(m_ProxyMesh);
+ }
+ m_ProxyMesh = Resources.Load<Mesh>("DS_HazeMeshProxySphere");
+ break;
+ case LightType.Spot:
+ if (m_PreviousLightType == LightType.Point)
+ {
+ m_ProxyMesh = new Mesh();
+ }
+ else if (m_ProxyMesh != null)
+ {
+ m_ProxyMesh.Clear();
+ }
+ CreateProxyMeshCone(m_ProxyMesh);
+ break;
+ default:
+ Debug.LogError("DeepSky::DS_HazeLightVolume: Unsupported light type! " + base.gameObject.name + " will not render volumetrics.");
+ base.enabled = false;
+ break;
+ }
+ }
+
+ public bool ShadowModeChanged()
+ {
+ if (m_Light == null)
+ {
+ return false;
+ }
+ return m_Light.shadows != m_PreviousShadowMode;
+ }
+
+ public void UpdateShadowMode()
+ {
+ if (m_Light.shadows == LightShadows.None)
+ {
+ m_VolumeMaterial.DisableKeyword("SHADOWS_DEPTH");
+ m_VolumeMaterial.DisableKeyword("SHADOWS_CUBE");
+ }
+ else if (m_Light.type == LightType.Point)
+ {
+ m_VolumeMaterial.EnableKeyword("SHADOWS_CUBE");
+ m_VolumeMaterial.DisableKeyword("SHADOWS_DEPTH");
+ }
+ else if (m_Light.type == LightType.Spot)
+ {
+ m_VolumeMaterial.EnableKeyword("SHADOWS_DEPTH");
+ m_VolumeMaterial.DisableKeyword("SHADOWS_CUBE");
+ }
+ m_PreviousShadowMode = m_Light.shadows;
+ }
+
+ public void Register()
+ {
+ DS_HazeCore instance = DS_HazeCore.Instance;
+ if (instance == null)
+ {
+ Debug.LogError("DeepSky::DS_HazeLightVolume: Attempting to add a light volume but no HS_HazeCore found in scene! Please make sure there is a DS_HazeCore object.");
+ }
+ else
+ {
+ instance.AddLightVolume(this);
+ }
+ }
+
+ public void Deregister()
+ {
+ DS_HazeCore instance = DS_HazeCore.Instance;
+ if (instance != null)
+ {
+ instance.RemoveLightVolume(this);
+ }
+ }
+
+ public bool WillRender(Vector3 cameraPos)
+ {
+ return base.isActiveAndEnabled & (Vector3.Distance(cameraPos, base.transform.position) < m_EndFade);
+ }
+
+ private void Update()
+ {
+ m_DensityOffset -= m_AnimateDirection * m_AnimateSpeed * Time.deltaTime * 0.1f;
+ }
+
+ private void OnEnable()
+ {
+ m_Light = GetComponent<Light>();
+ if (m_Light == null)
+ {
+ Debug.LogError("DeepSky::DS_HazeLightVolume: No Light component found on " + base.gameObject.name);
+ base.enabled = false;
+ }
+ if (kLightVolumeShader == null)
+ {
+ kLightVolumeShader = Resources.Load<Shader>("DS_HazeLightVolume");
+ }
+ if (m_VolumeMaterial == null)
+ {
+ m_VolumeMaterial = new Material(kLightVolumeShader);
+ m_VolumeMaterial.hideFlags = HideFlags.HideAndDontSave;
+ }
+ if (m_RenderCmd == null)
+ {
+ m_RenderCmd = new CommandBuffer();
+ m_RenderCmd.name = base.gameObject.name + "_DS_Haze_RenderLightVolume";
+ m_Light.AddCommandBuffer(LightEvent.AfterShadowMap, m_RenderCmd);
+ }
+ if (LightTypeChanged())
+ {
+ UpdateLightType();
+ }
+ else if (ProxyMeshRequiresRebuild())
+ {
+ RebuildProxyMesh();
+ }
+ if (ShadowModeChanged())
+ {
+ UpdateShadowMode();
+ }
+ Register();
+ }
+
+ private void OnDisable()
+ {
+ Deregister();
+ }
+
+ private void OnDestroy()
+ {
+ if (m_RenderCmd != null)
+ {
+ m_RenderCmd.Dispose();
+ }
+ Deregister();
+ if (m_ProxyMesh != null && m_Light.type != LightType.Point)
+ {
+ UnityEngine.Object.DestroyImmediate(m_ProxyMesh);
+ }
+ if (m_VolumeMaterial != null)
+ {
+ UnityEngine.Object.DestroyImmediate(m_VolumeMaterial);
+ }
+ }
+
+ private int SetShaderPassAndMatrix(Transform cameraTransform, int downSampleFactor, out Matrix4x4 worldMtx)
+ {
+ worldMtx = Matrix4x4.TRS(base.transform.position, base.transform.rotation, new Vector3(m_Light.range, m_Light.range, m_Light.range));
+ int num = 0;
+ if (m_Light.type == LightType.Spot)
+ {
+ float num2 = Mathf.Cos(m_Light.spotAngle / 2f * ((float)Math.PI / 180f));
+ Vector3 normalized = (cameraTransform.position - base.transform.position).normalized;
+ float num3 = Vector3.Dot(normalized, base.transform.forward);
+ num = ((num3 > num2) ? 1 : 2);
+ }
+ if (downSampleFactor == 4)
+ {
+ num += 3;
+ }
+ if (m_Falloff == DS_LightFalloff.Quadratic)
+ {
+ num += 6;
+ }
+ if (m_UseFog)
+ {
+ num += 12;
+ }
+ return num;
+ }
+
+ public void FillLightCommandBuffer(RenderTexture radianceTarget, Transform cameraTransform, int downSampleFactor)
+ {
+ m_RenderCmd.SetGlobalTexture("_ShadowMapTexture", BuiltinRenderTextureType.CurrentActive);
+ Matrix4x4 worldMtx;
+ int shaderPass = SetShaderPassAndMatrix(cameraTransform, downSampleFactor, out worldMtx);
+ m_RenderCmd.SetRenderTarget(radianceTarget);
+ m_RenderCmd.DrawMesh(m_ProxyMesh, worldMtx, m_VolumeMaterial, 0, shaderPass);
+ }
+
+ public void AddLightRenderCommand(Transform cameraTransform, CommandBuffer cmd, int downSampleFactor)
+ {
+ Matrix4x4 worldMtx;
+ int shaderPass = SetShaderPassAndMatrix(cameraTransform, downSampleFactor, out worldMtx);
+ cmd.DrawMesh(m_ProxyMesh, worldMtx, m_VolumeMaterial, 0, shaderPass);
+ }
+
+ public void SetupMaterialPerFrame(Matrix4x4 viewProjMtx, Matrix4x4 viewMtx, Transform cameraTransform, float offsetIndex)
+ {
+ m_VolumeMaterial.DisableKeyword("SAMPLES_4");
+ m_VolumeMaterial.DisableKeyword("SAMPLES_8");
+ m_VolumeMaterial.DisableKeyword("SAMPLES_16");
+ m_VolumeMaterial.DisableKeyword("SAMPLES_32");
+ switch (m_Samples)
+ {
+ case DS_SamplingQuality.x4:
+ m_VolumeMaterial.EnableKeyword("SAMPLES_4");
+ break;
+ case DS_SamplingQuality.x8:
+ m_VolumeMaterial.EnableKeyword("SAMPLES_8");
+ break;
+ case DS_SamplingQuality.x16:
+ m_VolumeMaterial.EnableKeyword("SAMPLES_16");
+ break;
+ case DS_SamplingQuality.x32:
+ m_VolumeMaterial.EnableKeyword("SAMPLES_32");
+ break;
+ default:
+ m_VolumeMaterial.EnableKeyword("SAMPLES_16");
+ break;
+ }
+ float num = 1f - Mathf.Clamp01((Vector3.Distance(cameraTransform.position, base.transform.position) - m_StartFade) / (m_EndFade - m_StartFade));
+ m_VolumeMaterial.SetVector("_DS_HazeSamplingParams", new Vector4(offsetIndex, 0f, m_DensityTextureContrast, 0f));
+ m_VolumeMaterial.SetVector("_DS_HazeCameraDirection", new Vector4(cameraTransform.forward.x, cameraTransform.forward.y, cameraTransform.forward.z, 1f));
+ m_VolumeMaterial.SetColor("_DS_HazeLightVolumeColour", m_Light.color.linear * m_Light.intensity * num);
+ m_VolumeMaterial.SetVector("_DS_HazeLightVolumeScattering", new Vector4(m_Scattering, m_SecondaryScattering, m_ScatteringDirection, Mathf.Clamp01(1f - m_SecondaryScattering)));
+ m_VolumeMaterial.SetVector("_DS_HazeLightVolumeParams0", new Vector4(base.transform.position.x, base.transform.position.y, base.transform.position.z, m_Light.range));
+ Matrix4x4 matrix4x = Matrix4x4.TRS(base.transform.position, base.transform.rotation, new Vector3(m_Light.range, m_Light.range, m_Light.range));
+ m_VolumeMaterial.SetMatrix("_WorldViewProj", viewProjMtx * matrix4x);
+ m_VolumeMaterial.SetMatrix("_WorldView", viewMtx * matrix4x);
+ if ((bool)m_DensityTexture)
+ {
+ m_VolumeMaterial.EnableKeyword("DENSITY_TEXTURE");
+ m_VolumeMaterial.SetTexture("_DensityTexture", m_DensityTexture);
+ m_VolumeMaterial.SetVector("_DS_HazeDensityParams", new Vector4(m_DensityOffset.x, m_DensityOffset.y, m_DensityOffset.z, m_DensityTextureScale * 0.01f));
+ }
+ else
+ {
+ m_VolumeMaterial.DisableKeyword("DENSITY_TEXTURE");
+ }
+ bool flag = m_Light.shadows != LightShadows.None;
+ if (m_Light.type == LightType.Point)
+ {
+ m_VolumeMaterial.DisableKeyword("SPOT_COOKIE");
+ m_VolumeMaterial.DisableKeyword("SHADOWS_DEPTH");
+ if (flag)
+ {
+ m_VolumeMaterial.EnableKeyword("SHADOWS_CUBE");
+ }
+ else
+ {
+ m_VolumeMaterial.DisableKeyword("SHADOWS_CUBE");
+ }
+ if ((bool)m_Light.cookie)
+ {
+ m_VolumeMaterial.EnableKeyword("POINT_COOKIE");
+ m_VolumeMaterial.SetMatrix("_DS_Haze_WorldToCookie", base.transform.worldToLocalMatrix);
+ m_VolumeMaterial.SetTexture("_LightTexture0", m_Light.cookie);
+ }
+ else
+ {
+ m_VolumeMaterial.DisableKeyword("POINT_COOKIE");
+ }
+ }
+ else if (m_Light.type == LightType.Spot)
+ {
+ m_VolumeMaterial.DisableKeyword("POINT_COOKIE");
+ m_VolumeMaterial.DisableKeyword("SHADOWS_CUBE");
+ if (flag)
+ {
+ m_VolumeMaterial.EnableKeyword("SHADOWS_DEPTH");
+ Matrix4x4 inverse = Matrix4x4.TRS(base.transform.position, base.transform.rotation, Vector3.one).inverse;
+ Matrix4x4 matrix4x2 = Matrix4x4.TRS(new Vector3(0.5f, 0.5f, 0.5f), Quaternion.identity, new Vector3(0.5f, 0.5f, 0.5f));
+ Matrix4x4 matrix4x3 = Matrix4x4.Perspective(m_Light.spotAngle, 1f, m_Light.range, m_Light.shadowNearPlane);
+ Matrix4x4 value = matrix4x2 * matrix4x3;
+ value[0, 2] *= -1f;
+ value[1, 2] *= -1f;
+ value[2, 2] *= -1f;
+ value[3, 2] *= -1f;
+ value *= inverse;
+ m_VolumeMaterial.SetMatrix("_DS_Haze_WorldToShadow", value);
+ }
+ else
+ {
+ m_VolumeMaterial.DisableKeyword("SHADOWS_DEPTH");
+ }
+ float num2 = Mathf.Cos(m_Light.spotAngle / 2f * ((float)Math.PI / 180f));
+ Vector3 lhs = base.transform.position + base.transform.forward * m_Light.range;
+ float z = 0f - Vector3.Dot(lhs, base.transform.forward);
+ m_VolumeMaterial.SetVector("_DS_HazeLightVolumeParams1", new Vector4(base.transform.forward.x, base.transform.forward.y, base.transform.forward.z, 1f));
+ m_VolumeMaterial.SetVector("_DS_HazeLightVolumeParams2", new Vector4(num2, 1f / num2, z, 0f));
+ if ((bool)m_Light.cookie)
+ {
+ m_VolumeMaterial.EnableKeyword("SPOT_COOKIE");
+ Matrix4x4 inverse2 = Matrix4x4.TRS(base.transform.position, base.transform.rotation, Vector3.one).inverse;
+ Matrix4x4 matrix4x4 = Matrix4x4.TRS(new Vector3(0.5f, 0.5f, 0f), Quaternion.identity, new Vector3(-0.5f, -0.5f, 1f));
+ Matrix4x4 matrix4x5 = Matrix4x4.Perspective(m_Light.spotAngle, 1f, 0f, 1f);
+ m_VolumeMaterial.SetMatrix("_DS_Haze_WorldToCookie", matrix4x4 * matrix4x5 * inverse2);
+ m_VolumeMaterial.SetTexture("_LightTexture0", m_Light.cookie);
+ }
+ else
+ {
+ m_VolumeMaterial.DisableKeyword("SPOT_COOKIE");
+ }
+ }
+ }
+}
diff --git a/DeepSky.Haze/DS_HazeView.cs b/DeepSky.Haze/DS_HazeView.cs
new file mode 100644
index 0000000..925f1a3
--- /dev/null
+++ b/DeepSky.Haze/DS_HazeView.cs
@@ -0,0 +1,1120 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Rendering;
+
+namespace DeepSky.Haze;
+
+[ExecuteInEditMode]
+[AddComponentMenu("DeepSky Haze/View", 1)]
+public class DS_HazeView : MonoBehaviour
+{
+ private enum SizeFactor
+ {
+ Half = 2,
+ Quarter = 4
+ }
+
+ private enum VolumeSamples
+ {
+ x16,
+ x24,
+ x32
+ }
+
+ private static string kClearRadianceCmdBufferName = "DS_Haze_ClearRadiance";
+
+ private static string kShadowCascadesCmdBufferName = "DS_Haze_ShadowCascadesCopy";
+
+ private static string kDirectionalLightCmdBufferName = "DS_Haze_DirectLight";
+
+ private static string kRenderLightVolumeCmdBufferName = "DS_Haze_RenderLightVolume";
+
+ private static string kPreviousDepthTargetName = "DS_Haze_PreviousDepthTarget";
+
+ private static string kRadianceTarget01Name = "DS_Haze_RadianceTarget_01";
+
+ private static string kRadianceTarget02Name = "DS_Haze_RadianceTarget_02";
+
+ private static Shader kShader;
+
+ [SerializeField]
+ private bool m_OverrideTime;
+
+ [SerializeField]
+ [Range(0f, 1f)]
+ private float m_Time = 0.5f;
+
+ [SerializeField]
+ private bool m_OverrideContextAsset;
+
+ [SerializeField]
+ private DS_HazeContextAsset m_Context;
+
+ [SerializeField]
+ private bool m_OverrideContextVariant;
+
+ [SerializeField]
+ private int m_ContextItemIndex;
+
+ [SerializeField]
+ private Light m_DirectLight;
+
+ [SerializeField]
+ private bool m_RenderAtmosphereVolumetrics = true;
+
+ [SerializeField]
+ private bool m_RenderLocalVolumetrics = true;
+
+ [SerializeField]
+ private bool m_TemporalReprojection = true;
+
+ [SerializeField]
+ private SizeFactor m_DownsampleFactor = SizeFactor.Half;
+
+ [SerializeField]
+ private VolumeSamples m_VolumeSamples;
+
+ [SerializeField]
+ [Range(100f, 5000f)]
+ private int m_GaussianDepthFalloff = 500;
+
+ [SerializeField]
+ [Range(0f, 0.5f)]
+ private float m_UpsampleDepthThreshold = 0.06f;
+
+ [SerializeField]
+ [Range(0.001f, 1f)]
+ private float m_TemporalRejectionScale = 0.1f;
+
+ [SerializeField]
+ [Range(0.1f, 0.9f)]
+ private float m_TemporalBlendFactor = 0.25f;
+
+ private ShadowProjection m_ShadowProjectionType = ShadowProjection.StableFit;
+
+ [SerializeField]
+ private bool m_ApplyAirToSkybox;
+
+ [SerializeField]
+ private bool m_ApplyHazeToSkybox = true;
+
+ [SerializeField]
+ private bool m_ApplyFogExtinctionToSkybox = true;
+
+ [SerializeField]
+ private bool m_ApplyFogLightingToSkybox = true;
+
+ [SerializeField]
+ private bool m_ShowTemporalRejection;
+
+ [SerializeField]
+ private bool m_ShowUpsampleThreshold;
+
+ private Camera m_Camera;
+
+ private RenderTexture m_PerFrameRadianceTarget;
+
+ private RenderTexture m_RadianceTarget_01;
+
+ private RenderTexture m_RadianceTarget_02;
+
+ private RenderTexture m_CurrentRadianceTarget;
+
+ private RenderTexture m_PreviousRadianceTarget;
+
+ private RenderTexture m_PreviousDepthTarget;
+
+ private CommandBuffer m_ShadowCascadesCmdBuffer;
+
+ private CommandBuffer m_DirectionalLightCmdBuffer;
+
+ private CommandBuffer m_ClearRadianceCmdBuffer;
+
+ private CommandBuffer m_RenderNonShadowVolumes;
+
+ private Material m_Material;
+
+ private Matrix4x4 m_PreviousViewProjMatrix = Matrix4x4.identity;
+
+ private Matrix4x4 m_PreviousInvViewProjMatrix = Matrix4x4.identity;
+
+ private float m_InterleavedOffsetIndex;
+
+ private int m_X;
+
+ private int m_Y;
+
+ private RenderingPath m_PreviousRenderPath;
+
+ private ColorSpace m_ColourSpace;
+
+ private List<DS_HazeLightVolume> m_PerFrameLightVolumes = new List<DS_HazeLightVolume>();
+
+ private List<DS_HazeLightVolume> m_PerFrameShadowLightVolumes = new List<DS_HazeLightVolume>();
+
+ private Dictionary<Light, CommandBuffer> m_LightVolumeCmdBuffers = new Dictionary<Light, CommandBuffer>();
+
+ public bool OverrideTime
+ {
+ get
+ {
+ return m_OverrideTime;
+ }
+ set
+ {
+ m_OverrideTime = value;
+ if (value && m_OverrideContextVariant)
+ {
+ m_OverrideContextVariant = false;
+ }
+ }
+ }
+
+ public float Time
+ {
+ get
+ {
+ return m_Time;
+ }
+ set
+ {
+ m_Time = value;
+ }
+ }
+
+ public bool OverrideContextAsset
+ {
+ get
+ {
+ return m_OverrideContextAsset;
+ }
+ set
+ {
+ m_OverrideContextAsset = value;
+ }
+ }
+
+ public DS_HazeContextAsset ContextAsset
+ {
+ get
+ {
+ return m_Context;
+ }
+ set
+ {
+ m_Context = value;
+ }
+ }
+
+ public bool OverrideContextVariant
+ {
+ get
+ {
+ return m_OverrideContextVariant;
+ }
+ set
+ {
+ m_OverrideContextVariant = value;
+ if (value && m_OverrideTime)
+ {
+ m_OverrideTime = false;
+ }
+ }
+ }
+
+ public int ContextItemIndex
+ {
+ get
+ {
+ return m_ContextItemIndex;
+ }
+ set
+ {
+ m_ContextItemIndex = ((value > 0) ? value : 0);
+ }
+ }
+
+ public Light DirectLight
+ {
+ get
+ {
+ return m_DirectLight;
+ }
+ set
+ {
+ m_DirectLight = value;
+ }
+ }
+
+ public Vector2 RadianceTargetSize => new Vector2(m_X, m_Y);
+
+ public int SampleCount => m_VolumeSamples switch
+ {
+ VolumeSamples.x16 => 16,
+ VolumeSamples.x24 => 24,
+ VolumeSamples.x32 => 32,
+ _ => 16,
+ };
+
+ public int DownSampleFactor => (m_DownsampleFactor != SizeFactor.Half) ? 4 : 2;
+
+ public bool RenderAtmosphereVolumetrics
+ {
+ get
+ {
+ return m_RenderAtmosphereVolumetrics;
+ }
+ set
+ {
+ m_RenderAtmosphereVolumetrics = value;
+ SetTemporalKeywords();
+ }
+ }
+
+ public bool RenderLocalVolumetrics
+ {
+ get
+ {
+ return m_RenderLocalVolumetrics;
+ }
+ set
+ {
+ m_RenderLocalVolumetrics = value;
+ SetTemporalKeywords();
+ }
+ }
+
+ public bool TemporalReprojection
+ {
+ get
+ {
+ return m_TemporalReprojection;
+ }
+ set
+ {
+ m_TemporalReprojection = value;
+ SetTemporalKeywords();
+ }
+ }
+
+ public bool WillRenderWithTemporalReprojection => m_TemporalReprojection & (m_RenderAtmosphereVolumetrics | m_RenderLocalVolumetrics);
+
+ public int AntiAliasingLevel()
+ {
+ int result = 1;
+ if (m_Camera.actualRenderingPath == RenderingPath.Forward && m_Camera.allowMSAA && QualitySettings.antiAliasing > 0)
+ {
+ result = QualitySettings.antiAliasing;
+ }
+ return result;
+ }
+
+ private bool CheckHasSystemSupport()
+ {
+ if (!SystemInfo.supportsImageEffects)
+ {
+ Debug.LogError("DeepSky::DS_HazeView: Image effects are not supported on this platform.");
+ base.enabled = false;
+ return false;
+ }
+ if (SystemInfo.graphicsShaderLevel < 30)
+ {
+ Debug.LogError("DeepSky::DS_HazeView: Minimum required shader model (3.0) is not supported on this platform.");
+ base.enabled = false;
+ return false;
+ }
+ if (m_Camera.allowHDR && !SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBHalf))
+ {
+ Debug.LogError("DeepSky::DS_HazeView: ARGBHalf render texture format is not supported on this platform.");
+ base.enabled = false;
+ return false;
+ }
+ if (!SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.RFloat))
+ {
+ Debug.LogError("DeepSky::DS_HazeView: RFloat render texture format is not supported on this platform.");
+ base.enabled = false;
+ return false;
+ }
+ return true;
+ }
+
+ private void SetMaterialFromContext(DS_HazeContextItem ctx)
+ {
+ if (WillRenderWithTemporalReprojection)
+ {
+ m_InterleavedOffsetIndex += 0.0625f;
+ if (Mathf.Approximately(m_InterleavedOffsetIndex, 1f))
+ {
+ m_InterleavedOffsetIndex = 0f;
+ }
+ }
+ float x = 1f;
+ float y = 1f;
+ float z = 1f;
+ switch (DS_HazeCore.Instance.HeightFalloff)
+ {
+ case DS_HazeCore.HeightFalloffType.None:
+ x = 1f;
+ y = 1f;
+ z = 1f;
+ break;
+ case DS_HazeCore.HeightFalloffType.Exponential:
+ {
+ float num = Mathf.Abs(base.transform.position.y);
+ x = Mathf.Exp((0f - ctx.m_AirDensityHeightFalloff) * num);
+ y = Mathf.Exp((0f - ctx.m_HazeDensityHeightFalloff) * num);
+ z = Mathf.Exp((0f - ctx.m_FogDensityHeightFalloff) * (num - ctx.m_FogStartHeight));
+ break;
+ }
+ }
+ Vector3 vector = ctx.m_AirScatteringScale * new Vector3(0.00116f, 0.0027f, 0.00662f);
+ float x2 = ctx.m_HazeScatteringScale * 0.0021f;
+ float fogScatteringScale = ctx.m_FogScatteringScale;
+ float w = ctx.m_FogExtinctionScale * 0.01f;
+ Vector4 value = new Vector4(ctx.m_AirDensityHeightFalloff, ctx.m_HazeDensityHeightFalloff, 0f, ctx.m_HazeScatteringDirection);
+ Vector4 value2 = new Vector4(x2, (!m_RenderAtmosphereVolumetrics) ? 0f : ctx.m_HazeSecondaryScatteringRatio, fogScatteringScale, w);
+ Vector4 value3 = new Vector4(x, y, z, 0f);
+ Vector4 value4 = new Vector4(ctx.m_FogStartDistance, ctx.m_FogDensityHeightFalloff, ctx.m_FogOpacity, ctx.m_FogScatteringDirection);
+ Vector4 value5 = new Vector4(m_GaussianDepthFalloff, m_UpsampleDepthThreshold * 0.01f, m_TemporalRejectionScale, m_TemporalBlendFactor);
+ m_Material.SetVector("_SamplingParams", value5);
+ m_Material.SetVector("_InterleavedOffset", new Vector4(m_InterleavedOffsetIndex, 0f, 0f, 0f));
+ m_Material.SetMatrix("_PreviousViewProjMatrix", m_PreviousViewProjMatrix);
+ m_Material.SetMatrix("_PreviousInvViewProjMatrix", m_PreviousInvViewProjMatrix);
+ Shader.SetGlobalVector("_DS_BetaParams", value2);
+ Shader.SetGlobalVector("_DS_RBetaS", vector);
+ Shader.SetGlobalVector("_DS_AirHazeParams", value);
+ Shader.SetGlobalVector("_DS_FogParams", value4);
+ Shader.SetGlobalVector("_DS_InitialDensityParams", value3);
+ Vector3 vector2;
+ Color color;
+ if ((bool)m_DirectLight)
+ {
+ vector2 = -m_DirectLight.transform.forward;
+ color = m_DirectLight.color.linear * m_DirectLight.intensity;
+ Shader.SetGlobalColor("_DS_FogAmbientLight", ctx.m_FogAmbientColour.linear * m_DirectLight.intensity);
+ Shader.SetGlobalColor("_DS_FogDirectLight", ctx.m_FogLightColour.linear * m_DirectLight.intensity);
+ }
+ else
+ {
+ vector2 = Vector3.up;
+ color = Color.white;
+ Shader.SetGlobalColor("_DS_FogAmbientLight", ctx.m_FogAmbientColour.linear);
+ Shader.SetGlobalColor("_DS_FogDirectLight", ctx.m_FogLightColour.linear);
+ }
+ Shader.SetGlobalVector("_DS_LightDirection", vector2);
+ Shader.SetGlobalVector("_DS_LightColour", color);
+ }
+
+ private void SetGlobalParamsToNull()
+ {
+ Shader.SetGlobalVector("_DS_BetaParams", Vector4.zero);
+ Shader.SetGlobalVector("_DS_RBetaS", Vector4.zero);
+ }
+
+ public void SetDebugKeywords()
+ {
+ if (m_ShowTemporalRejection)
+ {
+ m_Material.EnableKeyword("SHOW_TEMPORAL_REJECTION");
+ }
+ else
+ {
+ m_Material.DisableKeyword("SHOW_TEMPORAL_REJECTION");
+ }
+ if (m_ShowUpsampleThreshold)
+ {
+ m_Material.EnableKeyword("SHOW_UPSAMPLE_THRESHOLD");
+ }
+ else
+ {
+ m_Material.DisableKeyword("SHOW_UPSAMPLE_THRESHOLD");
+ }
+ }
+
+ public void SetSkyboxKeywords()
+ {
+ if (m_ApplyAirToSkybox)
+ {
+ m_Material.EnableKeyword("DS_HAZE_APPLY_RAYLEIGH");
+ }
+ else
+ {
+ m_Material.DisableKeyword("DS_HAZE_APPLY_RAYLEIGH");
+ }
+ if (m_ApplyHazeToSkybox)
+ {
+ m_Material.EnableKeyword("DS_HAZE_APPLY_MIE");
+ }
+ else
+ {
+ m_Material.DisableKeyword("DS_HAZE_APPLY_MIE");
+ }
+ if (m_ApplyFogExtinctionToSkybox)
+ {
+ m_Material.EnableKeyword("DS_HAZE_APPLY_FOG_EXTINCTION");
+ }
+ else
+ {
+ m_Material.DisableKeyword("DS_HAZE_APPLY_FOG_EXTINCTION");
+ }
+ if (m_ApplyFogLightingToSkybox)
+ {
+ m_Material.EnableKeyword("DS_HAZE_APPLY_FOG_RADIANCE");
+ }
+ else
+ {
+ m_Material.DisableKeyword("DS_HAZE_APPLY_FOG_RADIANCE");
+ }
+ }
+
+ public void SetTemporalKeywords()
+ {
+ if (WillRenderWithTemporalReprojection)
+ {
+ m_Material.EnableKeyword("DS_HAZE_TEMPORAL");
+ return;
+ }
+ m_Material.DisableKeyword("DS_HAZE_TEMPORAL");
+ if (m_ShowTemporalRejection)
+ {
+ m_ShowTemporalRejection = false;
+ m_Material.DisableKeyword("SHOW_TEMPORAL_REJECTION");
+ }
+ if ((bool)m_RadianceTarget_01)
+ {
+ m_RadianceTarget_01.Release();
+ UnityEngine.Object.DestroyImmediate(m_RadianceTarget_01);
+ m_RadianceTarget_01 = null;
+ }
+ if ((bool)m_RadianceTarget_02)
+ {
+ m_RadianceTarget_02.Release();
+ UnityEngine.Object.DestroyImmediate(m_RadianceTarget_02);
+ m_RadianceTarget_02 = null;
+ }
+ if ((bool)m_PreviousDepthTarget)
+ {
+ m_PreviousDepthTarget.Release();
+ UnityEngine.Object.DestroyImmediate(m_PreviousDepthTarget);
+ m_PreviousDepthTarget = null;
+ }
+ }
+
+ private void SetShaderKeyWords()
+ {
+ if (m_ShadowProjectionType == ShadowProjection.CloseFit)
+ {
+ m_Material.EnableKeyword("SHADOW_PROJ_CLOSE");
+ }
+ else if (m_ShadowProjectionType == ShadowProjection.StableFit)
+ {
+ m_Material.DisableKeyword("SHADOW_PROJ_CLOSE");
+ }
+ if (DS_HazeCore.Instance != null)
+ {
+ switch (DS_HazeCore.Instance.HeightFalloff)
+ {
+ case DS_HazeCore.HeightFalloffType.None:
+ m_Material.EnableKeyword("DS_HAZE_HEIGHT_FALLOFF_NONE");
+ break;
+ case DS_HazeCore.HeightFalloffType.Exponential:
+ m_Material.DisableKeyword("DS_HAZE_HEIGHT_FALLOFF_NONE");
+ break;
+ default:
+ m_Material.EnableKeyword("DS_HAZE_HEIGHT_FALLOFF_NONE");
+ break;
+ }
+ }
+ }
+
+ private void OnEnable()
+ {
+ SetGlobalParamsToNull();
+ m_Camera = GetComponent<Camera>();
+ if (!m_Camera)
+ {
+ Debug.LogError("DeepSky::DS_HazeView: GameObject '" + base.gameObject.name + "' does not have a camera component!");
+ base.enabled = false;
+ return;
+ }
+ if (!CheckHasSystemSupport())
+ {
+ base.enabled = false;
+ return;
+ }
+ if (kShader == null)
+ {
+ kShader = Resources.Load<Shader>("DS_Haze");
+ }
+ if (m_Material == null)
+ {
+ m_Material = new Material(kShader);
+ m_Material.hideFlags = HideFlags.HideAndDontSave;
+ }
+ if (m_Camera.actualRenderingPath == RenderingPath.Forward && (m_Camera.depthTextureMode & DepthTextureMode.Depth) != DepthTextureMode.Depth)
+ {
+ m_Camera.depthTextureMode |= DepthTextureMode.Depth;
+ }
+ if (m_RenderNonShadowVolumes == null)
+ {
+ CommandBuffer[] commandBuffers = m_Camera.GetCommandBuffers(CameraEvent.BeforeImageEffectsOpaque);
+ bool flag = false;
+ CommandBuffer[] array = commandBuffers;
+ foreach (CommandBuffer commandBuffer in array)
+ {
+ if (commandBuffer.name == kRenderLightVolumeCmdBufferName)
+ {
+ m_RenderNonShadowVolumes = commandBuffer;
+ flag = true;
+ break;
+ }
+ }
+ if (!flag)
+ {
+ m_RenderNonShadowVolumes = new CommandBuffer();
+ m_RenderNonShadowVolumes.name = kRenderLightVolumeCmdBufferName;
+ m_Camera.AddCommandBuffer(CameraEvent.BeforeImageEffectsOpaque, m_RenderNonShadowVolumes);
+ }
+ }
+ m_CurrentRadianceTarget = m_RadianceTarget_01;
+ m_PreviousRadianceTarget = m_RadianceTarget_02;
+ SetSkyboxKeywords();
+ SetDebugKeywords();
+ m_ColourSpace = QualitySettings.activeColorSpace;
+ m_PreviousRenderPath = m_Camera.actualRenderingPath;
+ }
+
+ private void CreateRadianceTarget(string name, out RenderTexture radianceTarget)
+ {
+ if (m_Camera.allowHDR)
+ {
+ radianceTarget = new RenderTexture(m_Camera.pixelWidth, m_Camera.pixelHeight, 0, RenderTextureFormat.ARGBHalf);
+ }
+ else
+ {
+ radianceTarget = new RenderTexture(m_Camera.pixelWidth, m_Camera.pixelHeight, 0, RenderTextureFormat.ARGB32);
+ }
+ radianceTarget.name = name;
+ radianceTarget.antiAliasing = AntiAliasingLevel();
+ radianceTarget.useMipMap = false;
+ radianceTarget.hideFlags = HideFlags.HideAndDontSave;
+ radianceTarget.filterMode = FilterMode.Point;
+ }
+
+ private void CreateDepthTarget(string name, out RenderTexture depthTarget, bool downsample = false)
+ {
+ depthTarget = new RenderTexture((!downsample) ? m_Camera.pixelWidth : m_X, (!downsample) ? m_Camera.pixelHeight : m_Y, 0, RenderTextureFormat.RFloat, RenderTextureReadWrite.Linear);
+ depthTarget.name = name;
+ depthTarget.antiAliasing = 1;
+ depthTarget.useMipMap = false;
+ depthTarget.hideFlags = HideFlags.HideAndDontSave;
+ depthTarget.filterMode = FilterMode.Point;
+ }
+
+ private bool CameraHasClearRadianceCmdBuffer(out CommandBuffer foundCmd)
+ {
+ CommandBuffer[] commandBuffers;
+ if (m_Camera.actualRenderingPath == RenderingPath.DeferredShading)
+ {
+ commandBuffers = m_Camera.GetCommandBuffers(CameraEvent.BeforeGBuffer);
+ }
+ else
+ {
+ CameraEvent evt = (((m_Camera.depthTextureMode & DepthTextureMode.DepthNormals) == DepthTextureMode.DepthNormals) ? CameraEvent.BeforeDepthNormalsTexture : CameraEvent.BeforeDepthTexture);
+ commandBuffers = m_Camera.GetCommandBuffers(evt);
+ }
+ CommandBuffer[] array = commandBuffers;
+ foreach (CommandBuffer commandBuffer in array)
+ {
+ if (commandBuffer.name == kClearRadianceCmdBufferName)
+ {
+ foundCmd = commandBuffer;
+ return true;
+ }
+ }
+ foundCmd = null;
+ return false;
+ }
+
+ private CommandBuffer LightHasCascadesCopyCmdBuffer()
+ {
+ CommandBuffer[] commandBuffers = m_DirectLight.GetCommandBuffers(LightEvent.AfterShadowMap);
+ CommandBuffer[] array = commandBuffers;
+ foreach (CommandBuffer commandBuffer in array)
+ {
+ if (commandBuffer.name == kShadowCascadesCmdBufferName)
+ {
+ return commandBuffer;
+ }
+ }
+ return null;
+ }
+
+ private CommandBuffer LightHasRenderCmdBuffer()
+ {
+ CommandBuffer[] commandBuffers = m_DirectLight.GetCommandBuffers(LightEvent.AfterScreenspaceMask);
+ CommandBuffer[] array = commandBuffers;
+ foreach (CommandBuffer commandBuffer in array)
+ {
+ if (commandBuffer.name == kDirectionalLightCmdBufferName)
+ {
+ return commandBuffer;
+ }
+ }
+ return null;
+ }
+
+ public void RemoveCommandBufferFromLight(Light light)
+ {
+ CommandBuffer[] commandBuffers = light.GetCommandBuffers(LightEvent.AfterShadowMap);
+ for (int i = 0; i < commandBuffers.Length; i++)
+ {
+ if (commandBuffers[i].name == kShadowCascadesCmdBufferName)
+ {
+ light.RemoveCommandBuffer(LightEvent.AfterShadowMap, commandBuffers[i]);
+ break;
+ }
+ }
+ commandBuffers = light.GetCommandBuffers(LightEvent.AfterScreenspaceMask);
+ for (int j = 0; j < commandBuffers.Length; j++)
+ {
+ if (commandBuffers[j].name == kDirectionalLightCmdBufferName)
+ {
+ light.RemoveCommandBuffer(LightEvent.AfterScreenspaceMask, commandBuffers[j]);
+ break;
+ }
+ }
+ }
+
+ private void RenderPathChanged()
+ {
+ if (m_Camera.actualRenderingPath == RenderingPath.Forward && (m_Camera.depthTextureMode & DepthTextureMode.Depth) != DepthTextureMode.Depth)
+ {
+ m_Camera.depthTextureMode |= DepthTextureMode.Depth;
+ }
+ if (m_ClearRadianceCmdBuffer != null)
+ {
+ CameraEvent evt = ((m_PreviousRenderPath != RenderingPath.DeferredShading) ? (((m_Camera.depthTextureMode & DepthTextureMode.DepthNormals) == DepthTextureMode.DepthNormals) ? CameraEvent.BeforeDepthNormalsTexture : CameraEvent.BeforeDepthTexture) : CameraEvent.BeforeGBuffer);
+ CommandBuffer[] commandBuffers = m_Camera.GetCommandBuffers(evt);
+ CommandBuffer[] array = commandBuffers;
+ foreach (CommandBuffer commandBuffer in array)
+ {
+ if (commandBuffer.name == kClearRadianceCmdBufferName)
+ {
+ m_Camera.RemoveCommandBuffer(evt, commandBuffer);
+ break;
+ }
+ }
+ }
+ m_PreviousRenderPath = m_Camera.actualRenderingPath;
+ }
+
+ private void UpdateResources()
+ {
+ m_X = m_Camera.pixelWidth / (int)m_DownsampleFactor;
+ m_Y = m_Camera.pixelHeight / (int)m_DownsampleFactor;
+ if (m_Camera.actualRenderingPath != m_PreviousRenderPath)
+ {
+ RenderPathChanged();
+ }
+ RenderTextureFormat renderTextureFormat = (m_Camera.allowHDR ? RenderTextureFormat.ARGBHalf : RenderTextureFormat.ARGB32);
+ bool flag = m_ColourSpace != QualitySettings.activeColorSpace;
+ m_ColourSpace = QualitySettings.activeColorSpace;
+ if (WillRenderWithTemporalReprojection)
+ {
+ if (m_RadianceTarget_01 == null)
+ {
+ CreateRadianceTarget(kRadianceTarget01Name, out m_RadianceTarget_01);
+ m_CurrentRadianceTarget = m_RadianceTarget_01;
+ }
+ else if (flag || m_RadianceTarget_01.width != m_Camera.pixelWidth || m_RadianceTarget_01.height != m_Camera.pixelHeight || m_RadianceTarget_01.format != renderTextureFormat)
+ {
+ UnityEngine.Object.DestroyImmediate(m_RadianceTarget_01);
+ CreateRadianceTarget(kRadianceTarget01Name, out m_RadianceTarget_01);
+ m_CurrentRadianceTarget = m_RadianceTarget_01;
+ }
+ if (m_RadianceTarget_02 == null)
+ {
+ CreateRadianceTarget(kRadianceTarget02Name, out m_RadianceTarget_02);
+ m_PreviousRadianceTarget = m_RadianceTarget_02;
+ }
+ else if (flag || m_RadianceTarget_02.width != m_Camera.pixelWidth || m_RadianceTarget_02.height != m_Camera.pixelHeight || m_RadianceTarget_02.format != renderTextureFormat)
+ {
+ UnityEngine.Object.DestroyImmediate(m_RadianceTarget_02);
+ CreateRadianceTarget(kRadianceTarget02Name, out m_RadianceTarget_02);
+ m_PreviousRadianceTarget = m_RadianceTarget_02;
+ }
+ if (m_PreviousDepthTarget == null)
+ {
+ CreateDepthTarget(kPreviousDepthTargetName, out m_PreviousDepthTarget);
+ }
+ else if (m_PreviousDepthTarget.width != m_Camera.pixelWidth || m_PreviousDepthTarget.height != m_Camera.pixelHeight)
+ {
+ UnityEngine.Object.DestroyImmediate(m_PreviousDepthTarget);
+ CreateDepthTarget(kPreviousDepthTargetName, out m_PreviousDepthTarget);
+ }
+ }
+ if (m_ClearRadianceCmdBuffer == null)
+ {
+ m_ClearRadianceCmdBuffer = new CommandBuffer();
+ m_ClearRadianceCmdBuffer.name = kClearRadianceCmdBufferName;
+ }
+ CameraEvent evt = ((m_Camera.actualRenderingPath != RenderingPath.DeferredShading) ? (((m_Camera.depthTextureMode & DepthTextureMode.DepthNormals) == DepthTextureMode.DepthNormals) ? CameraEvent.BeforeDepthNormalsTexture : CameraEvent.BeforeDepthTexture) : CameraEvent.BeforeGBuffer);
+ if (!CameraHasClearRadianceCmdBuffer(out var foundCmd))
+ {
+ m_Camera.AddCommandBuffer(evt, m_ClearRadianceCmdBuffer);
+ }
+ else if (foundCmd != m_ClearRadianceCmdBuffer)
+ {
+ m_Camera.RemoveCommandBuffer(evt, foundCmd);
+ foundCmd.Dispose();
+ m_Camera.AddCommandBuffer(evt, m_ClearRadianceCmdBuffer);
+ }
+ if ((bool)m_DirectLight)
+ {
+ m_ShadowCascadesCmdBuffer = LightHasCascadesCopyCmdBuffer();
+ if (m_ShadowCascadesCmdBuffer == null)
+ {
+ m_ShadowCascadesCmdBuffer = new CommandBuffer();
+ m_ShadowCascadesCmdBuffer.name = kShadowCascadesCmdBufferName;
+ m_ShadowCascadesCmdBuffer.SetGlobalTexture("_ShadowCascades", new RenderTargetIdentifier(BuiltinRenderTextureType.CurrentActive));
+ m_DirectLight.AddCommandBuffer(LightEvent.AfterShadowMap, m_ShadowCascadesCmdBuffer);
+ }
+ m_DirectionalLightCmdBuffer = LightHasRenderCmdBuffer();
+ if (m_DirectionalLightCmdBuffer == null)
+ {
+ m_DirectionalLightCmdBuffer = new CommandBuffer();
+ m_DirectionalLightCmdBuffer.name = kDirectionalLightCmdBufferName;
+ m_DirectLight.AddCommandBuffer(LightEvent.AfterScreenspaceMask, m_DirectionalLightCmdBuffer);
+ }
+ if (m_ShadowProjectionType != QualitySettings.shadowProjection)
+ {
+ m_ShadowProjectionType = QualitySettings.shadowProjection;
+ }
+ }
+ }
+
+ private void OnDisable()
+ {
+ SetGlobalParamsToNull();
+ CommandBuffer[] commandBuffers = m_Camera.GetCommandBuffers(CameraEvent.AfterSkybox);
+ CameraEvent evt = ((m_Camera.actualRenderingPath != RenderingPath.DeferredShading) ? (((m_Camera.depthTextureMode & DepthTextureMode.DepthNormals) == DepthTextureMode.DepthNormals) ? CameraEvent.BeforeDepthNormalsTexture : CameraEvent.BeforeDepthTexture) : CameraEvent.BeforeGBuffer);
+ commandBuffers = m_Camera.GetCommandBuffers(evt);
+ CommandBuffer[] array = commandBuffers;
+ foreach (CommandBuffer commandBuffer in array)
+ {
+ if (commandBuffer.name == kClearRadianceCmdBufferName)
+ {
+ m_Camera.RemoveCommandBuffer(evt, commandBuffer);
+ break;
+ }
+ }
+ if ((bool)m_DirectLight)
+ {
+ commandBuffers = m_DirectLight.GetCommandBuffers(LightEvent.AfterShadowMap);
+ CommandBuffer[] array2 = commandBuffers;
+ foreach (CommandBuffer commandBuffer2 in array2)
+ {
+ if (commandBuffer2.name == kShadowCascadesCmdBufferName)
+ {
+ m_DirectLight.RemoveCommandBuffer(LightEvent.AfterShadowMap, commandBuffer2);
+ break;
+ }
+ }
+ commandBuffers = m_DirectLight.GetCommandBuffers(LightEvent.AfterScreenspaceMask);
+ CommandBuffer[] array3 = commandBuffers;
+ foreach (CommandBuffer commandBuffer3 in array3)
+ {
+ if (commandBuffer3.name == kDirectionalLightCmdBufferName)
+ {
+ m_DirectLight.RemoveCommandBuffer(LightEvent.AfterScreenspaceMask, commandBuffer3);
+ break;
+ }
+ }
+ }
+ if (m_LightVolumeCmdBuffers.Count > 0)
+ {
+ foreach (KeyValuePair<Light, CommandBuffer> lightVolumeCmdBuffer in m_LightVolumeCmdBuffers)
+ {
+ lightVolumeCmdBuffer.Key.RemoveCommandBuffer(LightEvent.AfterShadowMap, lightVolumeCmdBuffer.Value);
+ lightVolumeCmdBuffer.Value.Dispose();
+ }
+ m_LightVolumeCmdBuffers.Clear();
+ }
+ if (m_RenderNonShadowVolumes != null)
+ {
+ m_RenderNonShadowVolumes.Clear();
+ }
+ }
+
+ private void OnDestroy()
+ {
+ if ((bool)m_RadianceTarget_01)
+ {
+ m_RadianceTarget_01.Release();
+ UnityEngine.Object.DestroyImmediate(m_RadianceTarget_01);
+ m_RadianceTarget_01 = null;
+ }
+ if ((bool)m_RadianceTarget_02)
+ {
+ m_RadianceTarget_02.Release();
+ UnityEngine.Object.DestroyImmediate(m_RadianceTarget_02);
+ m_RadianceTarget_02 = null;
+ }
+ if ((bool)m_PreviousDepthTarget)
+ {
+ m_PreviousDepthTarget.Release();
+ UnityEngine.Object.DestroyImmediate(m_PreviousDepthTarget);
+ m_PreviousDepthTarget = null;
+ }
+ if (m_ClearRadianceCmdBuffer != null)
+ {
+ if (m_Camera.actualRenderingPath == RenderingPath.DeferredShading)
+ {
+ m_Camera.RemoveCommandBuffer(CameraEvent.BeforeGBuffer, m_ClearRadianceCmdBuffer);
+ }
+ else
+ {
+ CameraEvent evt = (((m_Camera.depthTextureMode & DepthTextureMode.DepthNormals) == DepthTextureMode.DepthNormals) ? CameraEvent.BeforeDepthNormalsTexture : CameraEvent.BeforeDepthTexture);
+ m_Camera.RemoveCommandBuffer(evt, m_ClearRadianceCmdBuffer);
+ }
+ m_ClearRadianceCmdBuffer.Dispose();
+ m_ClearRadianceCmdBuffer = null;
+ }
+ if (m_ShadowCascadesCmdBuffer != null)
+ {
+ if (m_DirectLight != null)
+ {
+ m_DirectLight.RemoveCommandBuffer(LightEvent.AfterShadowMap, m_ShadowCascadesCmdBuffer);
+ }
+ m_ShadowCascadesCmdBuffer.Dispose();
+ m_ShadowCascadesCmdBuffer = null;
+ }
+ if (m_DirectionalLightCmdBuffer != null)
+ {
+ if (m_DirectLight != null)
+ {
+ m_DirectLight.RemoveCommandBuffer(LightEvent.AfterScreenspaceMask, m_DirectionalLightCmdBuffer);
+ }
+ m_DirectionalLightCmdBuffer.Dispose();
+ m_DirectionalLightCmdBuffer = null;
+ }
+ if (m_LightVolumeCmdBuffers.Count > 0)
+ {
+ foreach (KeyValuePair<Light, CommandBuffer> lightVolumeCmdBuffer in m_LightVolumeCmdBuffers)
+ {
+ lightVolumeCmdBuffer.Key.RemoveCommandBuffer(LightEvent.AfterShadowMap, lightVolumeCmdBuffer.Value);
+ lightVolumeCmdBuffer.Value.Dispose();
+ }
+ m_LightVolumeCmdBuffers.Clear();
+ }
+ if (m_RenderNonShadowVolumes != null)
+ {
+ m_Camera.RemoveCommandBuffer(CameraEvent.BeforeImageEffectsOpaque, m_RenderNonShadowVolumes);
+ m_RenderNonShadowVolumes.Dispose();
+ m_RenderNonShadowVolumes = null;
+ }
+ }
+
+ private void OnPreRender()
+ {
+ if (!CheckHasSystemSupport())
+ {
+ base.enabled = false;
+ }
+ UpdateResources();
+ SetShaderKeyWords();
+ RenderTextureFormat format = (m_Camera.allowHDR ? RenderTextureFormat.ARGBHalf : RenderTextureFormat.ARGB32);
+ m_PerFrameRadianceTarget = RenderTexture.GetTemporary(m_X, m_Y, 0, format, RenderTextureReadWrite.Linear, AntiAliasingLevel());
+ m_PerFrameRadianceTarget.name = "_DS_Haze_PerFrameRadiance";
+ m_PerFrameRadianceTarget.filterMode = FilterMode.Point;
+ m_ClearRadianceCmdBuffer.Clear();
+ m_ClearRadianceCmdBuffer.SetRenderTarget(m_PerFrameRadianceTarget);
+ m_ClearRadianceCmdBuffer.ClearRenderTarget(clearDepth: false, clearColor: true, Color.clear);
+ DS_HazeCore instance = DS_HazeCore.Instance;
+ DS_HazeContextItem dS_HazeContextItem = null;
+ if (m_OverrideContextAsset && m_Context != null)
+ {
+ dS_HazeContextItem = ((!m_OverrideContextVariant) ? m_Context.Context.GetContextItemBlended(m_Time) : m_Context.Context.GetItemAtIndex(m_ContextItemIndex));
+ }
+ else
+ {
+ if (instance == null)
+ {
+ SetGlobalParamsToNull();
+ return;
+ }
+ dS_HazeContextItem = instance.GetRenderContextAtPosition(base.transform.position);
+ }
+ if (dS_HazeContextItem == null)
+ {
+ SetGlobalParamsToNull();
+ }
+ else
+ {
+ SetMaterialFromContext(dS_HazeContextItem);
+ float farClipPlane = m_Camera.farClipPlane;
+ float num = m_Camera.fieldOfView * 0.5f;
+ float num2 = Mathf.Tan(num * ((float)Math.PI / 180f));
+ float num3 = num2 * m_Camera.aspect;
+ Vector3 vector = base.transform.forward * farClipPlane;
+ Vector3 vector2 = base.transform.right * num3 * farClipPlane;
+ Vector3 vector3 = base.transform.up * num2 * farClipPlane;
+ m_Material.SetVector("_ViewportCorner", vector - vector2 - vector3);
+ m_Material.SetVector("_ViewportRight", vector2 * 2f);
+ m_Material.SetVector("_ViewportUp", vector3 * 2f);
+ if ((bool)m_DirectLight && m_RenderAtmosphereVolumetrics)
+ {
+ m_DirectionalLightCmdBuffer.Blit(BuiltinRenderTextureType.None, m_PerFrameRadianceTarget, m_Material, (int)(m_VolumeSamples + ((m_DownsampleFactor != SizeFactor.Half) ? 3 : 0)));
+ }
+ }
+ if (!m_RenderLocalVolumetrics)
+ {
+ return;
+ }
+ Matrix4x4 gPUProjectionMatrix = GL.GetGPUProjectionMatrix(m_Camera.projectionMatrix, renderIntoTexture: true);
+ Matrix4x4 viewProjMtx = gPUProjectionMatrix * m_Camera.worldToCameraMatrix;
+ instance.GetRenderLightVolumes(base.transform.position, m_PerFrameLightVolumes, m_PerFrameShadowLightVolumes);
+ if (m_PerFrameLightVolumes.Count > 0)
+ {
+ m_RenderNonShadowVolumes.SetRenderTarget(m_PerFrameRadianceTarget);
+ }
+ foreach (DS_HazeLightVolume perFrameLightVolume in m_PerFrameLightVolumes)
+ {
+ perFrameLightVolume.SetupMaterialPerFrame(viewProjMtx, m_Camera.worldToCameraMatrix, base.transform, (!WillRenderWithTemporalReprojection) ? 0f : m_InterleavedOffsetIndex);
+ perFrameLightVolume.AddLightRenderCommand(base.transform, m_RenderNonShadowVolumes, (int)m_DownsampleFactor);
+ }
+ foreach (DS_HazeLightVolume perFrameShadowLightVolume in m_PerFrameShadowLightVolumes)
+ {
+ perFrameShadowLightVolume.SetupMaterialPerFrame(viewProjMtx, m_Camera.worldToCameraMatrix, base.transform, (!WillRenderWithTemporalReprojection) ? 0f : m_InterleavedOffsetIndex);
+ perFrameShadowLightVolume.FillLightCommandBuffer(m_PerFrameRadianceTarget, base.transform, (int)m_DownsampleFactor);
+ m_LightVolumeCmdBuffers.Add(perFrameShadowLightVolume.LightSource, perFrameShadowLightVolume.RenderCommandBuffer);
+ }
+ }
+
+ private void BlitToMRT(RenderTexture source, RenderTexture[] destination, Material mat, int pass)
+ {
+ RenderBuffer[] array = new RenderBuffer[destination.Length];
+ for (int i = 0; i < destination.Length; i++)
+ {
+ ref RenderBuffer reference = ref array[i];
+ reference = destination[i].colorBuffer;
+ }
+ Graphics.SetRenderTarget(array, destination[0].depthBuffer);
+ mat.SetTexture("_MainTex", source);
+ mat.SetPass(pass);
+ GL.PushMatrix();
+ GL.LoadOrtho();
+ GL.Begin(7);
+ GL.MultiTexCoord2(0, 0f, 0f);
+ GL.Vertex3(0f, 0f, 0.1f);
+ GL.MultiTexCoord2(0, 1f, 0f);
+ GL.Vertex3(1f, 0f, 0.1f);
+ GL.MultiTexCoord2(0, 1f, 1f);
+ GL.Vertex3(1f, 1f, 0.1f);
+ GL.MultiTexCoord2(0, 0f, 1f);
+ GL.Vertex3(0f, 1f, 0.1f);
+ GL.End();
+ GL.PopMatrix();
+ }
+
+ [ImageEffectOpaque]
+ private void OnRenderImage(RenderTexture src, RenderTexture dest)
+ {
+ RenderTexture renderTexture = null;
+ RenderTexture renderTexture2 = null;
+ if (m_RenderAtmosphereVolumetrics || m_RenderLocalVolumetrics)
+ {
+ renderTexture = RenderTexture.GetTemporary(m_X, m_Y, 0, m_Camera.allowHDR ? RenderTextureFormat.ARGBHalf : RenderTextureFormat.ARGB32);
+ renderTexture2 = RenderTexture.GetTemporary(m_X, m_Y, 0, RenderTextureFormat.RFloat, RenderTextureReadWrite.Linear, 1);
+ Graphics.Blit(null, renderTexture2, m_Material, (m_DownsampleFactor != SizeFactor.Half) ? 11 : 10);
+ m_Material.SetTexture("_HalfResDepth", renderTexture2);
+ Graphics.Blit(m_PerFrameRadianceTarget, renderTexture, m_Material, 6);
+ Graphics.Blit(renderTexture, m_PerFrameRadianceTarget, m_Material, 7);
+ if (m_TemporalReprojection)
+ {
+ m_Material.SetTexture("_PrevAccumBuffer", m_PreviousRadianceTarget);
+ m_Material.SetTexture("_PrevDepthBuffer", m_PreviousDepthTarget);
+ }
+ }
+ m_PerFrameRadianceTarget.filterMode = FilterMode.Bilinear;
+ m_Material.SetTexture("_RadianceBuffer", m_PerFrameRadianceTarget);
+ if (dest == null)
+ {
+ RenderTexture temporary = RenderTexture.GetTemporary(src.width, src.height, src.depth, src.format);
+ if (WillRenderWithTemporalReprojection)
+ {
+ RenderTexture[] destination = new RenderTexture[2] { temporary, m_CurrentRadianceTarget };
+ BlitToMRT(src, destination, m_Material, 8);
+ }
+ else
+ {
+ Graphics.Blit(src, temporary, m_Material, 8);
+ }
+ Graphics.Blit((Texture)temporary, (RenderTexture)null);
+ RenderTexture.ReleaseTemporary(temporary);
+ }
+ else if (WillRenderWithTemporalReprojection)
+ {
+ RenderTexture[] destination2 = new RenderTexture[2] { dest, m_CurrentRadianceTarget };
+ BlitToMRT(src, destination2, m_Material, 8);
+ }
+ else
+ {
+ Graphics.Blit(src, dest, m_Material, 8);
+ }
+ if (WillRenderWithTemporalReprojection)
+ {
+ Graphics.Blit(src, m_PreviousDepthTarget, m_Material, 9);
+ Graphics.SetRenderTarget(dest);
+ Shader.SetGlobalTexture("_DS_RadianceBuffer", m_CurrentRadianceTarget);
+ RenderTexture.ReleaseTemporary(m_PerFrameRadianceTarget);
+ }
+ else
+ {
+ Shader.SetGlobalTexture("_DS_RadianceBuffer", m_PerFrameRadianceTarget);
+ }
+ if (renderTexture != null)
+ {
+ RenderTexture.ReleaseTemporary(renderTexture);
+ }
+ if (renderTexture2 != null)
+ {
+ RenderTexture.ReleaseTemporary(renderTexture2);
+ }
+ }
+
+ private void OnPostRender()
+ {
+ if (WillRenderWithTemporalReprojection)
+ {
+ RenderTexture currentRadianceTarget = m_CurrentRadianceTarget;
+ m_CurrentRadianceTarget = m_PreviousRadianceTarget;
+ m_PreviousRadianceTarget = currentRadianceTarget;
+ Matrix4x4 worldToCameraMatrix = m_Camera.worldToCameraMatrix;
+ Matrix4x4 gPUProjectionMatrix = GL.GetGPUProjectionMatrix(m_Camera.projectionMatrix, renderIntoTexture: true);
+ m_PreviousViewProjMatrix = gPUProjectionMatrix * worldToCameraMatrix;
+ m_PreviousInvViewProjMatrix = m_PreviousViewProjMatrix.inverse;
+ }
+ else
+ {
+ RenderTexture.ReleaseTemporary(m_PerFrameRadianceTarget);
+ }
+ if (m_LightVolumeCmdBuffers.Count > 0)
+ {
+ foreach (KeyValuePair<Light, CommandBuffer> lightVolumeCmdBuffer in m_LightVolumeCmdBuffers)
+ {
+ lightVolumeCmdBuffer.Value.Clear();
+ }
+ m_LightVolumeCmdBuffers.Clear();
+ }
+ if ((bool)m_DirectLight)
+ {
+ m_DirectionalLightCmdBuffer.Clear();
+ }
+ m_RenderNonShadowVolumes.Clear();
+ m_PerFrameLightVolumes.Clear();
+ m_PerFrameShadowLightVolumes.Clear();
+ }
+}
diff --git a/DeepSky.Haze/DS_HazeZone.cs b/DeepSky.Haze/DS_HazeZone.cs
new file mode 100644
index 0000000..b4ffabb
--- /dev/null
+++ b/DeepSky.Haze/DS_HazeZone.cs
@@ -0,0 +1,105 @@
+using UnityEngine;
+
+namespace DeepSky.Haze;
+
+[ExecuteInEditMode]
+[AddComponentMenu("DeepSky Haze/Zone", 52)]
+public class DS_HazeZone : MonoBehaviour
+{
+ [SerializeField]
+ private DS_HazeContext m_Context = new DS_HazeContext();
+
+ [SerializeField]
+ [Range(0f, 250f)]
+ private int m_Priority;
+
+ [SerializeField]
+ [Range(0.001f, 1f)]
+ private float m_BlendRange = 0.1f;
+
+ private Bounds m_AABB;
+
+ private float m_BlendRangeInverse;
+
+ public DS_HazeContext Context => m_Context;
+
+ public int Priority
+ {
+ get
+ {
+ return m_Priority;
+ }
+ set
+ {
+ m_Priority = ((value > 0) ? value : 0);
+ }
+ }
+
+ public float BlendRange
+ {
+ get
+ {
+ return m_BlendRange;
+ }
+ set
+ {
+ m_BlendRange = Mathf.Clamp01(value);
+ }
+ }
+
+ private void Setup()
+ {
+ m_AABB = new Bounds(Vector3.zero, base.transform.localScale);
+ m_BlendRangeInverse = 1f / Mathf.Max(Mathf.Min(m_AABB.extents.x, m_AABB.extents.y, m_AABB.extents.z) * m_BlendRange, Mathf.Epsilon);
+ }
+
+ private void Start()
+ {
+ Setup();
+ }
+
+ private void OnValidate()
+ {
+ Setup();
+ }
+
+ public bool Contains(Vector3 position)
+ {
+ if (base.transform.hasChanged)
+ {
+ Setup();
+ }
+ Vector3 point = base.transform.InverseTransformPoint(position);
+ point.Scale(base.transform.localScale);
+ return m_AABB.Contains(point);
+ }
+
+ public float GetBlendWeight(Vector3 position)
+ {
+ Vector3 vector = base.transform.InverseTransformPoint(position);
+ vector.Scale(base.transform.localScale);
+ float num = Mathf.Abs(m_AABB.extents.x - Mathf.Abs(vector.x));
+ float num2 = Mathf.Abs(m_AABB.extents.y - Mathf.Abs(vector.y));
+ float num3 = Mathf.Abs(m_AABB.extents.z - Mathf.Abs(vector.z));
+ float num4 = Mathf.Min(num, num2, num3);
+ return Mathf.Clamp01(num4 * m_BlendRangeInverse);
+ }
+
+ public static bool operator >(DS_HazeZone c1, DS_HazeZone c2)
+ {
+ if (c1.m_Priority == c2.m_Priority)
+ {
+ return (Vector3.Dot(c1.m_AABB.extents, c1.m_AABB.extents) > Vector3.Dot(c2.m_AABB.extents, c2.m_AABB.extents)) ? true : false;
+ }
+ return (c1.m_Priority > c2.m_Priority) ? true : false;
+ }
+
+ public static bool operator <(DS_HazeZone c1, DS_HazeZone c2)
+ {
+ if (c1.m_Priority == c2.m_Priority)
+ {
+ return (Vector3.Dot(c1.m_AABB.extents, c1.m_AABB.extents) < Vector3.Dot(c2.m_AABB.extents, c2.m_AABB.extents)) ? true : false;
+ }
+ return (c1.m_Priority < c2.m_Priority) ? true : false;
+ }
+}
diff --git a/DeepSky.Haze/DS_LightFalloff.cs b/DeepSky.Haze/DS_LightFalloff.cs
new file mode 100644
index 0000000..7aeca76
--- /dev/null
+++ b/DeepSky.Haze/DS_LightFalloff.cs
@@ -0,0 +1,7 @@
+namespace DeepSky.Haze;
+
+public enum DS_LightFalloff
+{
+ Unity,
+ Quadratic
+}
diff --git a/DeepSky.Haze/DS_SamplingQuality.cs b/DeepSky.Haze/DS_SamplingQuality.cs
new file mode 100644
index 0000000..5ac91e5
--- /dev/null
+++ b/DeepSky.Haze/DS_SamplingQuality.cs
@@ -0,0 +1,9 @@
+namespace DeepSky.Haze;
+
+public enum DS_SamplingQuality
+{
+ x4,
+ x8,
+ x16,
+ x32
+}