//------------------------------------------------------------------------------------------------------------------ // Volumetric Fog & Mist 2 // Created by Kronnect //------------------------------------------------------------------------------------------------------------------ using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.Rendering; #if UNITY_2023_3_OR_NEWER using UnityEngine.Rendering.RenderGraphModule; #endif using UnityEngine.Rendering.Universal; namespace VolumetricFogAndMist2 { public class VolumetricFogRenderFeature : ScriptableRendererFeature { public static class ShaderParams { public const string LightBufferName = "_LightBuffer"; public static int LightBuffer = Shader.PropertyToID(LightBufferName); public static int LightBufferSize = Shader.PropertyToID("_VFRTSize"); public static int MainTex = Shader.PropertyToID("_MainTex"); public static int BlurRT = Shader.PropertyToID("_BlurTex"); public static int BlurRT2 = Shader.PropertyToID("_BlurTex2"); public static int MiscData = Shader.PropertyToID("_MiscData"); public static int ForcedInvisible = Shader.PropertyToID("_ForcedInvisible"); public static int DownsampledDepth = Shader.PropertyToID("_DownsampledDepth"); public static int BlueNoiseTexture = Shader.PropertyToID("_BlueNoise"); public static int BlurScale = Shader.PropertyToID("_BlurScale"); public static int Downscaling = Shader.PropertyToID("_Downscaling"); public static int ScatteringData = Shader.PropertyToID("_ScatteringData"); public static int ScatteringTint = Shader.PropertyToID("_ScatteringTint"); public static int BlurredTex = Shader.PropertyToID("_BlurredTex"); public const string SKW_DITHER = "DITHER"; public const string SKW_EDGE_PRESERVE = "EDGE_PRESERVE"; public const string SKW_EDGE_PRESERVE_UPSCALING = "EDGE_PRESERVE_UPSCALING"; public const string SKW_SCATTERING_HQ = "SCATTERING_HQ"; public const string SKW_DEPTH_PEELING = "VF2_DEPTH_PEELING"; public const string SKW_DEPTH_PREPASS = "VF2_DEPTH_PREPASS"; } public static int GetScaledSize (int size, float factor) { size = (int)(size / factor); size /= 2; if (size < 1) size = 1; return size * 2; } class VolumetricFogRenderPass : ScriptableRenderPass { const string m_ProfilerTag = "Volumetric Fog Buffer Rendering"; static FilteringSettings filteringSettings = new FilteringSettings(RenderQueueRange.transparent, -1); static readonly List shaderTagIdList = new List(); RTHandle m_LightBuffer; VolumetricFogRenderFeature settings; public VolumetricFogRenderPass () { shaderTagIdList.Clear(); shaderTagIdList.Add(new ShaderTagId("UniversalForward")); shaderTagIdList.Add(new ShaderTagId("SRPDefaultUnlit")); RenderTargetIdentifier lightBuffer = new RenderTargetIdentifier(ShaderParams.LightBuffer, 0, CubemapFace.Unknown, -1); m_LightBuffer = RTHandles.Alloc(lightBuffer, name: ShaderParams.LightBufferName); } public void CleanUp () { RTHandles.Release(m_LightBuffer); } public void Setup (VolumetricFogRenderFeature settings, RenderPassEvent renderPassEvent) { this.settings = settings; this.renderPassEvent = renderPassEvent; } #if UNITY_2023_3_OR_NEWER [Obsolete] #endif public override void Configure (CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) { RenderTextureDescriptor lightBufferDesc = cameraTextureDescriptor; VolumetricFogManager manager = VolumetricFogManager.GetManagerIfExists(); if (manager != null) { if (manager.downscaling > 1f) { int size = GetScaledSize(cameraTextureDescriptor.width, manager.downscaling); lightBufferDesc.width = size; lightBufferDesc.height = size; } lightBufferDesc.colorFormat = manager.blurHDR ? RenderTextureFormat.ARGBHalf : RenderTextureFormat.ARGB32; cmd.SetGlobalVector(ShaderParams.LightBufferSize, new Vector4(lightBufferDesc.width, lightBufferDesc.height, manager.downscaling > 1f ? 1f : 0, 0)); } lightBufferDesc.depthBufferBits = 0; lightBufferDesc.msaaSamples = 1; lightBufferDesc.useMipMap = false; cmd.GetTemporaryRT(ShaderParams.LightBuffer, lightBufferDesc, FilterMode.Bilinear); ConfigureTarget(m_LightBuffer); ConfigureClear(ClearFlag.Color, new Color(0, 0, 0, 0)); ConfigureInput(ScriptableRenderPassInput.Depth); } #if UNITY_2023_3_OR_NEWER [Obsolete] #endif public override void Execute (ScriptableRenderContext context, ref RenderingData renderingData) { VolumetricFogManager manager = VolumetricFogManager.GetManagerIfExists(); CommandBuffer cmd = CommandBufferPool.Get(m_ProfilerTag); cmd.SetGlobalInt(ShaderParams.ForcedInvisible, 0); context.ExecuteCommandBuffer(cmd); if (manager == null || (manager.downscaling <= 1f && manager.blurPasses < 1 && manager.scattering <= 0 && !isUsingDepthPeeling)) { CommandBufferPool.Release(cmd); return; } cmd.Clear(); foreach (VolumetricFog vg in VolumetricFog.volumetricFogs) { if (vg != null) { vg.meshRenderer.renderingLayerMask |= VolumetricFogManager.FOG_VOLUMES_RENDERING_LAYER; if (isUsingDepthPeeling && renderPassEvent < RenderPassEvent.AfterRenderingTransparents) { vg.RenderDistantFog(cmd); } } } if (isUsingDepthPeeling) { if (renderPassEvent < RenderPassEvent.AfterRenderingTransparents) { cmd.DisableShaderKeyword(ShaderParams.SKW_DEPTH_PREPASS); cmd.EnableShaderKeyword(ShaderParams.SKW_DEPTH_PEELING); } else { cmd.DisableShaderKeyword(ShaderParams.SKW_DEPTH_PEELING); cmd.EnableShaderKeyword(ShaderParams.SKW_DEPTH_PREPASS); } context.ExecuteCommandBuffer(cmd); } var sortFlags = SortingCriteria.CommonTransparent; var drawSettings = CreateDrawingSettings(shaderTagIdList, ref renderingData, sortFlags); var filterSettings = filteringSettings; filterSettings.layerMask = settings.fogLayerMask; filterSettings.renderingLayerMask = VolumetricFogManager.FOG_VOLUMES_RENDERING_LAYER; context.DrawRenderers(renderingData.cullResults, ref drawSettings, ref filterSettings); CommandBufferPool.Release(cmd); } #if UNITY_2023_3_OR_NEWER class PassData { public RendererListHandle rendererListHandle; public UniversalCameraData cameraData; public RenderPassEvent renderPassEvent; } public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) { using (var builder = renderGraph.AddUnsafePass(m_ProfilerTag, out var passData)) { builder.AllowPassCulling(false); UniversalResourceData resourceData = frameData.Get(); UniversalRenderingData renderingData = frameData.Get(); UniversalLightData lightData = frameData.Get(); UniversalCameraData cameraData = frameData.Get(); passData.cameraData = cameraData; passData.renderPassEvent = renderPassEvent; builder.UseTexture(resourceData.activeDepthTexture, AccessFlags.Read); ConfigureInput(ScriptableRenderPassInput.Depth); SortingCriteria sortingCriteria = SortingCriteria.CommonTransparent; var drawingSettings = CreateDrawingSettings(shaderTagIdList, renderingData, cameraData, lightData, sortingCriteria); var filterSettings = filteringSettings; filterSettings.layerMask = settings.fogLayerMask; filterSettings.renderingLayerMask = VolumetricFogManager.FOG_VOLUMES_RENDERING_LAYER; RendererListParams listParams = new RendererListParams(renderingData.cullResults, drawingSettings, filterSettings); passData.rendererListHandle = renderGraph.CreateRendererList(listParams); builder.UseRendererList(passData.rendererListHandle); builder.SetRenderFunc(static (PassData passData, UnsafeGraphContext context) => { CommandBuffer cmd = CommandBufferHelpers.GetNativeCommandBuffer(context.cmd); RenderTextureDescriptor lightBufferDesc = passData.cameraData.cameraTargetDescriptor; VolumetricFogManager manager = VolumetricFogManager.GetManagerIfExists(); if (manager != null) { if (manager.downscaling > 1f) { int size = GetScaledSize(lightBufferDesc.width, manager.downscaling); lightBufferDesc.width = size; lightBufferDesc.height = size; } lightBufferDesc.colorFormat = manager.blurHDR ? RenderTextureFormat.ARGBHalf : RenderTextureFormat.ARGB32; cmd.SetGlobalVector(ShaderParams.LightBufferSize, new Vector4(lightBufferDesc.width, lightBufferDesc.height, manager.downscaling > 1f ? 1f : 0, 0)); } lightBufferDesc.depthBufferBits = 0; lightBufferDesc.msaaSamples = 1; lightBufferDesc.useMipMap = false; cmd.GetTemporaryRT(ShaderParams.LightBuffer, lightBufferDesc, FilterMode.Bilinear); RenderTargetIdentifier rti = new RenderTargetIdentifier(ShaderParams.LightBuffer, 0, CubemapFace.Unknown, -1); cmd.SetRenderTarget(rti); cmd.ClearRenderTarget(false, true, new Color(0, 0, 0, 0)); cmd.SetGlobalInt(ShaderParams.ForcedInvisible, 0); if (manager == null || (manager.downscaling <= 1f && manager.blurPasses < 1 && manager.scattering <= 0 && !isUsingDepthPeeling)) { return; } int vgCount = VolumetricFog.volumetricFogs.Count; for (int i = 0; i < vgCount; i++) { VolumetricFog vg = VolumetricFog.volumetricFogs[i]; if (vg != null) { vg.meshRenderer.renderingLayerMask |= VolumetricFogManager.FOG_VOLUMES_RENDERING_LAYER; if (isUsingDepthPeeling && passData.renderPassEvent < RenderPassEvent.AfterRenderingTransparents) { vg.RenderDistantFog(cmd); } } } if (isUsingDepthPeeling) { if (passData.renderPassEvent < RenderPassEvent.AfterRenderingTransparents) { cmd.DisableShaderKeyword(ShaderParams.SKW_DEPTH_PREPASS); cmd.EnableShaderKeyword(ShaderParams.SKW_DEPTH_PEELING); } else { cmd.DisableShaderKeyword(ShaderParams.SKW_DEPTH_PEELING); cmd.EnableShaderKeyword(ShaderParams.SKW_DEPTH_PREPASS); } } context.cmd.DrawRendererList(passData.rendererListHandle); }); } } #endif } class BlurRenderPass : ScriptableRenderPass { enum Pass { BlurHorizontal = 0, BlurVertical = 1, BlurVerticalAndBlend = 2, UpscalingBlend = 3, DownscaleDepth = 4, BlurVerticalFinal = 5, Resample = 6, ResampleAndCombine = 7, ScatteringPrefilter = 8, ScatteringBlend = 9, Blend = 10 } class PassData { #if UNITY_2022_3_OR_NEWER public RTHandle source; #else public RenderTargetIdentifier source; #endif #if UNITY_2023_3_OR_NEWER public TextureHandle colorTexture; public UniversalCameraData cameraData; #endif public RenderPassEvent renderPassEvent; } const string m_ProfilerTag = "Volumetric Fog Render Feature"; ScriptableRenderer renderer; static Material mat; static RenderTextureDescriptor sourceDesc; static VolumetricFogManager manager; static readonly PassData passData = new PassData(); public void Setup (Shader shader, ScriptableRenderer renderer, RenderPassEvent renderPassEvent) { this.renderPassEvent = renderPassEvent; this.renderer = renderer; manager = VolumetricFogManager.GetManagerIfExists(); if (mat == null) { mat = CoreUtils.CreateEngineMaterial(shader); Texture2D noiseTex = Resources.Load("Textures/blueNoiseVF128"); mat.SetTexture(ShaderParams.BlueNoiseTexture, noiseTex); } } #if UNITY_2023_3_OR_NEWER [Obsolete] #endif public override void Configure (CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) { sourceDesc = cameraTextureDescriptor; ConfigureInput(ScriptableRenderPassInput.Depth); } #if UNITY_2023_3_OR_NEWER [Obsolete] #endif public override void Execute (ScriptableRenderContext context, ref RenderingData renderingData) { #if UNITY_2022_1_OR_NEWER passData.source = renderer.cameraColorTargetHandle; #else passData.source = renderer.cameraColorTarget; #endif passData.renderPassEvent = renderPassEvent; CommandBuffer cmd = CommandBufferPool.Get(m_ProfilerTag); ExecutePass(passData, cmd); context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); } #if UNITY_2023_3_OR_NEWER public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) { using (var builder = renderGraph.AddUnsafePass(m_ProfilerTag, out var passData)) { builder.AllowPassCulling(false); UniversalResourceData resourceData = frameData.Get(); UniversalRenderingData renderingData = frameData.Get(); UniversalLightData lightData = frameData.Get(); UniversalCameraData cameraData = frameData.Get(); passData.cameraData = cameraData; passData.colorTexture = resourceData.activeColorTexture; builder.UseTexture(resourceData.activeColorTexture, AccessFlags.ReadWrite); builder.UseTexture(resourceData.activeDepthTexture, AccessFlags.Read); ConfigureInput(ScriptableRenderPassInput.Depth); passData.renderPassEvent = renderPassEvent; sourceDesc = cameraData.cameraTargetDescriptor; builder.SetRenderFunc(static (PassData passData, UnsafeGraphContext context) => { CommandBuffer cmd = CommandBufferHelpers.GetNativeCommandBuffer(context.cmd); passData.source = passData.colorTexture; ExecutePass(passData, cmd); }); } } #endif static void ExecutePass (PassData passData, CommandBuffer cmd) { if (manager == null || (manager.downscaling <= 1f && manager.blurPasses < 1 && manager.scattering <= 0 && !isUsingDepthPeeling)) { Cleanup(); return; } mat.SetVector(ShaderParams.MiscData, new Vector4(manager.ditherStrength * 0.1f, 0, manager.blurEdgeDepthThreshold, manager.downscalingEdgeDepthThreshold * 0.001f)); if (manager.ditherStrength > 0) { mat.EnableKeyword(ShaderParams.SKW_DITHER); } else { mat.DisableKeyword(ShaderParams.SKW_DITHER); } mat.DisableKeyword(ShaderParams.SKW_EDGE_PRESERVE); mat.DisableKeyword(ShaderParams.SKW_EDGE_PRESERVE_UPSCALING); if (manager.blurPasses > 0 && manager.blurEdgePreserve) { mat.EnableKeyword(manager.downscaling > 1f ? ShaderParams.SKW_EDGE_PRESERVE_UPSCALING : ShaderParams.SKW_EDGE_PRESERVE); } #if UNITY_2022_3_OR_NEWER RTHandle source = passData.source; #else RenderTargetIdentifier source = passData.source; #endif cmd.SetGlobalInt(ShaderParams.ForcedInvisible, 1); RenderTextureDescriptor rtBlurDesc = sourceDesc; rtBlurDesc.width = GetScaledSize(sourceDesc.width, manager.downscaling); rtBlurDesc.height = GetScaledSize(sourceDesc.height, manager.downscaling); rtBlurDesc.useMipMap = false; rtBlurDesc.colorFormat = manager.blurHDR ? RenderTextureFormat.ARGBHalf : RenderTextureFormat.ARGB32; rtBlurDesc.msaaSamples = 1; rtBlurDesc.depthBufferBits = 0; bool usingDownscaling = manager.downscaling > 1f; bool isFrontDepthPeeling = isUsingDepthPeeling && passData.renderPassEvent >= RenderPassEvent.AfterRenderingTransparents; if (usingDownscaling && !isFrontDepthPeeling) { RenderTextureDescriptor rtDownscaledDepth = rtBlurDesc; rtDownscaledDepth.colorFormat = RenderTextureFormat.RFloat; cmd.GetTemporaryRT(ShaderParams.DownsampledDepth, rtDownscaledDepth, FilterMode.Bilinear); FullScreenBlit(cmd, source, ShaderParams.DownsampledDepth, mat, (int)Pass.DownscaleDepth); } if (isUsingDepthPeeling) { mat.EnableKeyword(ShaderParams.SKW_DEPTH_PEELING); } else { mat.DisableKeyword(ShaderParams.SKW_DEPTH_PEELING); } if (manager.blurPasses < 1) { // no blur but downscaling FullScreenBlit(cmd, ShaderParams.LightBuffer, source, mat, usingDownscaling ? (int)Pass.UpscalingBlend : (int)Pass.Blend); } else { // blur (with or without downscaling) rtBlurDesc.width = GetScaledSize(sourceDesc.width, manager.blurDownscaling); rtBlurDesc.height = GetScaledSize(sourceDesc.height, manager.blurDownscaling); cmd.GetTemporaryRT(ShaderParams.BlurRT, rtBlurDesc, FilterMode.Bilinear); cmd.GetTemporaryRT(ShaderParams.BlurRT2, rtBlurDesc, FilterMode.Bilinear); cmd.SetGlobalFloat(ShaderParams.BlurScale, manager.blurSpread * manager.blurDownscaling); FullScreenBlit(cmd, ShaderParams.LightBuffer, ShaderParams.BlurRT, mat, (int)Pass.BlurHorizontal); cmd.SetGlobalFloat(ShaderParams.BlurScale, manager.blurSpread); for (int k = 0; k < manager.blurPasses - 1; k++) { FullScreenBlit(cmd, ShaderParams.BlurRT, ShaderParams.BlurRT2, mat, (int)Pass.BlurVertical); FullScreenBlit(cmd, ShaderParams.BlurRT2, ShaderParams.BlurRT, mat, (int)Pass.BlurHorizontal); } if (usingDownscaling) { FullScreenBlit(cmd, ShaderParams.BlurRT, ShaderParams.BlurRT2, mat, (int)Pass.BlurVerticalFinal); FullScreenBlit(cmd, ShaderParams.BlurRT2, source, mat, (int)Pass.UpscalingBlend); } else { FullScreenBlit(cmd, ShaderParams.BlurRT, source, mat, (int)Pass.BlurVerticalAndBlend); } cmd.ReleaseTemporaryRT(ShaderParams.BlurRT2); cmd.ReleaseTemporaryRT(ShaderParams.BlurRT); } if (manager.scattering > 0 && (!isUsingDepthPeeling || isFrontDepthPeeling)) { ComputeScattering(cmd, source, mat); } cmd.ReleaseTemporaryRT(ShaderParams.LightBuffer); if (usingDownscaling) { cmd.ReleaseTemporaryRT(ShaderParams.DownsampledDepth); } } struct ScatteringMipData { public int rtDown, rtUp, width, height; } static ScatteringMipData[] rt; const int PYRAMID_MAX_LEVELS = 5; #if UNITY_2022_1_OR_NEWER static void ComputeScattering(CommandBuffer cmd, RTHandle source, Material mat) { #else static void ComputeScattering (CommandBuffer cmd, RenderTargetIdentifier source, Material mat) { #endif mat.SetVector(ShaderParams.ScatteringData, new Vector4(manager.scatteringThreshold, manager.scatteringIntensity, 1f - manager.scatteringAbsorption, manager.scattering)); mat.SetColor(ShaderParams.ScatteringTint, manager.scatteringTint); float downscaling = manager.downscaling; // Initialize buffers descriptors if (rt == null || rt.Length != PYRAMID_MAX_LEVELS + 1) { rt = new ScatteringMipData[PYRAMID_MAX_LEVELS + 1]; for (int k = 0; k < rt.Length; k++) { rt[k].rtDown = Shader.PropertyToID("_VFogDownMip" + k); rt[k].rtUp = Shader.PropertyToID("_VFogUpMip" + k); } } int width = GetScaledSize(sourceDesc.width, downscaling); int height = GetScaledSize(sourceDesc.height, downscaling); if (downscaling > 1 && manager.scatteringHighQuality) { mat.EnableKeyword(ShaderParams.SKW_SCATTERING_HQ); } else { mat.DisableKeyword(ShaderParams.SKW_SCATTERING_HQ); } if (!manager.scatteringHighQuality) { width /= 2; height /= 2; } int mipCount = manager.scatteringHighQuality ? 5 : 4; RenderTextureDescriptor scatterDesc = sourceDesc; scatterDesc.colorFormat = RenderTextureFormat.ARGBHalf; scatterDesc.msaaSamples = 1; scatterDesc.depthBufferBits = 0; for (int k = 0; k <= mipCount; k++) { if (width < 2) width = 2; if (height < 2) height = 2; scatterDesc.width = rt[k].width = width; scatterDesc.height = rt[k].height = height; cmd.GetTemporaryRT(rt[k].rtDown, scatterDesc, FilterMode.Bilinear); cmd.GetTemporaryRT(rt[k].rtUp, scatterDesc, FilterMode.Bilinear); width /= 2; height /= 2; } RenderTargetIdentifier sourceMip = rt[0].rtDown; FullScreenBlit(cmd, source, sourceMip, mat, (int)Pass.ScatteringPrefilter); // Blitting down... cmd.SetGlobalFloat(ShaderParams.BlurScale, 1f); for (int k = 1; k <= mipCount; k++) { FullScreenBlit(cmd, sourceMip, rt[k].rtDown, mat, (int)Pass.Resample); sourceMip = rt[k].rtDown; } // Blitting up... cmd.SetGlobalFloat(ShaderParams.BlurScale, 1.5f); for (int k = mipCount; k > 0; k--) { cmd.SetGlobalTexture(ShaderParams.BlurredTex, rt[k - 1].rtDown); FullScreenBlit(cmd, sourceMip, rt[k - 1].rtUp, mat, (int)Pass.ResampleAndCombine); sourceMip = rt[k - 1].rtUp; } FullScreenBlit(cmd, sourceMip, source, mat, (int)Pass.ScatteringBlend); } static void FullScreenBlit (CommandBuffer cmd, RenderTargetIdentifier source, RenderTargetIdentifier destination, Material material, int passIndex) { destination = new RenderTargetIdentifier(destination, 0, CubemapFace.Unknown, -1); cmd.SetRenderTarget(destination); cmd.SetGlobalTexture(ShaderParams.MainTex, source); cmd.DrawMesh(Tools.fullscreenMesh, Matrix4x4.identity, material, 0, passIndex); } static public void Cleanup () { Shader.SetGlobalInt(ShaderParams.ForcedInvisible, 0); } } [SerializeField, HideInInspector] Shader blurShader; VolumetricFogRenderPass fogRenderPass, fogRenderBackTranspPass; BlurRenderPass blurRenderPass, blurRenderBackTranspPass; public static bool installed; public static bool isRenderingBeforeTransparents; public static bool isUsingDepthPeeling; public RenderPassEvent renderPassEvent = RenderPassEvent.BeforeRenderingTransparents; [Tooltip("Specify which fog volumes will be rendered by this feature.")] public LayerMask fogLayerMask = -1; [Tooltip("Specify which cameras can execute this render feature. If you have several cameras in your scene, make sure only the correct cameras use this feature in order to optimize performance.")] public LayerMask cameraLayerMask = -1; [Tooltip("Ignores reflection probes from executing this render feature")] public bool ignoreReflectionProbes = true; void OnDisable () { installed = false; isRenderingBeforeTransparents = false; isUsingDepthPeeling = false; BlurRenderPass.Cleanup(); } private void OnDestroy () { if (fogRenderPass != null) { fogRenderPass.CleanUp(); } if (fogRenderBackTranspPass != null) { fogRenderBackTranspPass.CleanUp(); } } public override void Create () { name = "Volumetric Fog 2"; fogRenderPass = new VolumetricFogRenderPass(); blurRenderPass = new BlurRenderPass(); fogRenderBackTranspPass = new VolumetricFogRenderPass(); blurRenderBackTranspPass = new BlurRenderPass(); blurShader = Shader.Find("Hidden/VolumetricFog2/Blur"); if (blurShader == null) { Debug.LogWarning("Could not load Volumetric Fog composition shader."); } } // This method is called when setting up the renderer once per-camera. public override void AddRenderPasses (ScriptableRenderer renderer, ref RenderingData renderingData) { installed = true; if (VolumetricFog.volumetricFogs.Count == 0) return; VolumetricFogManager manager = VolumetricFogManager.GetManagerIfExists(); if (manager == null) { Shader.SetGlobalInt(ShaderParams.ForcedInvisible, 0); return; } isUsingDepthPeeling = manager.includeTransparent != 0 && manager.depthPeeling; if (manager.downscaling <= 1f && manager.blurPasses < 1 && manager.scattering <= 0 && !isUsingDepthPeeling) { Shader.SetGlobalInt(ShaderParams.ForcedInvisible, 0); Shader.DisableKeyword(ShaderParams.SKW_DEPTH_PREPASS); Shader.DisableKeyword(ShaderParams.SKW_DEPTH_PEELING); return; } Camera cam = renderingData.cameraData.camera; CameraType camType = cam.cameraType; if (camType == CameraType.Preview) return; if (ignoreReflectionProbes && camType == CameraType.Reflection) return; if ((fogLayerMask & cam.cullingMask) == 0) return; if ((cameraLayerMask & (1 << cam.gameObject.layer)) == 0) return; if (cam.targetTexture != null && cam.targetTexture.format == RenderTextureFormat.Depth) return; // ignore occlusion cams! RenderPassEvent injectionPoint = renderPassEvent; if (isUsingDepthPeeling) { fogRenderBackTranspPass.Setup(this, RenderPassEvent.AfterRenderingSkybox); renderer.EnqueuePass(fogRenderBackTranspPass); blurRenderBackTranspPass.Setup(blurShader, renderer, RenderPassEvent.AfterRenderingSkybox); renderer.EnqueuePass(blurRenderBackTranspPass); injectionPoint = (RenderPassEvent)Mathf.Max((int)injectionPoint, (int)RenderPassEvent.AfterRenderingTransparents); } isRenderingBeforeTransparents = injectionPoint < RenderPassEvent.AfterRenderingTransparents; fogRenderPass.Setup(this, injectionPoint); renderer.EnqueuePass(fogRenderPass); blurRenderPass.Setup(blurShader, renderer, injectionPoint); renderer.EnqueuePass(blurRenderPass); } } }