//pipelinedefine #define H_URP using HTraceWSGI.Scripts.Data.Private; using HTraceWSGI.Scripts.Extensions; using HTraceWSGI.Scripts.Globals; using HTraceWSGI.Scripts.Passes.Shared; using UnityEngine; using UnityEngine.Experimental.Rendering; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; #if UNITY_2023_3_OR_NEWER using UnityEngine.Rendering.RenderGraphModule; #endif namespace HTraceWSGI.Scripts.Passes.URP { internal class FinalPassURP : ScriptableRenderPass { const string _OutputTarget = "_OutputTarget"; private static string s_motionVectorsKeyword = "MOTION_VECTORS"; // Shader properties private static readonly int AmbientOcclusionParam = Shader.PropertyToID("_AmbientOcclusionParam"); private static readonly int DebugSwitch = Shader.PropertyToID("_DebugSwitch"); private static readonly int BuffersSwitch = Shader.PropertyToID("_BuffersSwitch"); private static readonly int Debug_Output = Shader.PropertyToID("_Debug_Output"); internal static ComputeShader VoxelVisualization; internal static Material VoxelVisualizationMaterial; internal static ComputeShader HLightCluster; internal static Material LightClusterVisualizationMaterial; // Buffers & etc internal static ComputeShader HDebug = null; // Textures internal static RTHandle OutputTarget; private static void SetUrpAdditionalLightShadowKeywords(ComputeShader ComputeShader) { if (ComputeShader == null) return; bool UseAdditionalLightShadows = HSettings.LightingSettings.EvaluatePunctualLights && HRendererURP.UrpAsset != null && HRendererURP.UrpAsset.supportsAdditionalLightShadows; if (UseAdditionalLightShadows) ComputeShader.EnableKeyword(VoxelizationShared.ADDITIONAL_LIGHT_SHADOWS); else ComputeShader.DisableKeyword(VoxelizationShared.ADDITIONAL_LIGHT_SHADOWS); } #region --------------------------- Non Render Graph --------------------------- #if !UNITY_6000_4_OR_NEWER private ScriptableRenderer _renderer; protected internal void Initialize(ScriptableRenderer renderer) { _renderer = renderer; } #if UNITY_2023_3_OR_NEWER [System.Obsolete] #endif public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) { // SetupShared(renderingData.cameraData.camera, renderingData.cameraData.renderScale, renderingData.cameraData.cameraTargetDescriptor); // // if (HDebug == null) HDebug = HExtensions.LoadComputeShader("HDebug"); // // int width = (int)(camera.scaledPixelWidth * renderScale); // int height = (int)(camera.scaledPixelHeight * renderScale); // // if (desc.width != width || desc.height != height) // desc = new RenderTextureDescriptor(width, height); // desc.depthBufferBits = 0; // Color and depth cannot be combined in RTHandles // desc.stencilFormat = GraphicsFormat.None; // desc.depthStencilFormat = GraphicsFormat.None; // desc.msaaSamples = 1; // desc.bindMS = false; // desc.enableRandomWrite = true; // // ExtensionsURP.ReAllocateIfNeeded(_OutputTarget, ref OutputTarget, ref desc); } #if UNITY_2023_3_OR_NEWER [System.Obsolete] #endif public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) { } #if UNITY_2023_3_OR_NEWER [System.Obsolete] #endif public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { Camera camera = renderingData.cameraData.camera; var cmd = CommandBufferPool.Get(HNames.HTRACE_FINAL_PASS_NAME); int width = (int)(camera.scaledPixelWidth * renderingData.cameraData.renderScale); int height = (int)(camera.scaledPixelHeight * renderingData.cameraData.renderScale); if (DebugModule(cmd, width, height, OutputTarget)) return; Blitter.BlitCameraTexture(cmd, OutputTarget, _renderer.cameraColorTargetHandle); context.ExecuteCommandBuffer(cmd); cmd.Clear(); CommandBufferPool.Release(cmd); } #endif #endregion --------------------------- Non Render Graph --------------------------- #region --------------------------- Render Graph --------------------------- #if UNITY_2023_3_OR_NEWER private class VoxelVisPassData { public UniversalCameraData UniversalCameraData; public TextureHandle VoxelVisualizationRayDirections; public TextureHandle VoxelVisualizationDebugOutput; } private class LightClusterVisPassData { public UniversalCameraData UniversalCameraData; public TextureHandle LightClusterDebugColor; public TextureHandle LightClusterDebugDepth; } private class DebugPassData { public TextureHandle ColorTexture; public TextureHandle DebugColorTexture; public TextureHandle DebugDepthTexture; public TextureHandle DebugGBuffer0Texture; public TextureHandle DebugGBuffer1Texture; public TextureHandle DebugGBuffer2Texture; public TextureHandle DebugMotionVectorsTexture; public TextureHandle DebugMotionMaskTexture; public UniversalCameraData UniversalCameraData; public TextureHandle OutputTarget; } public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) { if (HSettings.GeneralSettings.DebugModeWS == DebugModeWS.VoxelizedLighting || HSettings.GeneralSettings.DebugModeWS == DebugModeWS.VoxelizedColor) { using (var builder = renderGraph.AddUnsafePass(HNames.HTRACE_VOXEL_VISUALIZATION_PASS_NAME, out var passData, new ProfilingSampler(HNames.HTRACE_VOXEL_VISUALIZATION_PASS_NAME))) { UniversalResourceData resourceData = frameData.Get(); UniversalCameraData universalCameraData = frameData.Get(); UniversalRenderingData universalRenderingData = frameData.Get(); UniversalLightData lightData = frameData.Get(); builder.AllowGlobalStateModification(true); builder.AllowPassCulling(false); passData.UniversalCameraData = universalCameraData; TextureHandle colorTextureHandle = resourceData.activeColorTexture; TextureDesc textureDesc = colorTextureHandle.GetDescriptor(renderGraph); textureDesc.colorFormat = GraphicsFormat.R16G16B16A16_SFloat; textureDesc.name = "_VoxelVisualizationRayDirections"; passData.VoxelVisualizationRayDirections = renderGraph.CreateTexture(textureDesc); builder.UseTexture(passData.VoxelVisualizationRayDirections, AccessFlags.ReadWrite); textureDesc.colorFormat = GraphicsFormat.R32G32B32A32_SFloat; textureDesc.name = "_VoxelVisualizationDebugOutput"; textureDesc.enableRandomWrite = true; passData.VoxelVisualizationDebugOutput = renderGraph.CreateTexture(textureDesc); builder.UseTexture(passData.VoxelVisualizationDebugOutput, AccessFlags.ReadWrite); if (VoxelVisualization == null) VoxelVisualization = HExtensions.LoadComputeShader("VoxelVisualization"); if (VoxelVisualizationMaterial == null) VoxelVisualizationMaterial = CoreUtils.CreateEngineMaterial(Shader.Find("Hidden/HTraceWSGI/VoxelVisualizationURP")); builder.SetRenderFunc((VoxelVisPassData data, UnsafeGraphContext context) => { var cmd = CommandBufferHelpers.GetNativeCommandBuffer(context.cmd); Camera camera = data.UniversalCameraData.camera; int width = (int)(data.UniversalCameraData.camera.scaledPixelWidth * data.UniversalCameraData.renderScale); int height = (int)(data.UniversalCameraData.camera.scaledPixelHeight * data.UniversalCameraData.renderScale); // Disable visualization keywords by default VoxelVisualization.EnableKeyword(VoxelizationShared.VISUALIZE_OFF); VoxelVisualization.DisableKeyword(VoxelizationShared.VISUALIZE_LIGHTING); VoxelVisualization.DisableKeyword(VoxelizationShared.VISUALIZE_COLOR); if (HSettings.LightingSettings.EvaluatePunctualLights) VoxelVisualization.EnableKeyword(VoxelizationShared.EVALUATE_PUNCTUAL_LIGHTS); else VoxelVisualization.DisableKeyword(VoxelizationShared.EVALUATE_PUNCTUAL_LIGHTS); SetUrpAdditionalLightShadowKeywords(VoxelVisualization); using (new HTraceProfilingScope(cmd, VoxelizationShared.s_VisualizeVoxelsProfilingSampler)) { if (HSettings.GeneralSettings.DebugModeWS == DebugModeWS.VoxelizedLighting) {VoxelizationShared.VoxelVisualization.EnableKeyword(VoxelizationShared.VISUALIZE_LIGHTING); VoxelizationShared.VoxelVisualization.DisableKeyword(VoxelizationShared.VISUALIZE_COLOR); VoxelizationShared.VoxelVisualization.DisableKeyword(VoxelizationShared.VISUALIZE_OFF);} if (HSettings.GeneralSettings.DebugModeWS == DebugModeWS.VoxelizedColor) {VoxelizationShared.VoxelVisualization.EnableKeyword(VoxelizationShared.VISUALIZE_COLOR); VoxelizationShared.VoxelVisualization.DisableKeyword(VoxelizationShared.VISUALIZE_LIGHTING); VoxelizationShared.VoxelVisualization.DisableKeyword(VoxelizationShared.VISUALIZE_OFF);} Vector2Int runningRes = new Vector2Int(width, height); Vector2 probeAtlasRes = runningRes * Vector2.one / HSettings.GeneralSettings.RayCountMode.ParseToProbeSize() * HConstants.OCTAHEDRAL_SIZE; //Dispatch resolutions int fullResX_8 = Mathf.CeilToInt((float)runningRes.x / 8); int fullResY_8 = Mathf.CeilToInt((float)runningRes.y / 8); // Calculate rays in camera frustum // var debugCameraFrustum = HMath.ComputeFrustumCorners(camera); // // Interpolate rays in vf shader // CoreUtils.SetRenderTarget(cmd, data.VoxelVisualizationRayDirections); // VoxelVisualizationMaterial.SetMatrix(HShaderParams._DebugCameraFrustum, debugCameraFrustum); // CoreUtils.DrawFullScreen(cmd, VoxelVisualizationMaterial, VoxelizationShared.VoxelVisualizationRayDirections.rt, shaderPassId: 0); // Trace into voxels for debug cmd.SetComputeTextureParam(VoxelVisualization, (int)VoxelizationShared.VoxelVisualizationKernel.VisualizeVoxels, HShaderParams._DebugRayDirection, data.VoxelVisualizationRayDirections); cmd.SetComputeTextureParam(VoxelVisualization, (int)VoxelizationShared.VoxelVisualizationKernel.VisualizeVoxels, HShaderParams._Visualization_Output, data.VoxelVisualizationDebugOutput); cmd.SetComputeIntParam(VoxelVisualization, HShaderParams._MultibounceMode, (int)HSettings.GeneralSettings.Multibounce); cmd.DispatchCompute(VoxelVisualization, (int)VoxelizationShared.VoxelVisualizationKernel.VisualizeVoxels, fullResX_8, fullResY_8, TextureXR.slices); cmd.SetGlobalTexture(HShaderParams.g_HTraceBufferGI, data.VoxelVisualizationDebugOutput); } }); } } if (HSettings.LightingSettings.EvaluatePunctualLights && (HSettings.GeneralSettings.DebugModeWS == DebugModeWS.LightClusterColor || HSettings.GeneralSettings.DebugModeWS == DebugModeWS.LightClusterHeatmap)) { using (var builder = renderGraph.AddUnsafePass(HNames.HTRACE_LIGHT_CLUSTER_VISUALIZATION_PASS_NAME, out var passData, new ProfilingSampler(HNames.HTRACE_LIGHT_CLUSTER_VISUALIZATION_PASS_NAME))) { UniversalResourceData resourceData = frameData.Get(); UniversalCameraData universalCameraData = frameData.Get(); builder.AllowGlobalStateModification(true); builder.AllowPassCulling(false); passData.UniversalCameraData = universalCameraData; TextureHandle colorTextureHandle = resourceData.activeColorTexture; TextureDesc textureDesc = colorTextureHandle.GetDescriptor(renderGraph); textureDesc.clearBuffer = false; passData.LightClusterDebugColor = ExtensionsURP.CreateTexture("_LightClusterDebugColor", renderGraph, ref textureDesc, GraphicsFormat.R16G16B16A16_SFloat); builder.UseTexture(passData.LightClusterDebugColor, AccessFlags.ReadWrite); // Match the dedicated sampleable debug target used by the shared/HDRP path // instead of inheriting the camera depth texture descriptor. passData.LightClusterDebugDepth = ExtensionsURP.CreateTexture("_LightClusterDebugDepth", renderGraph, ref textureDesc, GraphicsFormat.R8_UNorm, depthBufferBits: DepthBits.Depth32, enableRandomWrite: false); builder.UseTexture(passData.LightClusterDebugDepth, AccessFlags.ReadWrite); if (HLightCluster == null) HLightCluster = HExtensions.LoadComputeShader($"HLightClusterURP", HRenderPipeline.URP);; if (LightClusterVisualizationMaterial == null) LightClusterVisualizationMaterial = CoreUtils.CreateEngineMaterial(Shader.Find("Hidden/HTraceWSGI/LightClusterVisualizationURP")); builder.SetRenderFunc((LightClusterVisPassData data, UnsafeGraphContext context) => { var cmd = CommandBufferHelpers.GetNativeCommandBuffer(context.cmd); Camera camera = data.UniversalCameraData.camera; int width = (int)(data.UniversalCameraData.camera.scaledPixelWidth * data.UniversalCameraData.renderScale); int height = (int)(data.UniversalCameraData.camera.scaledPixelHeight * data.UniversalCameraData.renderScale); if (HSettings.LightingSettings.EvaluatePunctualLights == true) { // Draw 2D debug light cluster view on visible surfaces cmd.SetComputeTextureParam(HLightCluster, (int)LightClusterShared.LightClusterKernels.DebugLightCluster, LightClusterShared._LightClusterDebug_Output, passData.LightClusterDebugColor); cmd.DispatchCompute(HLightCluster, (int)LightClusterShared.LightClusterKernels.DebugLightCluster, Mathf.CeilToInt(width / 8.0f), Mathf.CeilToInt(height / 8.0f), TextureXR.slices); } if (HSettings.LightingSettings.EvaluatePunctualLights && HSettings.GeneralSettings.VolumetricDebug) { // Find all edge cells relative to each light's radius cmd.DispatchCompute(HLightCluster, (int)LightClusterShared.LightClusterKernels.FillLightClusterDebugBuffer, HSettings.LightingSettings.LightClusterCellDensity / 4, HSettings.LightingSettings.LightClusterCellDensity / 4, HSettings.LightingSettings.LightClusterCellDensity / 4); LightClusterVisualizationMaterial.SetTexture(LightClusterShared._LightClusterDebugColor, passData.LightClusterDebugColor); LightClusterVisualizationMaterial.SetTexture(LightClusterShared._LightClusterDebugDepth, passData.LightClusterDebugDepth); // Set our own Color and Depth render targets CoreUtils.SetRenderTarget(cmd, passData.LightClusterDebugColor, passData.LightClusterDebugDepth, ClearFlag.Depth, Color.clear, 0, CubemapFace.Unknown, -1); // Draw cubes first to Color and then to Depth cmd.DrawProcedural(Matrix4x4.identity, LightClusterVisualizationMaterial, 0, MeshTopology.Triangles, 36, HSettings.LightingSettings.LightClusterCellDensity * HSettings.LightingSettings.LightClusterCellDensity * HSettings.LightingSettings.LightClusterCellDensity); cmd.DrawProcedural(Matrix4x4.identity, LightClusterVisualizationMaterial, 1, MeshTopology.Triangles, 36, HSettings.LightingSettings.LightClusterCellDensity * HSettings.LightingSettings.LightClusterCellDensity * HSettings.LightingSettings.LightClusterCellDensity); // Set only Color CoreUtils.SetRenderTarget(cmd, passData.LightClusterDebugColor, ClearFlag.None); // Draw lines testing against the Depth filled by Cubes cmd.DrawProcedural(Matrix4x4.identity, LightClusterVisualizationMaterial, 2, MeshTopology.Lines, 48, HSettings.LightingSettings.LightClusterCellDensity * HSettings.LightingSettings.LightClusterCellDensity * HSettings.LightingSettings.LightClusterCellDensity); } cmd.SetGlobalTexture(HShaderParams.g_LightClusterDebug, passData.LightClusterDebugColor); }); } } using (var builder = renderGraph.AddUnsafePass(HNames.HTRACE_FINAL_PASS_NAME, out var passData, new ProfilingSampler(HNames.HTRACE_FINAL_PASS_NAME))) { UniversalResourceData resourceData = frameData.Get(); UniversalCameraData universalCameraData = frameData.Get(); UniversalRenderingData universalRenderingData = frameData.Get(); builder.AllowGlobalStateModification(true); builder.AllowPassCulling(false); TextureHandle colorTexture = universalRenderingData.renderingMode == RenderingMode.Deferred #if UNITY_6000_1_OR_NEWER || universalRenderingData.renderingMode == RenderingMode.DeferredPlus #endif ? resourceData.activeColorTexture : resourceData.cameraColor; passData.ColorTexture = colorTexture; passData.DebugColorTexture = GBufferPassURP.DebugColorTextureRG; passData.DebugDepthTexture = GBufferPassURP.DebugDepthTextureRG; passData.DebugGBuffer0Texture = GBufferPassURP.DebugGBuffer0TextureRG; passData.DebugGBuffer1Texture = GBufferPassURP.DebugGBuffer1TextureRG; passData.DebugGBuffer2Texture = GBufferPassURP.DebugGBuffer2TextureRG; passData.DebugMotionVectorsTexture = MotionVectorsPassURP.DebugMotionVectorsTextureRG; passData.DebugMotionMaskTexture = MotionVectorsPassURP.DebugMotionMaskTextureRG; passData.UniversalCameraData = universalCameraData; if (passData.DebugColorTexture.IsValid()) builder.UseTexture(passData.DebugColorTexture, AccessFlags.Read); if (passData.DebugDepthTexture.IsValid()) builder.UseTexture(passData.DebugDepthTexture, AccessFlags.Read); if (passData.DebugGBuffer0Texture.IsValid()) builder.UseTexture(passData.DebugGBuffer0Texture, AccessFlags.Read); if (passData.DebugGBuffer1Texture.IsValid()) builder.UseTexture(passData.DebugGBuffer1Texture, AccessFlags.Read); if (passData.DebugGBuffer2Texture.IsValid()) builder.UseTexture(passData.DebugGBuffer2Texture, AccessFlags.Read); if (passData.DebugMotionVectorsTexture.IsValid()) builder.UseTexture(passData.DebugMotionVectorsTexture, AccessFlags.Read); if (passData.DebugMotionMaskTexture.IsValid()) builder.UseTexture(passData.DebugMotionMaskTexture, AccessFlags.Read); if (HDebug == null) HDebug = HExtensions.LoadComputeShader("HDebug"); TextureHandle colorTextureHandle = resourceData.cameraColor; TextureDesc desc = colorTextureHandle.GetDescriptor(renderGraph); desc.colorFormat = GraphicsFormat.R16G16B16A16_SFloat; desc.clearBuffer = false; desc.name = _OutputTarget; desc.enableRandomWrite = true; passData.OutputTarget = renderGraph.CreateTexture(desc); builder.UseTexture(passData.OutputTarget, AccessFlags.ReadWrite); builder.SetRenderFunc((DebugPassData data, UnsafeGraphContext context) => ExecutePass(data, context)); } } private static void ExecutePass(DebugPassData data, UnsafeGraphContext rgContext) { var cmd = CommandBufferHelpers.GetNativeCommandBuffer(rgContext.cmd); int width = (int)(data.UniversalCameraData.camera.scaledPixelWidth * data.UniversalCameraData.renderScale); int height = (int)(data.UniversalCameraData.camera.scaledPixelHeight * data.UniversalCameraData.renderScale); if (data.DebugColorTexture.IsValid()) cmd.SetGlobalTexture(HShaderParams.g_HTraceColor, data.DebugColorTexture); if (data.DebugDepthTexture.IsValid()) cmd.SetGlobalTexture(HShaderParams.g_HTraceDepth, data.DebugDepthTexture); if (data.DebugGBuffer0Texture.IsValid()) cmd.SetGlobalTexture(HShaderParams.g_HTraceGBuffer0, data.DebugGBuffer0Texture); if (data.DebugGBuffer1Texture.IsValid()) cmd.SetGlobalTexture(HShaderParams.g_HTraceGBuffer1, data.DebugGBuffer1Texture); if (data.DebugGBuffer2Texture.IsValid()) cmd.SetGlobalTexture(HShaderParams.g_HTraceGBuffer2, data.DebugGBuffer2Texture); if (data.DebugMotionVectorsTexture.IsValid()) cmd.SetGlobalTexture(HShaderParams.g_HTraceMotionVectors, data.DebugMotionVectorsTexture); if (data.DebugMotionMaskTexture.IsValid()) cmd.SetGlobalTexture(HShaderParams.g_HTraceMotionMask, data.DebugMotionMaskTexture); if (DebugModule(cmd, width, height, data.OutputTarget)) return; Blitter.BlitCameraTexture(cmd, data.OutputTarget, data.ColorTexture); } #endif #endregion --------------------------- Render Graph --------------------------- #region --------------------------- Shared --------------------------- private static bool DebugModule(CommandBuffer cmd, int width, int height, RTHandle outputTarget) { if (HSettings.GeneralSettings.DebugModeWS == DebugModeWS.None || HSettings.GeneralSettings.DebugModeWS == DebugModeWS.DirectLighting) return true; using (new HTraceProfilingScope(cmd, new ProfilingSamplerHTrace("Debug"))) { cmd.SetComputeIntParams(HDebug, DebugSwitch, (int)HSettings.GeneralSettings.DebugModeWS); cmd.SetComputeIntParams(HDebug, BuffersSwitch, (int)HSettings.GeneralSettings.HBuffer); int debug_kernel = 0; cmd.SetComputeTextureParam(HDebug, debug_kernel, Debug_Output, outputTarget.rt); cmd.DispatchCompute(HDebug, debug_kernel, Mathf.CeilToInt(width / 8.0f), Mathf.CeilToInt(height / 8.0f), HRenderer.TextureXrSlices); } return false; } protected internal void Dispose() { Object.DestroyImmediate(LightClusterVisualizationMaterial); //HLightCluster } #endregion --------------------------- Shared --------------------------- } }