using UnityEngine.Experimental.Rendering; using UnityEngine.Rendering.RenderGraphModule; namespace UnityEngine.Rendering.HighDefinition { class HDDiffuseShadowDenoiser { // The resources quired by this component ComputeShader m_ShadowDenoiser; // Kernels that we are using int m_BilateralFilterHSingleDirectionalKernel; int m_BilateralFilterVSingleDirectionalKernel; int m_BilateralFilterHColorDirectionalKernel; int m_BilateralFilterVColorDirectionalKernel; int m_BilateralFilterHSinglePointKernel; int m_BilateralFilterVSinglePointKernel; int m_BilateralFilterHSingleSpotKernel; int m_BilateralFilterVSingleSpotKernel; int m_BilateralFilterHSinglePyramidKernel; int m_BilateralFilterVSinglePyramidKernel; int m_BilateralFilterHSingleBoxKernel; int m_BilateralFilterVSingleBoxKernel; public HDDiffuseShadowDenoiser() { } public void Init(HDRPRayTracingResources rpRTResources) { m_ShadowDenoiser = rpRTResources.diffuseShadowDenoiserCS; m_BilateralFilterHSingleDirectionalKernel = m_ShadowDenoiser.FindKernel("BilateralFilterHSingleDirectional"); m_BilateralFilterVSingleDirectionalKernel = m_ShadowDenoiser.FindKernel("BilateralFilterVSingleDirectional"); m_BilateralFilterHColorDirectionalKernel = m_ShadowDenoiser.FindKernel("BilateralFilterHColorDirectional"); m_BilateralFilterVColorDirectionalKernel = m_ShadowDenoiser.FindKernel("BilateralFilterVColorDirectional"); m_BilateralFilterHSinglePointKernel = m_ShadowDenoiser.FindKernel("BilateralFilterHSinglePoint"); m_BilateralFilterVSinglePointKernel = m_ShadowDenoiser.FindKernel("BilateralFilterVSinglePoint"); m_BilateralFilterHSingleSpotKernel = m_ShadowDenoiser.FindKernel("BilateralFilterHSingleSpot"); m_BilateralFilterVSingleSpotKernel = m_ShadowDenoiser.FindKernel("BilateralFilterVSingleSpot"); m_BilateralFilterHSinglePyramidKernel = m_ShadowDenoiser.FindKernel("BilateralFilterHSinglePyramid"); m_BilateralFilterVSinglePyramidKernel = m_ShadowDenoiser.FindKernel("BilateralFilterVSinglePyramid"); m_BilateralFilterHSingleBoxKernel = m_ShadowDenoiser.FindKernel("BilateralFilterHSingleBox"); m_BilateralFilterVSingleBoxKernel = m_ShadowDenoiser.FindKernel("BilateralFilterVSingleBox"); } public void Release() { } class DiffuseShadowDenoiserDirectionalPassData { // Camera parameters public int texWidth; public int texHeight; public int viewCount; // Evaluation parameters public float lightAngle; public float cameraFov; public int kernelSize; // Kernels public int bilateralHKernel; public int bilateralVKernel; // Other parameters public ComputeShader diffuseShadowDenoiserCS; public TextureHandle depthStencilBuffer; public TextureHandle normalBuffer; public TextureHandle distanceBuffer; public TextureHandle noisyBuffer; public TextureHandle intermediateBuffer; public TextureHandle outputBuffer; } public TextureHandle DenoiseBufferDirectional(RenderGraph renderGraph, HDCamera hdCamera, TextureHandle depthBuffer, TextureHandle normalBuffer, TextureHandle noisyBuffer, TextureHandle distanceBuffer, int kernelSize, float angularDiameter, bool singleChannel = true) { using (var builder = renderGraph.AddRenderPass("TemporalDenoiser", out var passData, ProfilingSampler.Get(HDProfileId.DiffuseFilter))) { // Cannot run in async builder.EnableAsyncCompute(false); // Fetch all the resources // Set the camera parameters passData.texWidth = hdCamera.actualWidth; passData.texHeight = hdCamera.actualHeight; passData.viewCount = hdCamera.viewCount; // Evaluation parameters passData.cameraFov = hdCamera.camera.fieldOfView * Mathf.PI / 180.0f; // Convert the angular diameter of the directional light to radians (from degrees) passData.lightAngle = angularDiameter * Mathf.PI / 180.0f; passData.kernelSize = kernelSize; // Kernels passData.bilateralHKernel = singleChannel ? m_BilateralFilterHSingleDirectionalKernel : m_BilateralFilterHColorDirectionalKernel; passData.bilateralVKernel = singleChannel ? m_BilateralFilterVSingleDirectionalKernel : m_BilateralFilterVColorDirectionalKernel; // Other parameters passData.diffuseShadowDenoiserCS = m_ShadowDenoiser; // Input buffers passData.depthStencilBuffer = builder.UseDepthBuffer(depthBuffer, DepthAccess.Read); passData.normalBuffer = builder.ReadTexture(normalBuffer); passData.distanceBuffer = builder.ReadTexture(distanceBuffer); passData.noisyBuffer = builder.ReadTexture(noisyBuffer); // Temporary buffers passData.intermediateBuffer = builder.CreateTransientTexture(new TextureDesc(Vector2.one, true, true) { format = GraphicsFormat.R16G16B16A16_SFloat, enableRandomWrite = true, name = "Intermediate buffer" }); // Output buffer passData.outputBuffer = builder.ReadWriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true) { format = GraphicsFormat.R16G16B16A16_SFloat, enableRandomWrite = true, name = "Denoised Buffer" })); builder.SetRenderFunc( (DiffuseShadowDenoiserDirectionalPassData data, RenderGraphContext ctx) => { // Raise the distance based denoiser keyword CoreUtils.SetKeyword(ctx.cmd, "DISTANCE_BASED_DENOISER", true); // Evaluate the dispatch parameters int denoiserTileSize = 8; int numTilesX = (data.texWidth + (denoiserTileSize - 1)) / denoiserTileSize; int numTilesY = (data.texHeight + (denoiserTileSize - 1)) / denoiserTileSize; // Bind input uniforms for both dispatches ctx.cmd.SetComputeFloatParam(data.diffuseShadowDenoiserCS, HDShaderIDs._RaytracingLightAngle, data.lightAngle); ctx.cmd.SetComputeIntParam(data.diffuseShadowDenoiserCS, HDShaderIDs._DenoiserFilterRadius, data.kernelSize); ctx.cmd.SetComputeFloatParam(data.diffuseShadowDenoiserCS, HDShaderIDs._CameraFOV, data.cameraFov); // Bind Input Textures ctx.cmd.SetComputeTextureParam(data.diffuseShadowDenoiserCS, data.bilateralHKernel, HDShaderIDs._DepthTexture, data.depthStencilBuffer); ctx.cmd.SetComputeTextureParam(data.diffuseShadowDenoiserCS, data.bilateralHKernel, HDShaderIDs._NormalBufferTexture, data.normalBuffer); ctx.cmd.SetComputeTextureParam(data.diffuseShadowDenoiserCS, data.bilateralHKernel, HDShaderIDs._DenoiseInputTexture, data.noisyBuffer); ctx.cmd.SetComputeTextureParam(data.diffuseShadowDenoiserCS, data.bilateralHKernel, HDShaderIDs._DistanceTexture, data.distanceBuffer); ctx.cmd.SetComputeTextureParam(data.diffuseShadowDenoiserCS, data.bilateralHKernel, HDShaderIDs._StencilTexture, data.depthStencilBuffer, 0, RenderTextureSubElement.Stencil); // Bind output textures ctx.cmd.SetComputeTextureParam(data.diffuseShadowDenoiserCS, data.bilateralHKernel, HDShaderIDs._DenoiseOutputTextureRW, data.intermediateBuffer); // Do the Horizontal pass ctx.cmd.DispatchCompute(data.diffuseShadowDenoiserCS, data.bilateralHKernel, numTilesX, numTilesY, data.viewCount); // Bind Input Textures ctx.cmd.SetComputeTextureParam(data.diffuseShadowDenoiserCS, data.bilateralVKernel, HDShaderIDs._DepthTexture, data.depthStencilBuffer); ctx.cmd.SetComputeTextureParam(data.diffuseShadowDenoiserCS, data.bilateralVKernel, HDShaderIDs._NormalBufferTexture, data.normalBuffer); ctx.cmd.SetComputeTextureParam(data.diffuseShadowDenoiserCS, data.bilateralVKernel, HDShaderIDs._DenoiseInputTexture, data.intermediateBuffer); ctx.cmd.SetComputeTextureParam(data.diffuseShadowDenoiserCS, data.bilateralVKernel, HDShaderIDs._DistanceTexture, data.distanceBuffer); ctx.cmd.SetComputeTextureParam(data.diffuseShadowDenoiserCS, data.bilateralVKernel, HDShaderIDs._StencilTexture, data.depthStencilBuffer, 0, RenderTextureSubElement.Stencil); // Bind output textures ctx.cmd.SetComputeTextureParam(data.diffuseShadowDenoiserCS, data.bilateralVKernel, HDShaderIDs._DenoiseOutputTextureRW, data.outputBuffer); // Do the Vertical pass ctx.cmd.DispatchCompute(data.diffuseShadowDenoiserCS, data.bilateralVKernel, numTilesX, numTilesY, data.viewCount); CoreUtils.SetKeyword(ctx.cmd, "DISTANCE_BASED_DENOISER", false); }); return passData.outputBuffer; } } class DiffuseShadowDenoiserSpherePassData { // Camera parameters public int texWidth; public int texHeight; public int viewCount; // Evaluation parameters public float cameraFov; public PunctualShadowProperties properties; // Kernels public int bilateralHKernel; public int bilateralVKernel; // Other parameters public ComputeShader diffuseShadowDenoiserCS; public TextureHandle depthStencilBuffer; public TextureHandle normalBuffer; public TextureHandle distanceBuffer; public TextureHandle noisyBuffer; public TextureHandle intermediateBuffer; public TextureHandle outputBuffer; } public TextureHandle DenoiseBufferSphere(RenderGraph renderGraph, HDCamera hdCamera, TextureHandle depthBuffer, TextureHandle normalBuffer, TextureHandle noisyBuffer, TextureHandle distanceBuffer, PunctualShadowProperties properties) { using (var builder = renderGraph.AddRenderPass("DiffuseDenoiser", out var passData, ProfilingSampler.Get(HDProfileId.DiffuseFilter))) { // Cannot run in async builder.EnableAsyncCompute(false); // Set the camera parameters passData.texWidth = hdCamera.actualWidth; passData.texHeight = hdCamera.actualHeight; passData.viewCount = hdCamera.viewCount; // Evaluation parameters passData.cameraFov = hdCamera.camera.fieldOfView * Mathf.PI / 180.0f; passData.properties = properties; // Make sure the position is in the right space before injecting it if (ShaderConfig.s_CameraRelativeRendering != 0) passData.properties.lightPosition -= hdCamera.camera.transform.position; // Kernels switch (properties.lightType) { case GPULightType.Spot: { passData.bilateralHKernel = m_BilateralFilterHSingleSpotKernel; passData.bilateralVKernel = m_BilateralFilterVSingleSpotKernel; } break; case GPULightType.ProjectorPyramid: { passData.bilateralHKernel = m_BilateralFilterHSinglePyramidKernel; passData.bilateralVKernel = m_BilateralFilterVSinglePyramidKernel; } break; case GPULightType.ProjectorBox: { passData.bilateralHKernel = m_BilateralFilterHSingleBoxKernel; passData.bilateralVKernel = m_BilateralFilterVSingleBoxKernel; } break; case GPULightType.Point: default: { passData.bilateralHKernel = m_BilateralFilterHSinglePointKernel; passData.bilateralVKernel = m_BilateralFilterVSinglePointKernel; } break; } // Other parameters passData.diffuseShadowDenoiserCS = m_ShadowDenoiser; // Input buffers passData.depthStencilBuffer = builder.UseDepthBuffer(depthBuffer, DepthAccess.Read); passData.normalBuffer = builder.ReadTexture(normalBuffer); if (properties.distanceBasedDenoiser) passData.distanceBuffer = builder.ReadTexture(distanceBuffer); passData.noisyBuffer = builder.ReadTexture(noisyBuffer); // Temporary buffers passData.intermediateBuffer = builder.CreateTransientTexture(new TextureDesc(Vector2.one, true, true) { format = GraphicsFormat.R16G16B16A16_SFloat, enableRandomWrite = true, name = "Intermediate buffer" }); // Output buffer passData.outputBuffer = builder.ReadWriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true) { format = GraphicsFormat.R16G16B16A16_SFloat, enableRandomWrite = true, name = "Denoised Buffer" })); builder.SetRenderFunc( (DiffuseShadowDenoiserSpherePassData data, RenderGraphContext ctx) => { // Evaluate the dispatch parameters int shadowTileSize = 8; int numTilesX = (data.texWidth + (shadowTileSize - 1)) / shadowTileSize; int numTilesY = (data.texHeight + (shadowTileSize - 1)) / shadowTileSize; // Raise the distance based denoiser keyword CoreUtils.SetKeyword(ctx.cmd, "DISTANCE_BASED_DENOISER", data.properties.distanceBasedDenoiser); // Bind input uniforms for both dispatches ctx.cmd.SetComputeIntParam(data.diffuseShadowDenoiserCS, HDShaderIDs._RaytracingTargetLight, data.properties.lightIndex); switch(properties.lightType) { case GPULightType.Spot: { ctx.cmd.SetComputeFloatParam(data.diffuseShadowDenoiserCS, HDShaderIDs._RaytracingLightAngle, data.properties.lightConeAngle); } break; case GPULightType.ProjectorPyramid: case GPULightType.ProjectorBox: { ctx.cmd.SetComputeFloatParam(data.diffuseShadowDenoiserCS, HDShaderIDs._RaytracingLightSizeX, data.properties.lightSizeX); ctx.cmd.SetComputeFloatParam(data.diffuseShadowDenoiserCS, HDShaderIDs._RaytracingLightSizeY, data.properties.lightSizeY); } break; } ctx.cmd.SetComputeFloatParam(data.diffuseShadowDenoiserCS, HDShaderIDs._RaytracingLightRadius, data.properties.lightRadius); ctx.cmd.SetComputeIntParam(data.diffuseShadowDenoiserCS, HDShaderIDs._DenoiserFilterRadius, data.properties.kernelSize); ctx.cmd.SetComputeVectorParam(data.diffuseShadowDenoiserCS, HDShaderIDs._SphereLightPosition, data.properties.lightPosition); ctx.cmd.SetComputeFloatParam(data.diffuseShadowDenoiserCS, HDShaderIDs._CameraFOV, data.cameraFov); // Bind Input Textures ctx.cmd.SetComputeTextureParam(data.diffuseShadowDenoiserCS, data.bilateralHKernel, HDShaderIDs._DepthTexture, data.depthStencilBuffer); ctx.cmd.SetComputeTextureParam(data.diffuseShadowDenoiserCS, data.bilateralHKernel, HDShaderIDs._NormalBufferTexture, data.normalBuffer); ctx.cmd.SetComputeTextureParam(data.diffuseShadowDenoiserCS, data.bilateralHKernel, HDShaderIDs._DenoiseInputTexture, data.noisyBuffer); ctx.cmd.SetComputeTextureParam(data.diffuseShadowDenoiserCS, data.bilateralHKernel, HDShaderIDs._StencilTexture, data.depthStencilBuffer, 0, RenderTextureSubElement.Stencil); if (data.properties.distanceBasedDenoiser) ctx.cmd.SetComputeTextureParam(data.diffuseShadowDenoiserCS, data.bilateralHKernel, HDShaderIDs._DistanceTexture, data.distanceBuffer); // Bind output textures ctx.cmd.SetComputeTextureParam(data.diffuseShadowDenoiserCS, data.bilateralHKernel, HDShaderIDs._DenoiseOutputTextureRW, data.intermediateBuffer); // Do the Horizontal pass ctx.cmd.DispatchCompute(data.diffuseShadowDenoiserCS, data.bilateralHKernel, numTilesX, numTilesY, data.viewCount); ctx.cmd.SetComputeTextureParam(data.diffuseShadowDenoiserCS, data.bilateralVKernel, HDShaderIDs._DepthTexture, data.depthStencilBuffer); ctx.cmd.SetComputeTextureParam(data.diffuseShadowDenoiserCS, data.bilateralVKernel, HDShaderIDs._NormalBufferTexture, data.normalBuffer); ctx.cmd.SetComputeTextureParam(data.diffuseShadowDenoiserCS, data.bilateralVKernel, HDShaderIDs._DenoiseInputTexture, data.intermediateBuffer); ctx.cmd.SetComputeTextureParam(data.diffuseShadowDenoiserCS, data.bilateralVKernel, HDShaderIDs._StencilTexture, data.depthStencilBuffer, 0, RenderTextureSubElement.Stencil); if (data.properties.distanceBasedDenoiser) ctx.cmd.SetComputeTextureParam(data.diffuseShadowDenoiserCS, data.bilateralVKernel, HDShaderIDs._DistanceTexture, data.distanceBuffer); // Bind output textures ctx.cmd.SetComputeTextureParam(data.diffuseShadowDenoiserCS, data.bilateralVKernel, HDShaderIDs._DenoiseOutputTextureRW, data.outputBuffer); // Do the Vertical pass ctx.cmd.DispatchCompute(data.diffuseShadowDenoiserCS, data.bilateralVKernel, numTilesX, numTilesY, data.viewCount); CoreUtils.SetKeyword(ctx.cmd, "DISTANCE_BASED_DENOISER", false); }); return passData.outputBuffer; } } } }