174 lines
9.7 KiB
C#
174 lines
9.7 KiB
C#
|
using UnityEngine.Experimental.Rendering;
|
||
|
using UnityEngine.Rendering.RenderGraphModule;
|
||
|
using UnityEngine.Rendering;
|
||
|
|
||
|
namespace UnityEngine.Rendering.HighDefinition
|
||
|
{
|
||
|
class HDDiffuseDenoiser
|
||
|
{
|
||
|
// Resources used for the de-noiser
|
||
|
ComputeShader m_DiffuseDenoiser;
|
||
|
|
||
|
// Runtime Initialization data
|
||
|
bool m_DenoiserInitialized;
|
||
|
Texture2D m_OwnenScrambledTexture;
|
||
|
GraphicsBuffer m_PointDistribution;
|
||
|
|
||
|
// Kernels that may be required
|
||
|
int m_BilateralFilterSingleKernel;
|
||
|
int m_BilateralFilterColorKernel;
|
||
|
int m_GatherSingleKernel;
|
||
|
int m_GatherColorKernel;
|
||
|
|
||
|
public void Init(HDRenderPipeline renderPipeline)
|
||
|
{
|
||
|
// Keep track of the resources
|
||
|
m_DiffuseDenoiser = renderPipeline.runtimeShaders.diffuseDenoiserCS;
|
||
|
|
||
|
// Grab all the kernels we'll eventually need
|
||
|
m_BilateralFilterSingleKernel = m_DiffuseDenoiser.FindKernel("BilateralFilterSingle");
|
||
|
m_BilateralFilterColorKernel = m_DiffuseDenoiser.FindKernel("BilateralFilterColor");
|
||
|
m_GatherSingleKernel = m_DiffuseDenoiser.FindKernel("GatherSingle");
|
||
|
m_GatherColorKernel = m_DiffuseDenoiser.FindKernel("GatherColor");
|
||
|
|
||
|
// Data required for the online initialization
|
||
|
m_DenoiserInitialized = false;
|
||
|
m_OwnenScrambledTexture = renderPipeline.runtimeTextures.owenScrambledRGBATex;
|
||
|
m_PointDistribution = new GraphicsBuffer(GraphicsBuffer.Target.Structured, 16 * 4, 2 * sizeof(float));
|
||
|
}
|
||
|
|
||
|
public void Release()
|
||
|
{
|
||
|
CoreUtils.SafeRelease(m_PointDistribution);
|
||
|
}
|
||
|
|
||
|
class DiffuseDenoiserPassData
|
||
|
{
|
||
|
// Camera parameters
|
||
|
public int texWidth;
|
||
|
public int texHeight;
|
||
|
public int viewCount;
|
||
|
|
||
|
// Denoising parameters
|
||
|
public bool needInit;
|
||
|
public float pixelSpreadTangent;
|
||
|
public float kernelSize;
|
||
|
public bool halfResolutionFilter;
|
||
|
public bool jitterFilter;
|
||
|
public int frameIndex;
|
||
|
public float resolutionMultiplier;
|
||
|
|
||
|
// Kernels
|
||
|
public int bilateralFilterKernel;
|
||
|
public int gatherKernel;
|
||
|
|
||
|
// Other parameters
|
||
|
public BufferHandle pointDistribution;
|
||
|
public ComputeShader diffuseDenoiserCS;
|
||
|
|
||
|
public Texture2D owenScrambledTexture;
|
||
|
public TextureHandle depthStencilBuffer;
|
||
|
public TextureHandle normalBuffer;
|
||
|
public TextureHandle noisyBuffer;
|
||
|
public TextureHandle intermediateBuffer;
|
||
|
public TextureHandle outputBuffer;
|
||
|
}
|
||
|
|
||
|
internal struct DiffuseDenoiserParameters
|
||
|
{
|
||
|
public bool singleChannel;
|
||
|
public float kernelSize;
|
||
|
public bool halfResolutionFilter;
|
||
|
public bool jitterFilter;
|
||
|
public float resolutionMultiplier;
|
||
|
}
|
||
|
|
||
|
public TextureHandle Denoise(RenderGraph renderGraph, HDCamera hdCamera, DiffuseDenoiserParameters denoiserParams,
|
||
|
TextureHandle noisyBuffer, TextureHandle depthBuffer, TextureHandle normalBuffer, TextureHandle outputBuffer)
|
||
|
{
|
||
|
using (var builder = renderGraph.AddRenderPass<DiffuseDenoiserPassData>("DiffuseDenoiser", out var passData, ProfilingSampler.Get(HDProfileId.DiffuseFilter)))
|
||
|
{
|
||
|
// Cannot run in async
|
||
|
builder.EnableAsyncCompute(false);
|
||
|
|
||
|
// Initialization data
|
||
|
passData.needInit = !m_DenoiserInitialized;
|
||
|
m_DenoiserInitialized = true;
|
||
|
passData.owenScrambledTexture = m_OwnenScrambledTexture;
|
||
|
|
||
|
// Camera parameters
|
||
|
passData.texWidth = (int)Mathf.Floor(hdCamera.actualWidth / denoiserParams.resolutionMultiplier);
|
||
|
passData.texHeight = (int)Mathf.Floor(hdCamera.actualHeight / denoiserParams.resolutionMultiplier);
|
||
|
passData.viewCount = hdCamera.viewCount;
|
||
|
|
||
|
// Parameters
|
||
|
passData.pixelSpreadTangent = HDRenderPipeline.GetPixelSpreadTangent(hdCamera.camera.fieldOfView, passData.texWidth, passData.texHeight);
|
||
|
passData.kernelSize = denoiserParams.kernelSize;
|
||
|
passData.halfResolutionFilter = denoiserParams.halfResolutionFilter;
|
||
|
passData.jitterFilter = denoiserParams.jitterFilter;
|
||
|
passData.frameIndex = HDRenderPipeline.RayTracingFrameIndex(hdCamera);
|
||
|
passData.resolutionMultiplier = denoiserParams.resolutionMultiplier;
|
||
|
|
||
|
// Kernels
|
||
|
passData.bilateralFilterKernel = denoiserParams.singleChannel ? m_BilateralFilterSingleKernel : m_BilateralFilterColorKernel;
|
||
|
passData.gatherKernel = denoiserParams.singleChannel ? m_GatherSingleKernel : m_GatherColorKernel;
|
||
|
|
||
|
// Other parameters
|
||
|
passData.diffuseDenoiserCS = m_DiffuseDenoiser;
|
||
|
|
||
|
passData.pointDistribution = builder.ReadBuffer(renderGraph.ImportBuffer(m_PointDistribution));
|
||
|
passData.depthStencilBuffer = builder.ReadTexture(depthBuffer);
|
||
|
passData.normalBuffer = builder.ReadTexture(normalBuffer);
|
||
|
passData.noisyBuffer = builder.ReadTexture(noisyBuffer);
|
||
|
passData.intermediateBuffer = builder.CreateTransientTexture(new TextureDesc(Vector2.one, true, true) { colorFormat = GraphicsFormat.B10G11R11_UFloatPack32, enableRandomWrite = true, name = "DiffuseDenoiserIntermediate" });
|
||
|
passData.outputBuffer = builder.WriteTexture(outputBuffer);
|
||
|
|
||
|
builder.SetRenderFunc(
|
||
|
(DiffuseDenoiserPassData data, RenderGraphContext ctx) =>
|
||
|
{
|
||
|
// Generate the point distribution if needed (this is only ran once)
|
||
|
if (data.needInit)
|
||
|
{
|
||
|
int m_GeneratePointDistributionKernel = data.diffuseDenoiserCS.FindKernel("GeneratePointDistribution");
|
||
|
ctx.cmd.SetComputeTextureParam(data.diffuseDenoiserCS, m_GeneratePointDistributionKernel, HDShaderIDs._OwenScrambledRGTexture, data.owenScrambledTexture);
|
||
|
ctx.cmd.SetComputeBufferParam(data.diffuseDenoiserCS, m_GeneratePointDistributionKernel, "_PointDistributionRW", data.pointDistribution);
|
||
|
ctx.cmd.DispatchCompute(data.diffuseDenoiserCS, m_GeneratePointDistributionKernel, 1, 1, 1);
|
||
|
}
|
||
|
|
||
|
// Evaluate the dispatch parameters
|
||
|
int areaTileSize = 8;
|
||
|
int numTilesX = (data.texWidth + (areaTileSize - 1)) / areaTileSize;
|
||
|
int numTilesY = (data.texHeight + (areaTileSize - 1)) / areaTileSize;
|
||
|
|
||
|
// Request the intermediate buffers that we need
|
||
|
ctx.cmd.SetComputeFloatParam(data.diffuseDenoiserCS, HDShaderIDs._DenoiserFilterRadius, data.kernelSize);
|
||
|
ctx.cmd.SetComputeBufferParam(data.diffuseDenoiserCS, data.bilateralFilterKernel, HDShaderIDs._PointDistribution, data.pointDistribution);
|
||
|
ctx.cmd.SetComputeTextureParam(data.diffuseDenoiserCS, data.bilateralFilterKernel, HDShaderIDs._DenoiseInputTexture, data.noisyBuffer);
|
||
|
ctx.cmd.SetComputeTextureParam(data.diffuseDenoiserCS, data.bilateralFilterKernel, HDShaderIDs._DepthTexture, data.depthStencilBuffer);
|
||
|
ctx.cmd.SetComputeTextureParam(data.diffuseDenoiserCS, data.bilateralFilterKernel, HDShaderIDs._StencilTexture, data.depthStencilBuffer, 0, RenderTextureSubElement.Stencil);
|
||
|
ctx.cmd.SetComputeTextureParam(data.diffuseDenoiserCS, data.bilateralFilterKernel, HDShaderIDs._NormalBufferTexture, data.normalBuffer);
|
||
|
ctx.cmd.SetComputeTextureParam(data.diffuseDenoiserCS, data.bilateralFilterKernel, HDShaderIDs._DenoiseOutputTextureRW, data.halfResolutionFilter ? data.intermediateBuffer : data.outputBuffer);
|
||
|
ctx.cmd.SetComputeIntParam(data.diffuseDenoiserCS, HDShaderIDs._HalfResolutionFilter, data.halfResolutionFilter ? 1 : 0);
|
||
|
ctx.cmd.SetComputeFloatParam(data.diffuseDenoiserCS, HDShaderIDs._PixelSpreadAngleTangent, data.pixelSpreadTangent);
|
||
|
ctx.cmd.SetComputeVectorParam(data.diffuseDenoiserCS, HDShaderIDs._DenoiserResolutionMultiplierVals, new Vector4(data.resolutionMultiplier, 1.0f / data.resolutionMultiplier, 0.0f, 0.0f));
|
||
|
if (data.jitterFilter)
|
||
|
ctx.cmd.SetComputeIntParam(data.diffuseDenoiserCS, HDShaderIDs._JitterFramePeriod, (data.frameIndex % 4));
|
||
|
else
|
||
|
ctx.cmd.SetComputeIntParam(data.diffuseDenoiserCS, HDShaderIDs._JitterFramePeriod, -1);
|
||
|
|
||
|
ctx.cmd.DispatchCompute(data.diffuseDenoiserCS, data.bilateralFilterKernel, numTilesX, numTilesY, data.viewCount);
|
||
|
|
||
|
if (data.halfResolutionFilter)
|
||
|
{
|
||
|
ctx.cmd.SetComputeTextureParam(data.diffuseDenoiserCS, data.gatherKernel, HDShaderIDs._DenoiseInputTexture, data.intermediateBuffer);
|
||
|
ctx.cmd.SetComputeTextureParam(data.diffuseDenoiserCS, data.gatherKernel, HDShaderIDs._DepthTexture, data.depthStencilBuffer);
|
||
|
ctx.cmd.SetComputeTextureParam(data.diffuseDenoiserCS, data.gatherKernel, HDShaderIDs._DenoiseOutputTextureRW, data.outputBuffer);
|
||
|
ctx.cmd.DispatchCompute(data.diffuseDenoiserCS, data.gatherKernel, numTilesX, numTilesY, data.viewCount);
|
||
|
}
|
||
|
});
|
||
|
return passData.outputBuffer;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|