2021-09-09 20:42:29 -04:00

180 lines
10 KiB
C#

using UnityEngine.Experimental.Rendering;
using UnityEngine.Experimental.Rendering.RenderGraphModule;
namespace UnityEngine.Rendering.HighDefinition
{
public partial class HDRenderPipeline
{
class TraceSSGIPassData
{
public SSGITraceParameters parameters;
public TextureHandle depthTexture;
public TextureHandle normalBuffer;
public TextureHandle motionVectorsBuffer;
public TextureHandle colorPyramid;
public TextureHandle historyDepth;
public TextureHandle hitPointBuffer;
public TextureHandle outputBuffer0;
public TextureHandle outputBuffer1;
}
struct TraceOutput
{
public TextureHandle outputBuffer0;
public TextureHandle outputBuffer1;
}
TraceOutput TraceSSGI(RenderGraph renderGraph, HDCamera hdCamera, GlobalIllumination giSettings, TextureHandle depthPyramid, TextureHandle normalBuffer, TextureHandle motionVectorsBuffer)
{
using (var builder = renderGraph.AddRenderPass<TraceSSGIPassData>("Trace SSGI", out var passData, ProfilingSampler.Get(HDProfileId.SSGITrace)))
{
builder.EnableAsyncCompute(false);
passData.parameters = PrepareSSGITraceParameters(hdCamera, giSettings);
passData.depthTexture = builder.ReadTexture(depthPyramid);
passData.normalBuffer = builder.ReadTexture(normalBuffer);
if (!hdCamera.frameSettings.IsEnabled(FrameSettingsField.ObjectMotionVectors))
{
passData.motionVectorsBuffer = builder.ReadTexture(renderGraph.defaultResources.blackTextureXR);
}
else
{
passData.motionVectorsBuffer = builder.ReadTexture(motionVectorsBuffer);
}
var colorPyramid = hdCamera.GetPreviousFrameRT((int)HDCameraFrameHistoryType.ColorBufferMipChain);
passData.colorPyramid = colorPyramid != null ? builder.ReadTexture(renderGraph.ImportTexture(colorPyramid)) : renderGraph.defaultResources.blackTextureXR;
var historyDepth = hdCamera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.Depth);
passData.historyDepth = historyDepth != null ? builder.ReadTexture(renderGraph.ImportTexture(historyDepth)) : renderGraph.defaultResources.blackTextureXR;
passData.hitPointBuffer = builder.CreateTransientTexture(new TextureDesc(Vector2.one, true, true)
{ colorFormat = GraphicsFormat.R16G16B16A16_SFloat, enableRandomWrite = true, name = "SSGI Hit Point"});
passData.outputBuffer0 = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true)
{ colorFormat = GraphicsFormat.R16G16B16A16_SFloat, enableRandomWrite = true, name = "SSGI Signal0"}));
passData.outputBuffer1 = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true)
{ colorFormat = GraphicsFormat.R16G16B16A16_SFloat, enableRandomWrite = true, name = "SSGI Signal1" }));
builder.SetRenderFunc(
(TraceSSGIPassData data, RenderGraphContext ctx) =>
{
// We need to fill the structure that holds the various resources
SSGITraceResources resources = new SSGITraceResources();
resources.depthTexture = data.depthTexture;
resources.normalBuffer = data.normalBuffer;
resources.motionVectorsBuffer = data.motionVectorsBuffer;
resources.colorPyramid = data.colorPyramid;
resources.historyDepth = data.historyDepth;
resources.hitPointBuffer = data.hitPointBuffer;
resources.outputBuffer0 = data.outputBuffer0;
resources.outputBuffer1 = data.outputBuffer1;
ExecuteSSGITrace(ctx.cmd, data.parameters, resources);
});
TraceOutput traceOutput = new TraceOutput();
traceOutput.outputBuffer0 = passData.outputBuffer0;
traceOutput.outputBuffer1 = passData.outputBuffer1;
return traceOutput;
}
}
class UpscaleSSGIPassData
{
public SSGIUpscaleParameters parameters;
public TextureHandle depthTexture;
public TextureHandle inputBuffer;
public TextureHandle outputBuffer;
}
TextureHandle UpscaleSSGI(RenderGraph renderGraph, HDCamera hdCamera, GlobalIllumination giSettings, HDUtils.PackedMipChainInfo info, TextureHandle depthPyramid, TextureHandle inputBuffer)
{
using (var builder = renderGraph.AddRenderPass<UpscaleSSGIPassData>("Upscale SSGI", out var passData, ProfilingSampler.Get(HDProfileId.SSGIUpscale)))
{
builder.EnableAsyncCompute(false);
passData.parameters = PrepareSSGIUpscaleParameters(hdCamera, giSettings, info);
passData.depthTexture = builder.ReadTexture(depthPyramid);
passData.inputBuffer = builder.ReadTexture(inputBuffer);
passData.outputBuffer = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true)
{ colorFormat = GraphicsFormat.R16G16B16A16_SFloat, enableRandomWrite = true, name = "SSGI Final" }));
builder.SetRenderFunc(
(UpscaleSSGIPassData data, RenderGraphContext ctx) =>
{
// We need to fill the structure that holds the various resources
SSGIUpscaleResources resources = new SSGIUpscaleResources();
resources.depthTexture = data.depthTexture;
resources.inputBuffer = data.inputBuffer;
resources.outputBuffer = data.outputBuffer;
ExecuteSSGIUpscale(ctx.cmd, data.parameters, resources);
});
return passData.outputBuffer;
}
}
class ConvertSSGIPassData
{
public SSGIConvertParameters parameters;
public TextureHandle depthTexture;
public TextureHandle stencilBuffer;
public TextureHandle normalBuffer;
public TextureHandle inoutputBuffer0;
public TextureHandle inoutputBuffer1;
}
TextureHandle ConvertSSGI(RenderGraph renderGraph, HDCamera hdCamera, bool halfResolution, TextureHandle depthPyramid, TextureHandle stencilBuffer, TextureHandle normalBuffer, TextureHandle inoutputBuffer0, TextureHandle inoutputBuffer1)
{
using (var builder = renderGraph.AddRenderPass<ConvertSSGIPassData>("Upscale SSGI", out var passData, ProfilingSampler.Get(HDProfileId.SSGIConvert)))
{
builder.EnableAsyncCompute(false);
passData.parameters = PrepareSSGIConvertParameters(hdCamera, halfResolution);
passData.depthTexture = builder.ReadTexture(depthPyramid);
passData.stencilBuffer = builder.ReadTexture(stencilBuffer);
passData.normalBuffer = builder.ReadTexture(normalBuffer);
passData.inoutputBuffer0 = builder.ReadWriteTexture(inoutputBuffer0);
passData.inoutputBuffer1 = builder.ReadWriteTexture(inoutputBuffer1);
builder.SetRenderFunc(
(ConvertSSGIPassData data, RenderGraphContext ctx) =>
{
// We need to fill the structure that holds the various resources
SSGIConvertResources resources = new SSGIConvertResources();
resources.depthTexture = data.depthTexture;
resources.stencilBuffer = data.stencilBuffer;
resources.normalBuffer = data.normalBuffer;
resources.inoutBuffer0 = data.inoutputBuffer0;
resources.inputBufer1 = data.inoutputBuffer1;
ExecuteSSGIConversion(ctx.cmd, data.parameters, resources);
});
return passData.inoutputBuffer0;
}
}
TextureHandle RenderSSGI(RenderGraph renderGraph, HDCamera hdCamera, TextureHandle depthPyramid, TextureHandle stencilBuffer, TextureHandle normalBuffer, TextureHandle motionVectorsBuffer, ShaderVariablesRaytracing shaderVariablesRayTracingCB, HDUtils.PackedMipChainInfo info)
{
// Grab the global illumination volume component
GlobalIllumination giSettings = hdCamera.volumeStack.GetComponent<GlobalIllumination>();
using (new RenderGraphProfilingScope(renderGraph, ProfilingSampler.Get(HDProfileId.SSGIPass)))
{
// Trace the signal
TraceOutput traceOutput = TraceSSGI(renderGraph, hdCamera, giSettings, depthPyramid, normalBuffer, motionVectorsBuffer);
// Evaluate the history validity
float historyValidity = EvaluateIndirectDiffuseHistoryValidityCombined(hdCamera, giSettings.fullResolutionSS, false);
SSGIDenoiser ssgiDenoiser = GetSSGIDenoiser();
SSGIDenoiser.SSGIDenoiserOutput denoiserOutput = ssgiDenoiser.Denoise(renderGraph, hdCamera, depthPyramid, normalBuffer, motionVectorsBuffer, traceOutput.outputBuffer0, traceOutput.outputBuffer1, m_DepthBufferMipChainInfo, !giSettings.fullResolutionSS, historyValidity: historyValidity);
// Propagate the history
PropagateIndirectDiffuseHistoryValidityCombined(hdCamera, giSettings.fullResolutionSS, false);
// Convert back the result to RGB space
TextureHandle colorBuffer = ConvertSSGI(renderGraph, hdCamera, !giSettings.fullResolutionSS, depthPyramid, stencilBuffer, normalBuffer, denoiserOutput.outputBuffer0, denoiserOutput.outputBuffer1);
// Upscale it if required
// If this was a half resolution effect, we still have to upscale it
if (!giSettings.fullResolutionSS)
colorBuffer = UpscaleSSGI(renderGraph, hdCamera, giSettings, info, depthPyramid, colorBuffer);
return colorBuffer;
}
}
}
}