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

193 lines
9.3 KiB
C#

using UnityEngine.Experimental.Rendering;
using UnityEngine.Experimental.Rendering.RenderGraphModule;
namespace UnityEngine.Rendering.HighDefinition
{
partial class AmbientOcclusionSystem
{
TextureHandle CreateAmbientOcclusionTexture(RenderGraph renderGraph)
{
return renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true) { enableRandomWrite = true, colorFormat = GraphicsFormat.R8_UNorm, name = "Ambient Occlusion" });
}
public TextureHandle Render(RenderGraph renderGraph, HDCamera hdCamera, TextureHandle depthBuffer, TextureHandle normalBuffer, TextureHandle motionVectors, TextureHandle historyValidityBuffer,
in HDUtils.PackedMipChainInfo depthMipInfo, ShaderVariablesRaytracing shaderVariablesRaytracing, TextureHandle rayCountTexture)
{
var settings = hdCamera.volumeStack.GetComponent<AmbientOcclusion>();
TextureHandle result;
// AO has side effects (as it uses an imported history buffer)
// So we can't rely on automatic pass stripping. This is why we have to be explicit here.
if (IsActive(hdCamera, settings))
{
using (new RenderGraphProfilingScope(renderGraph, ProfilingSampler.Get(HDProfileId.AmbientOcclusion)))
{
float scaleFactor = m_RunningFullRes ? 1.0f : 0.5f;
if (settings.fullResolution != m_RunningFullRes)
{
m_RunningFullRes = settings.fullResolution;
scaleFactor = m_RunningFullRes ? 1.0f : 0.5f;
}
hdCamera.AllocateAmbientOcclusionHistoryBuffer(scaleFactor);
if (hdCamera.frameSettings.IsEnabled(FrameSettingsField.RayTracing) && settings.rayTracing.value)
return m_RaytracingAmbientOcclusion.RenderRTAO(renderGraph, hdCamera, depthBuffer, normalBuffer, motionVectors, historyValidityBuffer,
rayCountTexture, shaderVariablesRaytracing);
else
{
var historyRT = hdCamera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.AmbientOcclusion);
var currentHistory = renderGraph.ImportTexture(historyRT);
var outputHistory = renderGraph.ImportTexture(hdCamera.GetPreviousFrameRT((int)HDCameraFrameHistoryType.AmbientOcclusion));
Vector2 historySize = new Vector2(historyRT.referenceSize.x * historyRT.scaleFactor.x,
historyRT.referenceSize.y * historyRT.scaleFactor.y);
var rtScaleForHistory = hdCamera.historyRTHandleProperties.rtHandleScale;
var aoParameters = PrepareRenderAOParameters(hdCamera, historySize * rtScaleForHistory, depthMipInfo);
var packedData = RenderAO(renderGraph, aoParameters, depthBuffer, normalBuffer);
result = DenoiseAO(renderGraph, aoParameters, depthBuffer, motionVectors, packedData, currentHistory, outputHistory);
result = UpsampleAO(renderGraph, aoParameters, result, depthBuffer);
}
}
}
else
{
result = renderGraph.defaultResources.blackTextureXR;
}
return result;
}
class RenderAOPassData
{
public RenderAOParameters parameters;
public TextureHandle packedData;
public TextureHandle depthPyramid;
public TextureHandle normalBuffer;
}
TextureHandle RenderAO(RenderGraph renderGraph, in RenderAOParameters parameters, TextureHandle depthPyramid, TextureHandle normalBuffer)
{
using (var builder = renderGraph.AddRenderPass<RenderAOPassData>("GTAO Horizon search and integration", out var passData, ProfilingSampler.Get(HDProfileId.HorizonSSAO)))
{
builder.EnableAsyncCompute(parameters.runAsync);
float scaleFactor = parameters.fullResolution ? 1.0f : 0.5f;
passData.parameters = parameters;
passData.packedData = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one * scaleFactor, true, true)
{ colorFormat = GraphicsFormat.R32_SFloat, enableRandomWrite = true, name = "AO Packed data" }));
passData.depthPyramid = builder.ReadTexture(depthPyramid);
passData.normalBuffer = builder.ReadTexture(normalBuffer);
builder.SetRenderFunc(
(RenderAOPassData data, RenderGraphContext ctx) =>
{
RenderAO(data.parameters, data.packedData, data.depthPyramid, data.normalBuffer, ctx.cmd);
});
return passData.packedData;
}
}
class DenoiseAOPassData
{
public RenderAOParameters parameters;
public TextureHandle packedData;
public TextureHandle packedDataBlurred;
public TextureHandle currentHistory;
public TextureHandle outputHistory;
public TextureHandle denoiseOutput;
public TextureHandle motionVectors;
}
TextureHandle DenoiseAO(RenderGraph renderGraph,
in RenderAOParameters parameters,
TextureHandle depthTexture,
TextureHandle motionVectors,
TextureHandle aoPackedData,
TextureHandle currentHistory,
TextureHandle outputHistory)
{
if (!parameters.temporalAccumulation && !parameters.fullResolution)
return aoPackedData;
TextureHandle denoiseOutput;
using (var builder = renderGraph.AddRenderPass<DenoiseAOPassData>("Denoise GTAO", out var passData))
{
builder.EnableAsyncCompute(parameters.runAsync);
float scaleFactor = parameters.fullResolution ? 1.0f : 0.5f;
passData.parameters = parameters;
passData.packedData = builder.ReadTexture(aoPackedData);
if (parameters.temporalAccumulation)
{
passData.motionVectors = builder.ReadTexture(motionVectors);
passData.currentHistory = builder.ReadTexture(currentHistory); // can also be written on first frame, but since it's an imported resource, it doesn't matter in term of lifetime.
passData.outputHistory = builder.WriteTexture(outputHistory);
}
passData.packedDataBlurred = builder.CreateTransientTexture(
new TextureDesc(Vector2.one * scaleFactor, true, true) { colorFormat = GraphicsFormat.R32_SFloat, enableRandomWrite = true, name = "AO Packed blurred data" });
if (parameters.fullResolution)
passData.denoiseOutput = builder.WriteTexture(CreateAmbientOcclusionTexture(renderGraph));
else
passData.denoiseOutput = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one * 0.5f, true, true) { enableRandomWrite = true, colorFormat = GraphicsFormat.R32_SFloat, name = "Final Half Res AO Packed" }));
denoiseOutput = passData.denoiseOutput;
builder.SetRenderFunc(
(DenoiseAOPassData data, RenderGraphContext ctx) =>
{
DenoiseAO(data.parameters,
data.packedData,
data.packedDataBlurred,
data.currentHistory,
data.outputHistory,
data.motionVectors,
data.denoiseOutput,
ctx.cmd);
});
return passData.denoiseOutput;
}
}
class UpsampleAOPassData
{
public RenderAOParameters parameters;
public TextureHandle depthTexture;
public TextureHandle input;
public TextureHandle output;
}
TextureHandle UpsampleAO(RenderGraph renderGraph, in RenderAOParameters parameters, TextureHandle input, TextureHandle depthTexture)
{
if (parameters.fullResolution)
return input;
using (var builder = renderGraph.AddRenderPass<UpsampleAOPassData>("Upsample GTAO", out var passData, ProfilingSampler.Get(HDProfileId.UpSampleSSAO)))
{
builder.EnableAsyncCompute(parameters.runAsync);
passData.parameters = parameters;
passData.input = builder.ReadTexture(input);
passData.depthTexture = builder.ReadTexture(depthTexture);
passData.output = builder.WriteTexture(CreateAmbientOcclusionTexture(renderGraph));
builder.SetRenderFunc(
(UpsampleAOPassData data, RenderGraphContext ctx) =>
{
UpsampleAO(data.parameters, data.depthTexture, data.input, data.output, ctx.cmd);
});
return passData.output;
}
}
}
}