357 lines
19 KiB
C#

using UnityEngine.Experimental.Rendering;
using UnityEngine.Experimental.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_BilateralFilterHSingleSphereKernel;
int m_BilateralFilterVSingleSphereKernel;
public HDDiffuseShadowDenoiser()
{
}
public void Init(HDRenderPipelineRayTracingResources 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_BilateralFilterHSingleSphereKernel = m_ShadowDenoiser.FindKernel("BilateralFilterHSingleSphere");
m_BilateralFilterVSingleSphereKernel = m_ShadowDenoiser.FindKernel("BilateralFilterVSingleSphere");
}
public void Release()
{
}
struct DiffuseShadowDirectionalDenoiserParameters
{
// 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;
}
DiffuseShadowDirectionalDenoiserParameters PrepareDiffuseShadowDirectionalDenoiserParameters(HDCamera hdCamera, float angularDiameter, int kernelSize, bool singleChannel)
{
DiffuseShadowDirectionalDenoiserParameters dsddParams = new DiffuseShadowDirectionalDenoiserParameters();
// Set the camera parameters
dsddParams.texWidth = hdCamera.actualWidth;
dsddParams.texHeight = hdCamera.actualHeight;
dsddParams.viewCount = hdCamera.viewCount;
// Evaluation parameters
dsddParams.cameraFov = hdCamera.camera.fieldOfView * Mathf.PI / 180.0f;
// Convert the angular diameter of the directional light to radians (from degrees)
dsddParams.lightAngle = angularDiameter * Mathf.PI / 180.0f;
dsddParams.kernelSize = kernelSize;
// Kernels
dsddParams.bilateralHKernel = singleChannel ? m_BilateralFilterHSingleDirectionalKernel : m_BilateralFilterHColorDirectionalKernel;
dsddParams.bilateralVKernel = singleChannel ? m_BilateralFilterVSingleDirectionalKernel : m_BilateralFilterVColorDirectionalKernel;
// Other parameters
dsddParams.diffuseShadowDenoiserCS = m_ShadowDenoiser;
return dsddParams;
}
struct DiffuseShadowDirectionalDenoiserResources
{
public RTHandle depthStencilBuffer;
public RTHandle normalBuffer;
public RTHandle distanceBuffer;
public RTHandle noisyBuffer;
public RTHandle intermediateBuffer;
public RTHandle outputBuffer;
}
static void ExecuteDiffuseShadowDirectionalDenoiser(CommandBuffer cmd, DiffuseShadowDirectionalDenoiserParameters dsddParams, DiffuseShadowDirectionalDenoiserResources dsddResources)
{
// Evaluate the dispatch parameters
int denoiserTileSize = 8;
int numTilesX = (dsddParams.texWidth + (denoiserTileSize - 1)) / denoiserTileSize;
int numTilesY = (dsddParams.texHeight + (denoiserTileSize - 1)) / denoiserTileSize;
// Bind input uniforms
cmd.SetComputeFloatParam(dsddParams.diffuseShadowDenoiserCS, HDShaderIDs._DirectionalLightAngle, dsddParams.lightAngle);
cmd.SetComputeIntParam(dsddParams.diffuseShadowDenoiserCS, HDShaderIDs._DenoiserFilterRadius, dsddParams.kernelSize);
cmd.SetComputeFloatParam(dsddParams.diffuseShadowDenoiserCS, HDShaderIDs._CameraFOV, dsddParams.cameraFov);
// Bind Input Textures
cmd.SetComputeTextureParam(dsddParams.diffuseShadowDenoiserCS, dsddParams.bilateralHKernel, HDShaderIDs._DepthTexture, dsddResources.depthStencilBuffer);
cmd.SetComputeTextureParam(dsddParams.diffuseShadowDenoiserCS, dsddParams.bilateralHKernel, HDShaderIDs._NormalBufferTexture, dsddResources.normalBuffer);
cmd.SetComputeTextureParam(dsddParams.diffuseShadowDenoiserCS, dsddParams.bilateralHKernel, HDShaderIDs._DenoiseInputTexture, dsddResources.noisyBuffer);
cmd.SetComputeTextureParam(dsddParams.diffuseShadowDenoiserCS, dsddParams.bilateralHKernel, HDShaderIDs._DistanceTexture, dsddResources.distanceBuffer);
// Bind output textures
cmd.SetComputeTextureParam(dsddParams.diffuseShadowDenoiserCS, dsddParams.bilateralHKernel, HDShaderIDs._DenoiseOutputTextureRW, dsddResources.intermediateBuffer);
// Do the Horizontal pass
cmd.DispatchCompute(dsddParams.diffuseShadowDenoiserCS, dsddParams.bilateralHKernel, numTilesX, numTilesY, dsddParams.viewCount);
// Bind input uniforms
cmd.SetComputeIntParam(dsddParams.diffuseShadowDenoiserCS, HDShaderIDs._DenoiserFilterRadius, dsddParams.kernelSize);
cmd.SetComputeFloatParam(dsddParams.diffuseShadowDenoiserCS, HDShaderIDs._DirectionalLightAngle, dsddParams.lightAngle);
cmd.SetComputeFloatParam(dsddParams.diffuseShadowDenoiserCS, HDShaderIDs._CameraFOV, dsddParams.cameraFov);
// Bind Input Textures
cmd.SetComputeTextureParam(dsddParams.diffuseShadowDenoiserCS, dsddParams.bilateralVKernel, HDShaderIDs._DepthTexture, dsddResources.depthStencilBuffer);
cmd.SetComputeTextureParam(dsddParams.diffuseShadowDenoiserCS, dsddParams.bilateralVKernel, HDShaderIDs._NormalBufferTexture, dsddResources.normalBuffer);
cmd.SetComputeTextureParam(dsddParams.diffuseShadowDenoiserCS, dsddParams.bilateralVKernel, HDShaderIDs._DenoiseInputTexture, dsddResources.intermediateBuffer);
cmd.SetComputeTextureParam(dsddParams.diffuseShadowDenoiserCS, dsddParams.bilateralVKernel, HDShaderIDs._DistanceTexture, dsddResources.distanceBuffer);
// Bind output textures
cmd.SetComputeTextureParam(dsddParams.diffuseShadowDenoiserCS, dsddParams.bilateralVKernel, HDShaderIDs._DenoiseOutputTextureRW, dsddResources.outputBuffer);
// Do the Vertical pass
cmd.DispatchCompute(dsddParams.diffuseShadowDenoiserCS, dsddParams.bilateralVKernel, numTilesX, numTilesY, dsddParams.viewCount);
}
class DiffuseShadowDenoiserDirectionalPassData
{
public DiffuseShadowDirectionalDenoiserParameters parameters;
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<DiffuseShadowDenoiserDirectionalPassData>("TemporalDenoiser", out var passData, ProfilingSampler.Get(HDProfileId.DiffuseFilter)))
{
// Cannot run in async
builder.EnableAsyncCompute(false);
// Fetch all the resources
passData.parameters = PrepareDiffuseShadowDirectionalDenoiserParameters(hdCamera, angularDiameter, kernelSize, singleChannel);
// 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)
{ colorFormat = GraphicsFormat.R16G16B16A16_SFloat, enableRandomWrite = true, name = "Intermediate buffer" });
// Output buffer
passData.outputBuffer = builder.ReadWriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true)
{ colorFormat = GraphicsFormat.R16G16B16A16_SFloat, enableRandomWrite = true, name = "Denoised Buffer" }));
builder.SetRenderFunc(
(DiffuseShadowDenoiserDirectionalPassData data, RenderGraphContext ctx) =>
{
DiffuseShadowDirectionalDenoiserResources resources = new DiffuseShadowDirectionalDenoiserResources();
resources.depthStencilBuffer = data.depthStencilBuffer;
resources.normalBuffer = data.normalBuffer;
resources.distanceBuffer = data.distanceBuffer;
resources.noisyBuffer = data.noisyBuffer;
resources.intermediateBuffer = data.intermediateBuffer;
resources.outputBuffer = data.outputBuffer;
ExecuteDiffuseShadowDirectionalDenoiser(ctx.cmd, data.parameters, resources);
});
return passData.outputBuffer;
}
}
struct DiffuseShadowSphereDenoiserParameters
{
// Camera parameters
public int texWidth;
public int texHeight;
public int viewCount;
// Evaluation parameters
public Vector3 lightPosition;
public float lightRadius;
public float cameraFov;
public int kernelSize;
// Kernels
public int bilateralHKernel;
public int bilateralVKernel;
// Other parameters
public ComputeShader diffuseShadowDenoiserCS;
}
DiffuseShadowSphereDenoiserParameters PrepareDiffuseShadowSphereDenoiserParameters(HDCamera hdCamera, Vector3 lightPosition, float lightRadius, int kernelSize)
{
DiffuseShadowSphereDenoiserParameters dssdParams = new DiffuseShadowSphereDenoiserParameters();
// Set the camera parameters
dssdParams.texWidth = hdCamera.actualWidth;
dssdParams.texHeight = hdCamera.actualHeight;
dssdParams.viewCount = hdCamera.viewCount;
// Evaluation parameters
dssdParams.cameraFov = hdCamera.camera.fieldOfView * Mathf.PI / 180.0f;
dssdParams.lightPosition = lightPosition;
// Make sure the position is in the right space before injecting it
if (ShaderConfig.s_CameraRelativeRendering != 0)
{
dssdParams.lightPosition -= hdCamera.camera.transform.position;
}
dssdParams.lightRadius = lightRadius;
dssdParams.kernelSize = kernelSize;
// Kernels
dssdParams.bilateralHKernel = m_BilateralFilterHSingleSphereKernel;
dssdParams.bilateralVKernel = m_BilateralFilterVSingleSphereKernel;
// Other parameters
dssdParams.diffuseShadowDenoiserCS = m_ShadowDenoiser;
return dssdParams;
}
struct DiffuseShadowSphereDenoiserResources
{
public RTHandle depthStencilBuffer;
public RTHandle normalBuffer;
public RTHandle distanceBuffer;
public RTHandle noisyBuffer;
public RTHandle intermediateBuffer;
public RTHandle outputBuffer;
}
static void ExecuteDiffuseShadowSphereDenoiser(CommandBuffer cmd, DiffuseShadowSphereDenoiserParameters dssdParams, DiffuseShadowSphereDenoiserResources dssdResources)
{
// Evaluate the dispatch parameters
int shadowTileSize = 8;
int numTilesX = (dssdParams.texWidth + (shadowTileSize - 1)) / shadowTileSize;
int numTilesY = (dssdParams.texHeight + (shadowTileSize - 1)) / shadowTileSize;
// Bind input uniforms
cmd.SetComputeIntParam(dssdParams.diffuseShadowDenoiserCS, HDShaderIDs._DenoiserFilterRadius, dssdParams.kernelSize);
cmd.SetComputeVectorParam(dssdParams.diffuseShadowDenoiserCS, HDShaderIDs._SphereLightPosition, dssdParams.lightPosition);
cmd.SetComputeFloatParam(dssdParams.diffuseShadowDenoiserCS, HDShaderIDs._SphereLightRadius, dssdParams.lightRadius);
cmd.SetComputeFloatParam(dssdParams.diffuseShadowDenoiserCS, HDShaderIDs._CameraFOV, dssdParams.cameraFov);
// Bind Input Textures
cmd.SetComputeTextureParam(dssdParams.diffuseShadowDenoiserCS, dssdParams.bilateralHKernel, HDShaderIDs._DepthTexture, dssdResources.depthStencilBuffer);
cmd.SetComputeTextureParam(dssdParams.diffuseShadowDenoiserCS, dssdParams.bilateralHKernel, HDShaderIDs._NormalBufferTexture, dssdResources.normalBuffer);
cmd.SetComputeTextureParam(dssdParams.diffuseShadowDenoiserCS, dssdParams.bilateralHKernel, HDShaderIDs._DenoiseInputTexture, dssdResources.noisyBuffer);
cmd.SetComputeTextureParam(dssdParams.diffuseShadowDenoiserCS, dssdParams.bilateralHKernel, HDShaderIDs._DistanceTexture, dssdResources.distanceBuffer);
// Bind output textures
cmd.SetComputeTextureParam(dssdParams.diffuseShadowDenoiserCS, dssdParams.bilateralHKernel, HDShaderIDs._DenoiseOutputTextureRW, dssdResources.intermediateBuffer);
// Do the Horizontal pass
cmd.DispatchCompute(dssdParams.diffuseShadowDenoiserCS, dssdParams.bilateralHKernel, numTilesX, numTilesY, dssdParams.viewCount);
// Bind input uniforms
cmd.SetComputeIntParam(dssdParams.diffuseShadowDenoiserCS, HDShaderIDs._DenoiserFilterRadius, dssdParams.kernelSize);
cmd.SetComputeVectorParam(dssdParams.diffuseShadowDenoiserCS, HDShaderIDs._SphereLightPosition, dssdParams.lightPosition);
cmd.SetComputeFloatParam(dssdParams.diffuseShadowDenoiserCS, HDShaderIDs._SphereLightRadius, dssdParams.lightRadius);
cmd.SetComputeFloatParam(dssdParams.diffuseShadowDenoiserCS, HDShaderIDs._CameraFOV, dssdParams.cameraFov);
cmd.SetComputeTextureParam(dssdParams.diffuseShadowDenoiserCS, dssdParams.bilateralVKernel, HDShaderIDs._DenoiseInputTexture, dssdResources.intermediateBuffer);
cmd.SetComputeTextureParam(dssdParams.diffuseShadowDenoiserCS, dssdParams.bilateralVKernel, HDShaderIDs._DistanceTexture, dssdResources.distanceBuffer);
cmd.SetComputeTextureParam(dssdParams.diffuseShadowDenoiserCS, dssdParams.bilateralVKernel, HDShaderIDs._DepthTexture, dssdResources.depthStencilBuffer);
cmd.SetComputeTextureParam(dssdParams.diffuseShadowDenoiserCS, dssdParams.bilateralVKernel, HDShaderIDs._NormalBufferTexture, dssdResources.normalBuffer);
// Bind output textures
cmd.SetComputeTextureParam(dssdParams.diffuseShadowDenoiserCS, dssdParams.bilateralVKernel, HDShaderIDs._DenoiseOutputTextureRW, dssdResources.outputBuffer);
// Do the Vertical pass
cmd.DispatchCompute(dssdParams.diffuseShadowDenoiserCS, dssdParams.bilateralVKernel, numTilesX, numTilesY, dssdParams.viewCount);
}
class DiffuseShadowDenoiserSpherePassData
{
public DiffuseShadowSphereDenoiserParameters parameters;
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,
int kernelSize, Vector3 lightPosition, float lightRadius)
{
using (var builder = renderGraph.AddRenderPass<DiffuseShadowDenoiserSpherePassData>("DiffuseDenoiser", out var passData, ProfilingSampler.Get(HDProfileId.DiffuseFilter)))
{
// Cannot run in async
builder.EnableAsyncCompute(false);
// Fetch all the resources
passData.parameters = PrepareDiffuseShadowSphereDenoiserParameters(hdCamera, lightPosition, lightRadius, kernelSize);
// 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)
{ colorFormat = GraphicsFormat.R16G16B16A16_SFloat, enableRandomWrite = true, name = "Intermediate buffer" });
// Output buffer
passData.outputBuffer = builder.ReadWriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true)
{ colorFormat = GraphicsFormat.R16G16B16A16_SFloat, enableRandomWrite = true, name = "Denoised Buffer" }));
builder.SetRenderFunc(
(DiffuseShadowDenoiserSpherePassData data, RenderGraphContext ctx) =>
{
DiffuseShadowSphereDenoiserResources resources = new DiffuseShadowSphereDenoiserResources();
resources.depthStencilBuffer = data.depthStencilBuffer;
resources.normalBuffer = data.normalBuffer;
resources.distanceBuffer = data.distanceBuffer;
resources.noisyBuffer = data.noisyBuffer;
resources.intermediateBuffer = data.intermediateBuffer;
resources.outputBuffer = data.outputBuffer;
ExecuteDiffuseShadowSphereDenoiser(ctx.cmd, data.parameters, resources);
});
return passData.outputBuffer;
}
}
}
}