using System; using UnityEngine.Experimental.Rendering; using UnityEngine.Rendering.RenderGraphModule; namespace UnityEngine.Rendering.HighDefinition { public partial class HDRenderPipeline { // String values (ray tracing gen shaders) const string m_RayGenAreaShadowSingleName = "RayGenAreaShadowSingle"; const string m_RayGenDirectionalShadowSingleName = "RayGenDirectionalShadowSingle"; const string m_RayGenDirectionalColorShadowSingleName = "RayGenDirectionalColorShadowSingle"; const string m_RayGenShadowSegmentSingleName = "RayGenShadowSegmentSingle"; const string m_RayGenSemiTransparentShadowSegmentSingleName = "RayGenSemiTransparentShadowSegmentSingle"; // Shaders RayTracingShader m_ScreenSpaceShadowsRT; ComputeShader m_ScreenSpaceShadowsCS; ComputeShader m_ScreenSpaceShadowsFilterCS; // Kernels // Shared shadow kernels int m_ClearShadowTexture; int m_OutputShadowTextureKernel; int m_OutputColorShadowTextureKernel; int m_OutputSpecularShadowTextureKernel; // Directional shadow kernels int m_RaytracingDirectionalShadowSample; // Punctual shadow kernels int m_RaytracingPointShadowSample; int m_RaytracingSpotShadowSample; int m_RaytracingProjectorPyramidShadowSample; int m_RaytracingProjectorBoxShadowSample; // Area shadow kernels int m_AreaRaytracingShadowPrepassKernel; int m_AreaRaytracingShadowNewSampleKernel; int m_AreaShadowApplyTAAKernel; int m_AreaUpdateAnalyticHistoryKernel; int m_AreaUpdateShadowHistoryKernel; int m_AreaEstimateNoiseKernel; int m_AreaFirstDenoiseKernel; int m_AreaSecondDenoiseKernel; int m_AreaShadowNoDenoiseKernel; int m_WriteShadowTextureDebugKernel; // Temporary variables that allow us to read and write the right channels from the history buffer Vector4 m_ShadowChannelMask0 = new Vector4(1.0f, 1.0f, 1.0f, 1.0f); Vector4 m_ShadowChannelMask1 = new Vector4(1.0f, 1.0f, 1.0f, 1.0f); Vector4 m_ShadowChannelMask2 = new Vector4(1.0f, 1.0f, 1.0f, 1.0f); // Screen space shadow material static Material s_ScreenSpaceShadowsMat; // This buffer holds the unfiltered, accumulated, shadow values, it is accessed with the same index as the one used at runtime (aka screen space shadow slot) static RTHandle ShadowHistoryBufferAllocatorFunction(string viewName, int frameIndex, RTHandleSystem rtHandleSystem) { HDRenderPipeline hdrp = RenderPipelineManager.currentPipeline as HDRenderPipeline; HDRenderPipelineAsset hdPipelineAsset = hdrp.m_Asset; int numShadowSlices = Math.Max((int)Math.Ceiling(hdPipelineAsset.currentPlatformRenderPipelineSettings.hdShadowInitParams.maxScreenSpaceShadowSlots / 4.0f), 1); return rtHandleSystem.Alloc(Vector2.one, slices: numShadowSlices * TextureXR.slices, dimension: TextureDimension.Tex2DArray, filterMode: FilterMode.Point, colorFormat: GraphicsFormat.R16G16B16A16_SFloat, enableRandomWrite: true, useDynamicScale: true, useMipMap: false, name: string.Format("{0}_ScreenSpaceShadowHistoryBuffer{1}", viewName, frameIndex)); } // This value holds additional values that are required for the filtering process. // For directional, punctual and spot light it holds the sample accumulation count and for the area light it holds the analytic value. // It is accessed with the same index used at runtime (aka screen space shadow slot) static RTHandle ShadowHistoryValidityBufferAllocatorFunction(string viewName, int frameIndex, RTHandleSystem rtHandleSystem) { HDRenderPipeline hdrp = RenderPipelineManager.currentPipeline as HDRenderPipeline; HDRenderPipelineAsset hdPipelineAsset = hdrp.m_Asset; int numShadowSlices = Math.Max((int)Math.Ceiling(hdPipelineAsset.currentPlatformRenderPipelineSettings.hdShadowInitParams.maxScreenSpaceShadowSlots / 4.0f), 1); return rtHandleSystem.Alloc(Vector2.one, slices: numShadowSlices * TextureXR.slices, dimension: TextureDimension.Tex2DArray, filterMode: FilterMode.Point, colorFormat: GraphicsFormat.R16G16B16A16_SFloat, enableRandomWrite: true, useDynamicScale: true, useMipMap: false, name: string.Format("{0}_ShadowHistoryValidityBuffer{1}", viewName, frameIndex)); } static RTHandle ShadowHistoryDistanceBufferAllocatorFunction(string viewName, int frameIndex, RTHandleSystem rtHandleSystem) { HDRenderPipeline hdrp = RenderPipelineManager.currentPipeline as HDRenderPipeline; HDRenderPipelineAsset hdPipelineAsset = hdrp.m_Asset; int numShadowSlices = Math.Max((int)Math.Ceiling(hdPipelineAsset.currentPlatformRenderPipelineSettings.hdShadowInitParams.maxScreenSpaceShadowSlots / 4.0f), 1); return rtHandleSystem.Alloc(Vector2.one, slices: numShadowSlices * TextureXR.slices, dimension: TextureDimension.Tex2DArray, filterMode: FilterMode.Point, colorFormat: GraphicsFormat.R16G16B16A16_SFloat, enableRandomWrite: true, useDynamicScale: true, useMipMap: false, name: string.Format("{0}_ShadowHistoryDistanceBuffer{1}", viewName, frameIndex)); } RTHandle RequestShadowHistoryBuffer(HDCamera hdCamera) { return hdCamera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.RaytracedShadowHistory) ?? hdCamera.AllocHistoryFrameRT((int)HDCameraFrameHistoryType.RaytracedShadowHistory, ShadowHistoryBufferAllocatorFunction, 1); } RTHandle RequestShadowHistoryValidityBuffer(HDCamera hdCamera) { return hdCamera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.RaytracedShadowHistoryValidity) ?? hdCamera.AllocHistoryFrameRT((int)HDCameraFrameHistoryType.RaytracedShadowHistoryValidity, ShadowHistoryValidityBufferAllocatorFunction, 1); } RTHandle RequestShadowHistoryDistanceBuffer(HDCamera hdCamera) { return hdCamera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.RaytracedShadowDistanceValidity) ?? hdCamera.AllocHistoryFrameRT((int)HDCameraFrameHistoryType.RaytracedShadowDistanceValidity, ShadowHistoryDistanceBufferAllocatorFunction, 1); } // The three types of shadows that we currently support enum ScreenSpaceShadowType { GrayScale, Area, Color } // This functions returns a mask that tells us for a given slot and based on the light type, which channels should hold the shadow information. static void GetShadowChannelMask(int shadowSlot, ScreenSpaceShadowType shadowType, ref Vector4 outputMask) { int outputChannel = shadowSlot % 4; if (shadowType == ScreenSpaceShadowType.GrayScale) { switch (outputChannel) { case 0: { outputMask.Set(1.0f, 0.0f, 0.0f, 0.0f); break; } case 1: { outputMask.Set(0.0f, 1.0f, 0.0f, 0.0f); break; } case 2: { outputMask.Set(0.0f, 0.0f, 1.0f, 0.0f); break; } case 3: { outputMask.Set(0.0f, 0.0f, 0.0f, 1.0f); break; } } } else if (shadowType == ScreenSpaceShadowType.Area) { switch (outputChannel) { case 0: { outputMask.Set(1.0f, 1.0f, 0.0f, 0.0f); break; } case 1: { outputMask.Set(0.0f, 1.0f, 1.0f, 0.0f); break; } case 2: { outputMask.Set(0.0f, 0.0f, 1.0f, 1.0f); break; } default: Debug.Assert(false); break; } } else if (shadowType == ScreenSpaceShadowType.Color) { switch (outputChannel) { case 0: { outputMask.Set(1.0f, 1.0f, 1.0f, 0.0f); break; } default: Debug.Assert(false); break; } } } void InitializeScreenSpaceShadows() { if (!m_Asset.currentPlatformRenderPipelineSettings.hdShadowInitParams.supportScreenSpaceShadows) return; // Fetch the shaders if (m_RayTracingSupported) { m_ScreenSpaceShadowsCS = rayTracingResources.shadowRayTracingCS; m_ScreenSpaceShadowsFilterCS = rayTracingResources.shadowFilterCS; m_ScreenSpaceShadowsRT = rayTracingResources.shadowRayTracingRT; // Directional shadow kernels m_ClearShadowTexture = m_ScreenSpaceShadowsCS.FindKernel("ClearShadowTexture"); m_OutputShadowTextureKernel = m_ScreenSpaceShadowsCS.FindKernel("OutputShadowTexture"); m_OutputColorShadowTextureKernel = m_ScreenSpaceShadowsCS.FindKernel("OutputColorShadowTexture"); m_OutputSpecularShadowTextureKernel = m_ScreenSpaceShadowsCS.FindKernel("OutputSpecularShadowTexture"); m_RaytracingDirectionalShadowSample = m_ScreenSpaceShadowsCS.FindKernel("RaytracingDirectionalShadowSample"); m_RaytracingPointShadowSample = m_ScreenSpaceShadowsCS.FindKernel("RaytracingPointShadowSample"); m_RaytracingSpotShadowSample = m_ScreenSpaceShadowsCS.FindKernel("RaytracingSpotShadowSample"); m_RaytracingProjectorPyramidShadowSample = m_ScreenSpaceShadowsCS.FindKernel("RaytracingProjectorPyramidShadowSample"); m_RaytracingProjectorBoxShadowSample = m_ScreenSpaceShadowsCS.FindKernel("RaytracingProjectorBoxShadowSample"); // Area shadow kernels m_AreaRaytracingShadowPrepassKernel = m_ScreenSpaceShadowsCS.FindKernel("RaytracingAreaShadowPrepass"); m_AreaRaytracingShadowNewSampleKernel = m_ScreenSpaceShadowsCS.FindKernel("RaytracingAreaShadowNewSample"); m_AreaShadowApplyTAAKernel = m_ScreenSpaceShadowsFilterCS.FindKernel("AreaShadowApplyTAA"); m_AreaUpdateAnalyticHistoryKernel = m_ScreenSpaceShadowsFilterCS.FindKernel("AreaAnalyticHistoryCopy"); m_AreaUpdateShadowHistoryKernel = m_ScreenSpaceShadowsFilterCS.FindKernel("AreaShadowHistoryCopy"); m_AreaEstimateNoiseKernel = m_ScreenSpaceShadowsFilterCS.FindKernel("AreaShadowEstimateNoise"); m_AreaFirstDenoiseKernel = m_ScreenSpaceShadowsFilterCS.FindKernel("AreaShadowDenoiseFirstPass"); m_AreaSecondDenoiseKernel = m_ScreenSpaceShadowsFilterCS.FindKernel("AreaShadowDenoiseSecondPass"); m_AreaShadowNoDenoiseKernel = m_ScreenSpaceShadowsFilterCS.FindKernel("AreaShadowNoDenoise"); // Debug kernel m_WriteShadowTextureDebugKernel = m_ScreenSpaceShadowsFilterCS.FindKernel("WriteShadowTextureDebug"); } // Directional shadow material s_ScreenSpaceShadowsMat = CoreUtils.CreateEngineMaterial(screenSpaceShadowsShader); switch (m_Asset.currentPlatformRenderPipelineSettings.hdShadowInitParams.punctualShadowFilteringQuality) { case HDShadowFilteringQuality.Low: s_ScreenSpaceShadowsMat.EnableKeyword("PUNCTUAL_SHADOW_LOW"); break; case HDShadowFilteringQuality.Medium: s_ScreenSpaceShadowsMat.EnableKeyword("PUNCTUAL_SHADOW_MEDIUM"); break; case HDShadowFilteringQuality.High: s_ScreenSpaceShadowsMat.EnableKeyword("PUNCTUAL_SHADOW_HIGH"); break; default: s_ScreenSpaceShadowsMat.EnableKeyword("PUNCTUAL_SHADOW_MEDIUM"); break; } switch (m_Asset.currentPlatformRenderPipelineSettings.hdShadowInitParams.directionalShadowFilteringQuality) { case HDShadowFilteringQuality.Low: s_ScreenSpaceShadowsMat.EnableKeyword("DIRECTIONAL_SHADOW_LOW"); break; case HDShadowFilteringQuality.Medium: s_ScreenSpaceShadowsMat.EnableKeyword("DIRECTIONAL_SHADOW_MEDIUM"); break; case HDShadowFilteringQuality.High: s_ScreenSpaceShadowsMat.EnableKeyword("DIRECTIONAL_SHADOW_HIGH"); break; default: s_ScreenSpaceShadowsMat.EnableKeyword("DIRECTIONAL_SHADOW_MEDIUM"); break; } var areaShadowFilteringQuality = (ShaderConfig.s_AreaLights == 0) ? HDAreaShadowFilteringQuality.Medium : m_Asset.currentPlatformRenderPipelineSettings.hdShadowInitParams.areaShadowFilteringQuality; switch (areaShadowFilteringQuality) { case HDAreaShadowFilteringQuality.Medium: s_ScreenSpaceShadowsMat.EnableKeyword("AREA_SHADOW_MEDIUM"); break; case HDAreaShadowFilteringQuality.High: s_ScreenSpaceShadowsMat.EnableKeyword("AREA_SHADOW_HIGH"); break; default: s_ScreenSpaceShadowsMat.EnableKeyword("AREA_SHADOW_MEDIUM"); break; } } void ReleaseScreenSpaceShadows() { CoreUtils.Destroy(s_ScreenSpaceShadowsMat); } internal TextureHandle CreateScreenSpaceShadowTextureArray(RenderGraph renderGraph) { int numShadowTextures = Math.Max((int)Math.Ceiling(m_Asset.currentPlatformRenderPipelineSettings.hdShadowInitParams.maxScreenSpaceShadowSlots / 4.0f), 1); GraphicsFormat graphicsFormat = (GraphicsFormat)m_Asset.currentPlatformRenderPipelineSettings.hdShadowInitParams.screenSpaceShadowBufferFormat; return renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true) { format = graphicsFormat, slices = numShadowTextures * TextureXR.slices, dimension = TextureDimension.Tex2DArray, filterMode = FilterMode.Point, enableRandomWrite = true, useMipMap = false, name = "ScreenSpaceShadowArrayBuffer" }); } class ScreenSpaceShadowDebugPassData { // Camera parameters public int texWidth; public int texHeight; public int viewCount; // Evaluation parameters public int targetShadow; // Kernel public int debugKernel; // Other parameters public ComputeShader shadowFilter; public TextureHandle screenSpaceShadowArray; public TextureHandle outputBuffer; } TextureHandle EvaluateShadowDebugView(RenderGraph renderGraph, HDCamera hdCamera, TextureHandle screenSpaceShadowArray) { // If this is the right debug mode and the index we are asking for is in the range if (!rayTracingSupported || (m_ScreenSpaceShadowChannelSlot <= m_CurrentDebugDisplaySettings.data.screenSpaceShadowIndex)) return m_RenderGraph.defaultResources.blackTextureXR; using (var builder = renderGraph.AddUnsafePass("Screen Space Shadows Debug", out var passData, ProfilingSampler.Get(HDProfileId.ScreenSpaceShadowsDebug))) { passData.texWidth = hdCamera.actualWidth; passData.texHeight = hdCamera.actualHeight; passData.viewCount = hdCamera.viewCount; // Evaluation params passData.targetShadow = (int)m_CurrentDebugDisplaySettings.data.screenSpaceShadowIndex; // Kernel to be used passData.debugKernel = m_WriteShadowTextureDebugKernel; // TODO: move the debug kernel outside of the ray tracing resources passData.shadowFilter = rayTracingResources.shadowFilterCS; passData.screenSpaceShadowArray = screenSpaceShadowArray; builder.UseTexture(passData.screenSpaceShadowArray, AccessFlags.Read); passData.outputBuffer = renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true) { format = GraphicsFormat.R16G16B16A16_SFloat, enableRandomWrite = true, name = "EvaluateShadowDebug" }); builder.UseTexture(passData.outputBuffer, AccessFlags.Write); builder.SetRenderFunc( (ScreenSpaceShadowDebugPassData data, UnsafeGraphContext ctx) => { var natCmd = CommandBufferHelpers.GetNativeCommandBuffer(ctx.cmd); // Evaluate the dispatch parameters int shadowTileSize = 8; int numTilesX = (data.texWidth + (shadowTileSize - 1)) / shadowTileSize; int numTilesY = (data.texHeight + (shadowTileSize - 1)) / shadowTileSize; // If the screen space shadows we are asked to deliver is available output it to the intermediate texture natCmd.SetComputeIntParam(data.shadowFilter, HDShaderIDs._DenoisingHistorySlot, data.targetShadow); natCmd.SetComputeTextureParam(data.shadowFilter, data.debugKernel, HDShaderIDs._ScreenSpaceShadowsTextureRW, data.screenSpaceShadowArray); natCmd.SetComputeTextureParam(data.shadowFilter, data.debugKernel, HDShaderIDs._DenoiseOutputTextureRW, data.outputBuffer); natCmd.DispatchCompute(data.shadowFilter, data.debugKernel, numTilesX, numTilesY, data.viewCount); }); return passData.outputBuffer; } } class WriteScreenSpaceShadowPassData { // Camera parameters public int texWidth; public int texHeight; public int viewCount; // Evaluation parameters public Vector4 shadowChannelMask; public Vector4 shadowChannelMask0; public Vector4 shadowChannelMask1; public int shadowSlot; // Kernel public int shadowKernel; // Other parameters public ComputeShader screenSpaceShadowCS; public TextureHandle inputShadowBuffer; public TextureHandle outputShadowArrayBuffer; } void WriteScreenSpaceShadow(RenderGraph renderGraph, HDCamera hdCamera, TextureHandle shadowTexture, TextureHandle screenSpaceShadowArray, int shadowIndex, ScreenSpaceShadowType shadowType) { // Write the result texture to the screen space shadow buffer using (var builder = renderGraph.AddUnsafePass("Write Screen Space Shadows", out var passData, ProfilingSampler.Get(HDProfileId.RaytracingWriteShadow))) { passData.texWidth = hdCamera.actualWidth; passData.texHeight = hdCamera.actualHeight; passData.viewCount = hdCamera.viewCount; // Evaluation parameters GetShadowChannelMask(shadowIndex, shadowType, ref passData.shadowChannelMask); // If the light is an area, we also need to grab the individual channels if (shadowType == ScreenSpaceShadowType.Area) { GetShadowChannelMask(shadowIndex, ScreenSpaceShadowType.GrayScale, ref passData.shadowChannelMask0); GetShadowChannelMask(shadowIndex + 1, ScreenSpaceShadowType.GrayScale, ref passData.shadowChannelMask1); } passData.shadowSlot = shadowIndex; // Kernel switch (shadowType) { case ScreenSpaceShadowType.GrayScale: { passData.shadowKernel = m_OutputShadowTextureKernel; } break; case ScreenSpaceShadowType.Area: { passData.shadowKernel = m_OutputSpecularShadowTextureKernel; } break; case ScreenSpaceShadowType.Color: { passData.shadowKernel = m_OutputColorShadowTextureKernel; } break; } // Other parameters passData.screenSpaceShadowCS = m_ScreenSpaceShadowsCS; passData.inputShadowBuffer = shadowTexture; builder.UseTexture(passData.inputShadowBuffer, AccessFlags.Read); passData.outputShadowArrayBuffer = screenSpaceShadowArray; builder.UseTexture(passData.outputShadowArrayBuffer, AccessFlags.ReadWrite); builder.SetRenderFunc( (WriteScreenSpaceShadowPassData data, UnsafeGraphContext ctx) => { var natCmd = CommandBufferHelpers.GetNativeCommandBuffer(ctx.cmd); // Evaluate the dispatch parameters int shadowTileSize = 8; int numTilesX = (data.texWidth + (shadowTileSize - 1)) / shadowTileSize; int numTilesY = (data.texHeight + (shadowTileSize - 1)) / shadowTileSize; // Bind the input data natCmd.SetComputeIntParam(data.screenSpaceShadowCS, HDShaderIDs._RaytracingShadowSlot, data.shadowSlot / 4); natCmd.SetComputeVectorParam(data.screenSpaceShadowCS, HDShaderIDs._RaytracingChannelMask, data.shadowChannelMask); natCmd.SetComputeVectorParam(data.screenSpaceShadowCS, HDShaderIDs._RaytracingChannelMask0, data.shadowChannelMask0); natCmd.SetComputeVectorParam(data.screenSpaceShadowCS, HDShaderIDs._RaytracingChannelMask1, data.shadowChannelMask1); natCmd.SetComputeTextureParam(data.screenSpaceShadowCS, data.shadowKernel, HDShaderIDs._RaytracedShadowIntegration, data.inputShadowBuffer); // Bind the output texture natCmd.SetComputeTextureParam(data.screenSpaceShadowCS, data.shadowKernel, HDShaderIDs._ScreenSpaceShadowsTextureRW, data.outputShadowArrayBuffer); //Do our copy natCmd.DispatchCompute(data.screenSpaceShadowCS, data.shadowKernel, numTilesX, numTilesY, data.viewCount); }); } } bool RenderLightScreenSpaceShadows(RenderGraph renderGraph, HDCamera hdCamera, PrepassOutput prepassOutput, TextureHandle depthBuffer, TextureHandle normalBuffer, TextureHandle motionVectorsBuffer, TextureHandle historyValidityBuffer, TextureHandle rayCountTexture, TextureHandle screenSpaceShadowArray) { // Loop through all the potential screen space light shadows for (int lightIdx = 0; lightIdx < m_ScreenSpaceShadowIndex; ++lightIdx) { // This matches the directional light if (!m_CurrentScreenSpaceShadowData[lightIdx].valid) continue; // Fetch the light data and additional light data LightData currentLight = m_GpuLightsBuilder.lights[m_CurrentScreenSpaceShadowData[lightIdx].lightDataIndex]; HDAdditionalLightData currentAdditionalLightData = m_CurrentScreenSpaceShadowData[lightIdx].additionalLightData; // Trigger the right algorithm based on the light type switch (currentLight.lightType) { case GPULightType.Rectangle: { RenderAreaScreenSpaceShadow(renderGraph, hdCamera, currentLight, currentAdditionalLightData, m_CurrentScreenSpaceShadowData[lightIdx].lightDataIndex, prepassOutput, depthBuffer, normalBuffer, motionVectorsBuffer, rayCountTexture, screenSpaceShadowArray); } break; case GPULightType.Point: case GPULightType.Spot: case GPULightType.ProjectorPyramid: case GPULightType.ProjectorBox: { RenderPunctualScreenSpaceShadow(renderGraph, hdCamera, currentLight, currentAdditionalLightData, m_CurrentScreenSpaceShadowData[lightIdx].lightDataIndex, prepassOutput, depthBuffer, normalBuffer, motionVectorsBuffer, historyValidityBuffer, rayCountTexture, screenSpaceShadowArray); } break; } } return true; } bool RequestedScreenSpaceShadows() { // We have screen space shadows that needs to be evaluated if we have one of these: // - A screen space directional shadow // - A ray traced directional shadow bool screenSpaceShadowDirectionalRequired = m_CurrentSunLightAdditionalLightData != null && (m_CurrentSunShadowMapFlags & HDProcessedVisibleLightsBuilder.ShadowMapFlags.WillRenderScreenSpaceShadow) != 0; // - A ray traced spot or point shadow // - A ray traced area light shadow bool pointOrAreaLightShadowRequired = false; for (int lightIdx = 0; lightIdx < m_ScreenSpaceShadowIndex; ++lightIdx) { // This matches the directional light if (!m_CurrentScreenSpaceShadowData[lightIdx].valid) continue; pointOrAreaLightShadowRequired = true; break; } return screenSpaceShadowDirectionalRequired || pointOrAreaLightShadowRequired; } TextureHandle RenderScreenSpaceShadows(RenderGraph renderGraph, HDCamera hdCamera, PrepassOutput prepassOutput, TextureHandle depthBuffer, TextureHandle normalBuffer, TextureHandle motionVectorsBuffer, TextureHandle historyValidityBuffer, TextureHandle rayCountTexture) { // If screen space shadows are not supported for this camera, we are done bool validConditions = hdCamera.frameSettings.IsEnabled(FrameSettingsField.ScreenSpaceShadows) && RequestedScreenSpaceShadows(); if (!validConditions) { // We push the debug texture anyway if we are not evaluating any screen space shadows. PushFullScreenDebugTexture(m_RenderGraph, m_RenderGraph.defaultResources.whiteTextureXR, FullScreenDebugMode.ScreenSpaceShadows); return m_RenderGraph.defaultResources.blackTextureArrayXR; } using (new RenderGraphProfilingScope(renderGraph, ProfilingSampler.Get(HDProfileId.ScreenSpaceShadows))) { // Request the output texture TextureHandle screenSpaceShadowTexture = CreateScreenSpaceShadowTextureArray(renderGraph); // First of all we handle the directional light RenderDirectionalLightScreenSpaceShadow(renderGraph, hdCamera, depthBuffer, normalBuffer, motionVectorsBuffer, historyValidityBuffer, rayCountTexture, screenSpaceShadowTexture); if (hdCamera.frameSettings.IsEnabled(FrameSettingsField.RayTracing) && GetRayTracingState()) { // We handle the other light sources RenderLightScreenSpaceShadows(renderGraph, hdCamera, prepassOutput, depthBuffer, normalBuffer, motionVectorsBuffer, historyValidityBuffer, rayCountTexture, screenSpaceShadowTexture); } // We render the debug view, if the texture is not used, it is not evaluated anyway TextureHandle screenSpaceShadowDebug = EvaluateShadowDebugView(renderGraph, hdCamera, screenSpaceShadowTexture); PushFullScreenDebugTexture(m_RenderGraph, screenSpaceShadowDebug, FullScreenDebugMode.ScreenSpaceShadows); return screenSpaceShadowTexture; } } } }