diff options
Diffstat (limited to 'DeepSky.Haze')
-rw-r--r-- | DeepSky.Haze/DS_HazeContext.cs | 154 | ||||
-rw-r--r-- | DeepSky.Haze/DS_HazeContextAsset.cs | 14 | ||||
-rw-r--r-- | DeepSky.Haze/DS_HazeContextItem.cs | 173 | ||||
-rw-r--r-- | DeepSky.Haze/DS_HazeCore.cs | 218 | ||||
-rw-r--r-- | DeepSky.Haze/DS_HazeLightVolume.cs | 604 | ||||
-rw-r--r-- | DeepSky.Haze/DS_HazeView.cs | 1120 | ||||
-rw-r--r-- | DeepSky.Haze/DS_HazeZone.cs | 105 | ||||
-rw-r--r-- | DeepSky.Haze/DS_LightFalloff.cs | 7 | ||||
-rw-r--r-- | DeepSky.Haze/DS_SamplingQuality.cs | 9 |
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 +} |