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); } }
void RenderSSGI(HDCamera hdCamera, CommandBuffer cmd, ScriptableRenderContext renderContext, int frameCount) { // Grab the global illumination volume component GlobalIllumination giSettings = hdCamera.volumeStack.GetComponent <GlobalIllumination>(); // Based on if we are doing it in half resolution or full, we need to define initial and final buffer to avoid a useless blit RTHandle buffer0, buffer1; if (giSettings.fullResolutionSS) { buffer0 = m_IndirectDiffuseBuffer0; buffer1 = m_IndirectDiffuseBuffer1; } else { buffer0 = m_IndirectDiffuseBuffer1; buffer1 = m_IndirectDiffuseBuffer0; } using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.SSGIPass))) { // Trace the signal using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.SSGITrace))) { SSGITraceParameters parameters = PrepareSSGITraceParameters(hdCamera, giSettings); SSGITraceResources resources = PrepareSSGITraceResources(hdCamera, buffer0, m_IndirectDiffuseHitPointBuffer); ExecuteSSGITrace(cmd, parameters, resources); } // Denoise it using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.SSGIDenoise))) { float historyValidity = EvaluateHistoryValidity(hdCamera); SSGIDenoiser ssgiDenoiser = GetSSGIDenoiser(); ssgiDenoiser.Denoise(cmd, hdCamera, buffer0, buffer1, halfResolution: !giSettings.fullResolutionSS, historyValidity: historyValidity); } // Upscale it if required // If this was a half resolution effect, we still have to upscale it if (!giSettings.fullResolutionSS) { using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.SSGIUpscale))) { ComputeShader bilateralUpsampleCS = m_Asset.renderPipelineResources.shaders.bilateralUpsampleCS; SSGIUpscaleParameters parameters = PrepareSSGIUpscaleParameters(hdCamera, giSettings); SSGIUpscaleResources resources = PrepareSSGIUpscaleResources(hdCamera, buffer0, buffer1); ExecuteSSGIUpscale(cmd, parameters, resources); } } (RenderPipelineManager.currentPipeline as HDRenderPipeline).PushFullScreenDebugTexture(hdCamera, cmd, m_IndirectDiffuseBuffer0, FullScreenDebugMode.ScreenSpaceGlobalIllumination); } }
SSGITraceResources PrepareSSGITraceResources(HDCamera hdCamera, RTHandle outputBuffer, RTHandle hitPointBuffer) { SSGITraceResources ssgiTraceResources = new SSGITraceResources(); // Input buffers ssgiTraceResources.depthTexture = m_SharedRTManager.GetDepthTexture(); ssgiTraceResources.normalBuffer = m_SharedRTManager.GetNormalBuffer(); ssgiTraceResources.motionVectorsBuffer = m_SharedRTManager.GetMotionVectorsBuffer(); var previousColorPyramid = hdCamera.GetPreviousFrameRT((int)HDCameraFrameHistoryType.ColorBufferMipChain); ssgiTraceResources.colorPyramid = previousColorPyramid != null ? previousColorPyramid : TextureXR.GetBlackTexture(); var historyDepthBuffer = hdCamera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.Depth); ssgiTraceResources.historyDepth = historyDepthBuffer != null ? historyDepthBuffer : TextureXR.GetBlackTexture(); // Output buffers ssgiTraceResources.hitPointBuffer = hitPointBuffer; // Output buffers ssgiTraceResources.outputBuffer = outputBuffer; return(ssgiTraceResources); }
static void ExecuteSSGITrace(CommandBuffer cmd, SSGITraceParameters parameters, SSGITraceResources resources) { int ssgiTileSize = 8; int numTilesXHR = (parameters.texWidth + (ssgiTileSize - 1)) / ssgiTileSize; int numTilesYHR = (parameters.texHeight + (ssgiTileSize - 1)) / ssgiTileSize; // Inject all the input scalars float n = parameters.nearClipPlane; float f = parameters.farClipPlane; float thicknessScale = 1.0f / (1.0f + parameters.thickness); float thicknessBias = -n / (f - n) * (parameters.thickness * thicknessScale); cmd.SetComputeFloatParam(parameters.ssGICS, HDShaderIDs._IndirectDiffuseThicknessScale, thicknessScale); cmd.SetComputeFloatParam(parameters.ssGICS, HDShaderIDs._IndirectDiffuseThicknessBias, thicknessBias); cmd.SetComputeIntParam(parameters.ssGICS, HDShaderIDs._IndirectDiffuseSteps, parameters.raySteps); // Inject half screen size if required if (!parameters.fullResolutionSS) { cmd.SetComputeVectorParam(parameters.ssGICS, HDShaderIDs._HalfScreenSize, parameters.halfScreenSize); } // Inject the ray-tracing sampling data BlueNoise.BindDitheredTextureSet(cmd, parameters.ditheredTextureSet); // Inject all the input textures/buffers cmd.SetComputeTextureParam(parameters.ssGICS, parameters.traceKernel, HDShaderIDs._DepthTexture, resources.depthTexture); cmd.SetComputeTextureParam(parameters.ssGICS, parameters.traceKernel, HDShaderIDs._NormalBufferTexture, resources.normalBuffer); cmd.SetComputeTextureParam(parameters.ssGICS, parameters.traceKernel, HDShaderIDs._IndirectDiffuseHitPointTextureRW, resources.hitPointBuffer); cmd.SetComputeBufferParam(parameters.ssGICS, parameters.traceKernel, HDShaderIDs._DepthPyramidMipLevelOffsets, parameters.offsetBuffer); // Do the ray marching cmd.DispatchCompute(parameters.ssGICS, parameters.traceKernel, numTilesXHR, numTilesYHR, parameters.viewCount); // Update global constant buffer. // This should probably be a shader specific uniform instead of reusing the global constant buffer one since it's the only one updated here. ConstantBuffer.PushGlobal(cmd, parameters.shaderVariablesRayTracingCB, HDShaderIDs._ShaderVariablesRaytracing); // Inject all the input scalars cmd.SetComputeVectorParam(parameters.ssGICS, HDShaderIDs._ColorPyramidUvScaleAndLimitPrevFrame, parameters.colorPyramidUvScaleAndLimitPrevFrame); // Bind all the input buffers cmd.SetComputeTextureParam(parameters.ssGICS, parameters.projectKernel, HDShaderIDs._DepthTexture, resources.depthTexture); cmd.SetComputeTextureParam(parameters.ssGICS, parameters.projectKernel, HDShaderIDs._NormalBufferTexture, resources.normalBuffer); cmd.SetComputeTextureParam(parameters.ssGICS, parameters.projectKernel, HDShaderIDs._CameraMotionVectorsTexture, resources.motionVectorsBuffer); cmd.SetComputeTextureParam(parameters.ssGICS, parameters.projectKernel, HDShaderIDs._IndirectDiffuseHitPointTexture, resources.hitPointBuffer); cmd.SetComputeTextureParam(parameters.ssGICS, parameters.projectKernel, HDShaderIDs._ColorPyramidTexture, resources.colorPyramid); cmd.SetComputeTextureParam(parameters.ssGICS, parameters.projectKernel, HDShaderIDs._HistoryDepthTexture, resources.historyDepth); cmd.SetComputeBufferParam(parameters.ssGICS, parameters.projectKernel, HDShaderIDs._DepthPyramidMipLevelOffsets, parameters.offsetBuffer); // Bind the output texture cmd.SetComputeTextureParam(parameters.ssGICS, parameters.projectKernel, HDShaderIDs._IndirectDiffuseTexture0RW, resources.outputBuffer0); cmd.SetComputeTextureParam(parameters.ssGICS, parameters.projectKernel, HDShaderIDs._IndirectDiffuseTexture1RW, resources.outputBuffer1); // Do the reprojection cmd.DispatchCompute(parameters.ssGICS, parameters.projectKernel, numTilesXHR, numTilesYHR, parameters.viewCount); }