using System; using System.Collections.Generic; using UnityEngine.Experimental.Rendering; using UnityEngine.Rendering.RenderGraphModule; using UnityEngine.Rendering.Universal.U2D.Profiler; using CommonResourceData = UnityEngine.Rendering.Universal.UniversalResourceData; namespace UnityEngine.Rendering.Universal { internal class DrawShadow2DPass : ScriptableRenderPass { private static void ExecuteShadowPass(UnsafeCommandBuffer cmd, PassData passData, Light2D light, int batchIndex) { cmd.SetRenderTarget(passData.shadowTextures[batchIndex], passData.shadowDepth); // Reusing the depth/stencil so we have to clear it cmd.ClearRenderTarget(RTClearFlags.All, Color.clear, 1, 0); var projectedShadowMaterial = passData.rendererData.GetProjectedShadowMaterial(); var projectedUnshadowMaterial = passData.rendererData.GetProjectedUnshadowMaterial(); ShadowRendering.PrerenderShadows(cmd, passData.rendererData, ref passData.layerBatch, light, 0, light.shadowIntensity); } internal class PassData { internal LayerBatch layerBatch; internal Renderer2DData rendererData; internal TextureHandle[] shadowTextures; internal TextureHandle shadowDepth; internal bool isVolumetric; } public void Render(RenderGraph graph, ContextContainer frameData, int batchIndex, bool isVolumetric = false) { Universal2DResourceData universal2DResourceData = frameData.Get(); CommonResourceData commonResourceData = frameData.Get(); Renderer2DData rendererData = frameData.Get().renderingData; var layerBatch = frameData.Get().layerBatches[batchIndex]; if (!layerBatch.lightStats.useShadows || isVolumetric && !layerBatch.lightStats.useVolumetricShadowLights) return; var passName = !isVolumetric ? ProfilerMarkers.s_ShadowPass : ProfilerMarkers.s_ShadowVolumetricPass; var profilingSampler = !isVolumetric ? ProfilerMarkers.s_ProfilingSamplerShadowPass : ProfilerMarkers.s_ProfilingSamplerShadowVolumetricPass; LayerDebug.FormatPassName(layerBatch, ref passName); using (var builder = graph.AddUnsafePass(passName, out var passData, LayerDebug.GetProfilingSampler(passName, profilingSampler))) { passData.isVolumetric = isVolumetric; passData.layerBatch = layerBatch; passData.rendererData = rendererData; passData.shadowTextures = universal2DResourceData.shadowTextures[batchIndex]; passData.shadowDepth = universal2DResourceData.shadowDepth; for (var i = 0; i < passData.shadowTextures.Length; i++) builder.UseTexture(passData.shadowTextures[i], AccessFlags.Write); builder.UseTexture(passData.shadowDepth, AccessFlags.Write); builder.AllowGlobalStateModification(true); builder.SetRenderFunc(static (PassData data, UnsafeGraphContext context) => { for (int i = 0; i < data.layerBatch.shadowIndices.Count; ++i) { var cmd = context.cmd; var index = data.layerBatch.shadowIndices[i]; var light = data.layerBatch.lights[index]; if (data.isVolumetric && !RendererLighting.CanCastVolumetricShadows(light, data.layerBatch.endLayerValue)) continue; // Shadow Pass ExecuteShadowPass(cmd, data, light, i); } }); } } } }