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 m_PerFrameLightVolumes = new List(); private List m_PerFrameShadowLightVolumes = new List(); private Dictionary m_LightVolumeCmdBuffers = new Dictionary(); 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(); 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("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 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 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 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(); } }