using FidelityFX; using UnityEngine.Experimental.Rendering; using UnityEngine.Rendering.RenderGraphModule; namespace UnityEngine.Rendering.HighDefinition { public partial class HDRenderPipeline { private CacaoContext m_CacaoContext; class RenderCacaoParameters { public bool runAsync; public Vector2Int resolution; public bool downsample; public Cacao.Settings settings = Cacao.DefaultSettings; public Matrix4x4 projectionMatrix; public Matrix4x4 cameraToWorldMatrix; } class RenderCacaoPassData { public TextureHandle depthBuffer; public TextureHandle normalBuffer; public Matrix4x4 projectionMatrix; public Matrix4x4 normalsToView; public TextureHandle aoOutput; } TextureHandle RenderCacao(RenderGraph renderGraph, in RenderCacaoParameters parameters, TextureHandle depthBuffer, TextureHandle normalBuffer) { if (m_CacaoContext == null) { m_CacaoContext = new CacaoContext(); m_CacaoContext.Init(new CacaoShaders { prepareDepths = runtimeShaders.cacaoPrepareDepths, prepareNormals = runtimeShaders.cacaoPrepareNormals, generateImportanceMap = runtimeShaders.cacaoGenerateImportanceMap, generateSsao = runtimeShaders.cacaoGenerateSsao, edgeSensitiveBlur = runtimeShaders.cacaoEdgeSensitiveBlur, bilateralUpscale = runtimeShaders.cacaoBilateralUpscale, reinterleave = runtimeShaders.cacaoReinterleave, }); m_CacaoContext.InitScreenSizeDependentResources(new Cacao.ScreenSizeInfo { Width = (uint)parameters.resolution.x, Height = (uint)parameters.resolution.y, UseDownsampledSsao = parameters.downsample, }); } // TODO: init m_CacaoContext with data from parameters // TODO: detect changes in parameters and reinit m_CacaoContext if necessary m_CacaoContext.UpdateSettings(parameters.settings); using (var builder = renderGraph.AddRenderPass("FidelityFX CACAO", out var passData, ProfilingSampler.Get(HDProfileId.AmbientOcclusion))) { builder.EnableAsyncCompute(parameters.runAsync); passData.aoOutput = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true) { colorFormat = GraphicsFormat.R32_SFloat, enableRandomWrite = true, name = "CACAO Output" })); passData.depthBuffer = depthBuffer; passData.normalBuffer = normalBuffer; passData.projectionMatrix = parameters.projectionMatrix; passData.normalsToView = parameters.cameraToWorldMatrix * Cacao.UnityToCacaoViewMatrix; builder.SetRenderFunc((RenderCacaoPassData data, RenderGraphContext ctx) => { var dispatchInfo = new Cacao.DispatchInfo { DepthView = new Cacao.ResourceView(data.depthBuffer), NormalsView = new Cacao.ResourceView(data.normalBuffer), OutputView = new Cacao.ResourceView(data.aoOutput), }; ctx.cmd.SetGlobalTexture("_CameraDepthTexture", data.depthBuffer); ctx.cmd.SetGlobalTexture("_NormalBufferTexture", data.normalBuffer); ctx.cmd.SetGlobalTexture("_OcclusionTexture", data.aoOutput); m_CacaoContext.Draw(ctx.cmd, dispatchInfo, data.projectionMatrix, data.normalsToView); }); return passData.aoOutput; } } // TODO: clean up CacaoContext in some kind of cleanup method (called from where?) } }