HDShadowData CreateShadowData(HDShadowRequest shadowRequest, HDShadowAtlas atlas) { HDShadowData data = new HDShadowData(); var devProj = shadowRequest.deviceProjection; var view = shadowRequest.view; data.proj = new Vector4(devProj.m00, devProj.m11, devProj.m22, devProj.m23); data.pos = shadowRequest.position; data.rot0 = new Vector3(view.m00, view.m01, view.m02); data.rot1 = new Vector3(view.m10, view.m11, view.m12); data.rot2 = new Vector3(view.m20, view.m21, view.m22); data.shadowToWorld = shadowRequest.shadowToWorld; data.cacheTranslationDelta = new Vector3(0.0f, 0.0f, 0.0f); // Compute the scale and offset (between 0 and 1) for the atlas coordinates float rWidth = 1.0f / atlas.width; float rHeight = 1.0f / atlas.height; data.atlasOffset = Vector2.Scale(new Vector2(rWidth, rHeight), new Vector2(shadowRequest.atlasViewport.x, shadowRequest.atlasViewport.y)); data.shadowMapSize = new Vector4(shadowRequest.atlasViewport.width, shadowRequest.atlasViewport.height, 1.0f / shadowRequest.atlasViewport.width, 1.0f / shadowRequest.atlasViewport.height); data.normalBias = shadowRequest.normalBias; data.worldTexelSize = shadowRequest.worldTexelSize; data.shadowFilterParams0.x = shadowRequest.shadowSoftness; data.shadowFilterParams0.y = HDShadowUtils.Asfloat(shadowRequest.blockerSampleCount); data.shadowFilterParams0.z = HDShadowUtils.Asfloat(shadowRequest.filterSampleCount); data.shadowFilterParams0.w = shadowRequest.minFilterSize; data.zBufferParam = shadowRequest.zBufferParam; if (atlas.HasBlurredEVSM()) { data.shadowFilterParams0 = shadowRequest.evsmParams; } return(data); }
void BuildLightCluster(HDCamera hdCamera, CommandBuffer cmd) { using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.RaytracingBuildCluster))) { // Grab the kernel ComputeShader lightClusterCS = m_RenderPipelineRayTracingResources.lightClusterBuildCS; int lightClusterKernel = lightClusterCS.FindKernel(m_LightClusterKernelName); // Inject all the parameters cmd.SetComputeBufferParam(lightClusterCS, lightClusterKernel, HDShaderIDs._RaytracingLightClusterRW, m_LightCluster); cmd.SetComputeVectorParam(lightClusterCS, _ClusterCellSize, clusterCellSize); cmd.SetComputeBufferParam(lightClusterCS, lightClusterKernel, _LightVolumes, m_LightVolumeGPUArray); cmd.SetComputeFloatParam(lightClusterCS, _LightVolumeCount, HDShadowUtils.Asfloat(totalLightCount)); cmd.SetComputeBufferParam(lightClusterCS, lightClusterKernel, _RaytracingLightCullResult, m_LightCullResult); // Dispatch a compute int numGroupsX = 8; int numGroupsY = 8; int numGroupsZ = 4; cmd.DispatchCompute(lightClusterCS, lightClusterKernel, numGroupsX, numGroupsY, numGroupsZ); } }
void BuildLightCluster(HDCamera hdCamera, CommandBuffer cmd) { using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.RaytracingBuildCluster))) { var lightClusterSettings = hdCamera.volumeStack.GetComponent <LightCluster>(); numLightsPerCell = lightClusterSettings.maxNumLightsPercell.value; // Make sure the Cluster buffer has the right size int bufferSize = 64 * 64 * 32 * (numLightsPerCell + 4); if (m_LightCluster.count != bufferSize) { ResizeClusterBuffer(bufferSize); } // Grab the kernel ComputeShader lightClusterCS = m_RenderPipelineRayTracingResources.lightClusterBuildCS; int lightClusterKernel = lightClusterCS.FindKernel(m_LightClusterKernelName); // Inject all the parameters cmd.SetComputeBufferParam(lightClusterCS, lightClusterKernel, HDShaderIDs._RaytracingLightCluster, m_LightCluster); cmd.SetComputeVectorParam(lightClusterCS, HDShaderIDs._MinClusterPos, minClusterPos); cmd.SetComputeVectorParam(lightClusterCS, HDShaderIDs._MaxClusterPos, maxClusterPos); cmd.SetComputeVectorParam(lightClusterCS, _ClusterCellSize, clusterCellSize); cmd.SetComputeFloatParam(lightClusterCS, HDShaderIDs._LightPerCellCount, HDShadowUtils.Asfloat(numLightsPerCell)); cmd.SetComputeBufferParam(lightClusterCS, lightClusterKernel, _LightVolumes, m_LightVolumeGPUArray); cmd.SetComputeFloatParam(lightClusterCS, _LightVolumeCount, HDShadowUtils.Asfloat(totalLightCount)); cmd.SetComputeBufferParam(lightClusterCS, lightClusterKernel, _RaytracingLightCullResult, m_LightCullResult); // Dispatch a compute int numGroupsX = 8; int numGroupsY = 8; int numGroupsZ = 4; cmd.DispatchCompute(lightClusterCS, lightClusterKernel, numGroupsX, numGroupsY, numGroupsZ); } }
SSGIUpscaleParameters PrepareSSGIUpscaleParameters(HDCamera hdCamera, GlobalIllumination settings) { SSGIUpscaleParameters parameters = new SSGIUpscaleParameters(); // Set the camera parameters parameters.texWidth = hdCamera.actualWidth; parameters.texHeight = hdCamera.actualHeight; parameters.viewCount = hdCamera.viewCount; parameters.halfScreenSize.Set(parameters.texWidth / 2, parameters.texHeight / 2, 1.0f / (parameters.texWidth * 0.5f), 1.0f / (parameters.texHeight * 0.5f)); // Set the generation parameters var info = m_SharedRTManager.GetDepthBufferMipChainInfo(); parameters.firstMipOffset.Set(HDShadowUtils.Asfloat((uint)info.mipLevelOffsets[1].x), HDShadowUtils.Asfloat((uint)info.mipLevelOffsets[1].y)); // Grab the right kernel parameters.bilateralUpsampleCS = m_Asset.renderPipelineResources.shaders.bilateralUpsampleCS; parameters.upscaleKernel = m_BilateralUpSampleColorKernel; return(parameters); }
SSGIDenoiserParameters PrepareSSGIDenoiserParameters(HDCamera hdCamera, bool halfResolution, float historyValidity, bool historyNeedsClear, HDUtils.PackedMipChainInfo depthMipInfo) { var giSettings = hdCamera.volumeStack.GetComponent <UnityEngine.Rendering.HighDefinition.GlobalIllumination>(); SSGIDenoiserParameters parameters = new SSGIDenoiserParameters(); // Compute the dispatch parameters based on if we are half res or not int tileSize = 8; EvaluateDispatchParameters(hdCamera, halfResolution, tileSize, out parameters.numTilesX, out parameters.numTilesY, out parameters.halfScreenSize); parameters.firstMipOffset.Set(HDShadowUtils.Asfloat((uint)depthMipInfo.mipLevelOffsets[1].x), HDShadowUtils.Asfloat((uint)depthMipInfo.mipLevelOffsets[1].y)); parameters.historyValidity = historyValidity; parameters.viewCount = hdCamera.viewCount; // Denoising parameters parameters.filterRadius = giSettings.filterRadius; parameters.halfResolution = halfResolution; parameters.historyValidity = historyValidity; parameters.historyNeedsClear = historyNeedsClear; // Compute shader parameters.ssgiDenoiserCS = m_SSGIDenoiserCS; // Kernels parameters.spatialFilterKernel = halfResolution ? m_SpatialFilterHalfKernel : m_SpatialFilterKernel; parameters.temporalFilterKernel = halfResolution ? m_TemporalFilterHalfKernel : m_TemporalFilterKernel; parameters.copyHistory = m_CopyHistory; return(parameters); }
void BuildLightCluster(CommandBuffer cmd, ComputeShader lightClusterCS, HDRaytracingEnvironment currentEnv) { using (new ProfilingSample(cmd, "Build Light Cluster", CustomSamplerId.RaytracingBuildCluster.GetSampler())) { var lightClusterSettings = VolumeManager.instance.stack.GetComponent <LightCluster>(); numLightsPerCell = lightClusterSettings.maxNumLightsPercell.value; // Make sure the Cluster buffer has the right size int bufferSize = 64 * 64 * 32 * (numLightsPerCell + 4); if (m_LightCluster.count != bufferSize) { ResizeClusterBuffer(bufferSize); } // Grab the kernel int lightClusterKernel = lightClusterCS.FindKernel(m_LightClusterKernelName); // Inject all the parameters cmd.SetComputeBufferParam(lightClusterCS, lightClusterKernel, HDShaderIDs._RaytracingLightCluster, m_LightCluster); cmd.SetComputeVectorParam(lightClusterCS, HDShaderIDs._MinClusterPos, minClusterPos); cmd.SetComputeVectorParam(lightClusterCS, HDShaderIDs._MaxClusterPos, maxClusterPos); cmd.SetComputeVectorParam(lightClusterCS, _ClusterCellSize, clusterCellSize); cmd.SetComputeFloatParam(lightClusterCS, HDShaderIDs._LightPerCellCount, HDShadowUtils.Asfloat(numLightsPerCell)); cmd.SetComputeBufferParam(lightClusterCS, lightClusterKernel, _LightVolumes, m_LightVolumeGPUArray); cmd.SetComputeFloatParam(lightClusterCS, _LightVolumeCount, HDShadowUtils.Asfloat(totalLightCount)); cmd.SetComputeBufferParam(lightClusterCS, lightClusterKernel, _RaytracingLightCullResult, m_LightCullResult); // Dispatch a compute int numGroupsX = 8; int numGroupsY = 8; int numGroupsZ = 4; cmd.DispatchCompute(lightClusterCS, lightClusterKernel, numGroupsX, numGroupsY, numGroupsZ); } }
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); // Set the camera parameters passData.texWidth = hdCamera.actualWidth; passData.texHeight = hdCamera.actualHeight; passData.viewCount = hdCamera.viewCount; passData.halfScreenSize.Set(passData.texWidth / 2, passData.texHeight / 2, 1.0f / (passData.texWidth * 0.5f), 1.0f / (passData.texHeight * 0.5f)); // Set the generation parameters passData.firstMipOffset.Set(HDShadowUtils.Asfloat((uint)info.mipLevelOffsets[1].x), HDShadowUtils.Asfloat((uint)info.mipLevelOffsets[1].y)); // Grab the right kernel passData.bilateralUpsampleCS = m_Asset.renderPipelineResources.shaders.bilateralUpsampleCS; passData.upscaleKernel = m_BilateralUpSampleColorKernel; 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) => { // Re-evaluate the dispatch parameters (we are evaluating the upsample in full resolution) int ssgiTileSize = 8; int numTilesXHR = (data.texWidth + (ssgiTileSize - 1)) / ssgiTileSize; int numTilesYHR = (data.texHeight + (ssgiTileSize - 1)) / ssgiTileSize; // Inject the input scalars ctx.cmd.SetComputeVectorParam(data.bilateralUpsampleCS, HDShaderIDs._HalfScreenSize, data.halfScreenSize); ctx.cmd.SetComputeVectorParam(data.bilateralUpsampleCS, HDShaderIDs._DepthPyramidFirstMipLevelOffset, data.firstMipOffset); // Inject all the input buffers ctx.cmd.SetComputeTextureParam(data.bilateralUpsampleCS, data.upscaleKernel, HDShaderIDs._DepthTexture, data.depthTexture); ctx.cmd.SetComputeTextureParam(data.bilateralUpsampleCS, data.upscaleKernel, HDShaderIDs._LowResolutionTexture, data.inputBuffer); // Inject the output textures ctx.cmd.SetComputeTextureParam(data.bilateralUpsampleCS, data.upscaleKernel, HDShaderIDs._OutputUpscaledTexture, data.outputBuffer); // Upscale the buffer to full resolution ctx.cmd.DispatchCompute(data.bilateralUpsampleCS, data.upscaleKernel, numTilesXHR, numTilesYHR, data.viewCount); }); return(passData.outputBuffer); } }
public SSGIDenoiserOutput Denoise(RenderGraph renderGraph, HDCamera hdCamera, TextureHandle depthPyramid, TextureHandle normalBuffer, TextureHandle motionVectorsBuffer, TextureHandle inputBuffer0, TextureHandle inputBuffer1, HDUtils.PackedMipChainInfo depthMipInfo, bool halfResolution = false, float historyValidity = 1.0f) { using (var builder = renderGraph.AddRenderPass <DenoiseSSGIPassData>("Denoise SSGI", out var passData, ProfilingSampler.Get(HDProfileId.SSGIDenoise))) { builder.EnableAsyncCompute(false); // Prepass buffers passData.depthTexture = builder.ReadTexture(depthPyramid); passData.normalBuffer = builder.ReadTexture(normalBuffer); passData.motionVectorsBuffer = builder.ReadTexture(motionVectorsBuffer); // History buffers bool historyRequireClear = false; RTHandle indirectDiffuseHistory0 = RequestIndirectDiffuseHistory0(hdCamera, out historyRequireClear); passData.indirectDiffuseHistory0 = builder.ReadWriteTexture(renderGraph.ImportTexture(indirectDiffuseHistory0)); RTHandle indirectDiffuseHistory1 = RequestIndirectDiffuseHistory1(hdCamera, out historyRequireClear); passData.indirectDiffuseHistory1 = builder.ReadWriteTexture(renderGraph.ImportTexture(indirectDiffuseHistory1)); var historyDepthBuffer = halfResolution ? hdCamera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.Depth1) : hdCamera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.Depth); passData.historyDepthBuffer = historyDepthBuffer != null?builder.ReadTexture(renderGraph.ImportTexture(historyDepthBuffer)) : renderGraph.defaultResources.blackTextureXR; // Input buffers passData.inputBuffer0 = builder.ReadTexture(inputBuffer0); passData.inputBuffer1 = builder.ReadTexture(inputBuffer1); // Output buffers passData.outputBuffer0 = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true) { colorFormat = GraphicsFormat.B10G11R11_UFloatPack32, enableRandomWrite = true, name = "SSGI Denoised 0" })); passData.outputBuffer1 = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true) { colorFormat = GraphicsFormat.R16G16_SFloat, enableRandomWrite = true, name = "SSGI Denoised 1" })); // Parameters var giSettings = hdCamera.volumeStack.GetComponent <UnityEngine.Rendering.HighDefinition.GlobalIllumination>(); // Compute the dispatch parameters based on if we are half res or not int tileSize = 8; EvaluateDispatchParameters(hdCamera, halfResolution, tileSize, out passData.numTilesX, out passData.numTilesY, out passData.halfScreenSize); passData.firstMipOffset.Set(HDShadowUtils.Asfloat((uint)depthMipInfo.mipLevelOffsets[1].x), HDShadowUtils.Asfloat((uint)depthMipInfo.mipLevelOffsets[1].y)); passData.historyValidity = historyValidity; passData.viewCount = hdCamera.viewCount; passData.pixelSpreadTangent = HDRenderPipeline.GetPixelSpreadTangent(hdCamera.camera.fieldOfView, hdCamera.actualWidth, hdCamera.actualHeight); // Denoising parameters passData.filterRadius = giSettings.filterRadius; passData.halfResolution = halfResolution; passData.historyValidity = historyValidity; passData.historyNeedsClear = historyRequireClear; passData.exclusiveMode = !hdCamera.frameSettings.IsEnabled(FrameSettingsField.ProbeVolume); // Compute shader passData.ssgiDenoiserCS = m_SSGIDenoiserCS; // Kernels passData.spatialFilterKernel = halfResolution ? m_SpatialFilterHalfKernel : m_SpatialFilterKernel; passData.temporalFilterKernel = halfResolution ? m_TemporalFilterHalfKernel : m_TemporalFilterKernel; passData.copyHistory = m_CopyHistory; builder.SetRenderFunc( (DenoiseSSGIPassData data, RenderGraphContext ctx) => { int effectiveRadius = data.exclusiveMode ? data.filterRadius / 2 : data.filterRadius; if (data.exclusiveMode) { // Horizontal Filter SpatialFilter(ctx.cmd, data, effectiveRadius, new Vector2(1.0f, 0.0f), data.inputBuffer0, data.inputBuffer1, data.outputBuffer0, data.outputBuffer1); // Vertical Filter SpatialFilter(ctx.cmd, data, effectiveRadius, new Vector2(0.0f, 1.0f), data.outputBuffer0, data.outputBuffer1, data.inputBuffer0, data.inputBuffer1); } // Grab the history buffer if (data.historyNeedsClear) { // clear it to black if this is the first pass to avoid nans CoreUtils.SetRenderTarget(ctx.cmd, data.indirectDiffuseHistory0, ClearFlag.Color, Color.black); CoreUtils.SetRenderTarget(ctx.cmd, data.indirectDiffuseHistory1, ClearFlag.Color, Color.black); } // Bind the input buffers ctx.cmd.SetComputeTextureParam(data.ssgiDenoiserCS, data.temporalFilterKernel, HDShaderIDs._DepthTexture, data.depthTexture); ctx.cmd.SetComputeTextureParam(data.ssgiDenoiserCS, data.temporalFilterKernel, HDShaderIDs._NormalBufferTexture, data.normalBuffer); ctx.cmd.SetComputeTextureParam(data.ssgiDenoiserCS, data.temporalFilterKernel, HDShaderIDs._CameraMotionVectorsTexture, data.motionVectorsBuffer); ctx.cmd.SetComputeFloatParam(data.ssgiDenoiserCS, HDShaderIDs._HistoryValidity, data.historyValidity); if (data.halfResolution) { ctx.cmd.SetComputeTextureParam(data.ssgiDenoiserCS, data.temporalFilterKernel, HDShaderIDs._HistoryDepthTexture, data.historyDepthBuffer); ctx.cmd.SetComputeVectorParam(data.ssgiDenoiserCS, HDShaderIDs._DepthPyramidFirstMipLevelOffset, data.firstMipOffset); } else { ctx.cmd.SetComputeTextureParam(data.ssgiDenoiserCS, data.temporalFilterKernel, HDShaderIDs._HistoryDepthTexture, data.historyDepthBuffer); } ctx.cmd.SetComputeTextureParam(data.ssgiDenoiserCS, data.temporalFilterKernel, HDShaderIDs._HistoryBuffer0, data.indirectDiffuseHistory0); ctx.cmd.SetComputeTextureParam(data.ssgiDenoiserCS, data.temporalFilterKernel, HDShaderIDs._HistoryBuffer1, data.indirectDiffuseHistory1); ctx.cmd.SetComputeTextureParam(data.ssgiDenoiserCS, data.temporalFilterKernel, HDShaderIDs._InputNoisyBuffer0, data.inputBuffer0); ctx.cmd.SetComputeTextureParam(data.ssgiDenoiserCS, data.temporalFilterKernel, HDShaderIDs._InputNoisyBuffer1, data.inputBuffer1); // Bind the output buffer ctx.cmd.SetComputeTextureParam(data.ssgiDenoiserCS, data.temporalFilterKernel, HDShaderIDs._OutputFilteredBuffer0, data.outputBuffer0); ctx.cmd.SetComputeTextureParam(data.ssgiDenoiserCS, data.temporalFilterKernel, HDShaderIDs._OutputFilteredBuffer1, data.outputBuffer1); // Do the temporal pass ctx.cmd.DispatchCompute(data.ssgiDenoiserCS, data.temporalFilterKernel, data.numTilesX, data.numTilesY, data.viewCount); // Copy the new version into the history buffer ctx.cmd.SetComputeTextureParam(data.ssgiDenoiserCS, data.copyHistory, HDShaderIDs._InputNoisyBuffer0, data.outputBuffer0); ctx.cmd.SetComputeTextureParam(data.ssgiDenoiserCS, data.copyHistory, HDShaderIDs._InputNoisyBuffer1, data.outputBuffer1); ctx.cmd.SetComputeTextureParam(data.ssgiDenoiserCS, data.copyHistory, HDShaderIDs._OutputFilteredBuffer0, data.indirectDiffuseHistory0); ctx.cmd.SetComputeTextureParam(data.ssgiDenoiserCS, data.copyHistory, HDShaderIDs._OutputFilteredBuffer1, data.indirectDiffuseHistory1); ctx.cmd.DispatchCompute(data.ssgiDenoiserCS, data.copyHistory, data.numTilesX, data.numTilesY, data.viewCount); // Horizontal Filter SpatialFilter(ctx.cmd, data, effectiveRadius, new Vector2(1.0f, 0.0f), data.outputBuffer0, data.outputBuffer1, data.inputBuffer0, data.inputBuffer1); // Vertical Filter SpatialFilter(ctx.cmd, data, effectiveRadius, new Vector2(0.0f, 1.0f), data.inputBuffer0, data.inputBuffer1, data.outputBuffer0, data.outputBuffer1); }); SSGIDenoiserOutput denoiserOutput = new SSGIDenoiserOutput(); denoiserOutput.outputBuffer0 = passData.outputBuffer0; denoiserOutput.outputBuffer1 = passData.outputBuffer1; return(denoiserOutput); } }
public void Denoise(CommandBuffer cmd, HDCamera hdCamera, RTHandle noisyBuffer, RTHandle outputBuffer, bool halfResolution = false, float historyValidity = 1.0f) { // Grab the global illumination volume component var giSettings = hdCamera.volumeStack.GetComponent <UnityEngine.Rendering.HighDefinition.GlobalIllumination>(); var historyDepthBuffer = hdCamera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.Depth); var historyDepthBuffer1 = hdCamera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.Depth1); // If the depth textures are not available, we can't denoise if (historyDepthBuffer == null || historyDepthBuffer1 == null) { HDUtils.BlitCameraTexture(cmd, noisyBuffer, outputBuffer); return; } // Compute the dispatch parameters based on if we are half res or not int tileSize = 8; int numTilesX, numTilesY; Vector4 halfScreenSize; EvaluateDispatchParameters(hdCamera, halfResolution, tileSize, out numTilesX, out numTilesY, out halfScreenSize); // Pick the right kernel to use int m_KernelFilter = halfResolution ? m_SpatialFilterHalfKernel : m_SpatialFilterKernel; // Bind the input scalars var info = m_SharedRTManager.GetDepthBufferMipChainInfo(); firstMipOffset.Set(HDShadowUtils.Asfloat((uint)info.mipLevelOffsets[1].x), HDShadowUtils.Asfloat((uint)info.mipLevelOffsets[1].y)); cmd.SetComputeVectorParam(m_SSGIDenoiserCS, HDShaderIDs._DepthPyramidFirstMipLevelOffset, firstMipOffset); cmd.SetComputeIntParam(m_SSGIDenoiserCS, HDShaderIDs._IndirectDiffuseSpatialFilter, giSettings.filterRadius); // Inject half screen size if required if (halfResolution) { cmd.SetComputeVectorParam(m_SSGIDenoiserCS, HDShaderIDs._HalfScreenSize, halfScreenSize); } // Bind the input buffers cmd.SetComputeTextureParam(m_SSGIDenoiserCS, m_KernelFilter, HDShaderIDs._DepthTexture, m_SharedRTManager.GetDepthTexture()); cmd.SetComputeTextureParam(m_SSGIDenoiserCS, m_KernelFilter, HDShaderIDs._InputNoisyBuffer, noisyBuffer); // Bind the output buffer cmd.SetComputeTextureParam(m_SSGIDenoiserCS, m_KernelFilter, HDShaderIDs._OutputFilteredBuffer, outputBuffer); // Do the spatial pass cmd.DispatchCompute(m_SSGIDenoiserCS, m_KernelFilter, numTilesX, numTilesY, hdCamera.viewCount); // Grab the history buffer RTHandle indirectDiffuseHistory = hdCamera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.RaytracedIndirectDiffuseHF); if (indirectDiffuseHistory == null) { indirectDiffuseHistory = hdCamera.AllocHistoryFrameRT((int)HDCameraFrameHistoryType.RaytracedIndirectDiffuseHF, IndirectDiffuseHistoryBufferAllocatorFunction, 1); // clear it to black if this is the first pass to avoid nans CoreUtils.SetRenderTarget(cmd, indirectDiffuseHistory, ClearFlag.Color, clearColor: Color.black); } // Pick the right kernel to use m_KernelFilter = halfResolution ? m_TemporalFilterHalfKernel : m_TemporalFilterKernel; // Bind the input buffers cmd.SetComputeTextureParam(m_SSGIDenoiserCS, m_KernelFilter, HDShaderIDs._DepthTexture, m_SharedRTManager.GetDepthTexture()); cmd.SetComputeTextureParam(m_SSGIDenoiserCS, m_KernelFilter, HDShaderIDs._NormalBufferTexture, m_SharedRTManager.GetNormalBuffer()); cmd.SetComputeFloatParam(m_SSGIDenoiserCS, HDShaderIDs._HistoryValidity, historyValidity); if (halfResolution) { cmd.SetComputeTextureParam(m_SSGIDenoiserCS, m_KernelFilter, HDShaderIDs._HistoryDepthTexture, historyDepthBuffer1); cmd.SetComputeVectorParam(m_SSGIDenoiserCS, HDShaderIDs._DepthPyramidFirstMipLevelOffset, firstMipOffset); } else { cmd.SetComputeTextureParam(m_SSGIDenoiserCS, m_KernelFilter, HDShaderIDs._HistoryDepthTexture, historyDepthBuffer); } cmd.SetComputeTextureParam(m_SSGIDenoiserCS, m_KernelFilter, HDShaderIDs._HistoryBuffer, indirectDiffuseHistory); cmd.SetComputeTextureParam(m_SSGIDenoiserCS, m_KernelFilter, HDShaderIDs._InputNoisyBuffer, outputBuffer); // Bind the output buffer cmd.SetComputeTextureParam(m_SSGIDenoiserCS, m_KernelFilter, HDShaderIDs._OutputFilteredBuffer, noisyBuffer); // Do the temporal pass cmd.DispatchCompute(m_SSGIDenoiserCS, m_KernelFilter, numTilesX, numTilesY, hdCamera.viewCount); // Copy the new version into the history buffer cmd.SetComputeTextureParam(m_SSGIDenoiserCS, m_CopyHistory, HDShaderIDs._InputNoisyBuffer, noisyBuffer); cmd.SetComputeTextureParam(m_SSGIDenoiserCS, m_CopyHistory, HDShaderIDs._OutputFilteredBuffer, indirectDiffuseHistory); cmd.DispatchCompute(m_SSGIDenoiserCS, m_CopyHistory, numTilesX, numTilesY, hdCamera.viewCount); }
void RenderSSGI(HDCamera hdCamera, CommandBuffer cmd, ScriptableRenderContext renderContext, int frameCount) { // Grab the global illumination volume component GlobalIllumination giSettings = hdCamera.volumeStack.GetComponent <GlobalIllumination>(); // Grab the noise texture manager BlueNoise blueNoise = GetBlueNoiseManager(); // Grab the shaders we shall be using ComputeShader ssGICS = m_Asset.renderPipelineResources.shaders.screenSpaceGlobalIlluminationCS; // Evaluate the dispatch parameters int texWidth, texHeight; if (giSettings.fullResolutionSS) { texWidth = hdCamera.actualWidth; texHeight = hdCamera.actualHeight; halfScreenSize.Set(texWidth * 0.5f, texHeight * 0.5f, 2.0f / texWidth, 2.0f / texHeight); } else { texWidth = hdCamera.actualWidth / 2; texHeight = hdCamera.actualHeight / 2; halfScreenSize.Set(texWidth, texHeight, 1.0f / texWidth, 1.0f / texHeight); } int areaTileSize = 8; int numTilesXHR = (texWidth + (areaTileSize - 1)) / areaTileSize; int numTilesYHR = (texHeight + (areaTileSize - 1)) / areaTileSize; // 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))) { // Fetch the right tracing kernel int currentKernel = giSettings.fullResolutionSS ? m_TraceGlobalIlluminationKernel : m_TraceGlobalIlluminationHalfKernel; // Inject all the input scalars float n = hdCamera.camera.nearClipPlane; float f = hdCamera.camera.farClipPlane; float thickness = giSettings.depthBufferThickness.value; float thicknessScale = 1.0f / (1.0f + thickness); float thicknessBias = -n / (f - n) * (thickness * thicknessScale); cmd.SetComputeFloatParam(ssGICS, HDShaderIDs._IndirectDiffuseThicknessScale, thicknessScale); cmd.SetComputeFloatParam(ssGICS, HDShaderIDs._IndirectDiffuseThicknessBias, thicknessBias); cmd.SetComputeIntParam(ssGICS, HDShaderIDs._IndirectDiffuseSteps, giSettings.raySteps); cmd.SetComputeFloatParam(ssGICS, HDShaderIDs._IndirectDiffuseMaximalRadius, giSettings.maximalRadius); // Inject half screen size if required if (!giSettings.fullResolutionSS) { cmd.SetComputeVectorParam(ssGICS, HDShaderIDs._HalfScreenSize, halfScreenSize); } // Inject the ray-tracing sampling data blueNoise.BindDitheredRNGData1SPP(cmd); // Inject all the input textures/buffers cmd.SetComputeTextureParam(ssGICS, currentKernel, HDShaderIDs._DepthTexture, m_SharedRTManager.GetDepthTexture()); cmd.SetComputeTextureParam(ssGICS, currentKernel, HDShaderIDs._NormalBufferTexture, m_SharedRTManager.GetNormalBuffer()); cmd.SetComputeTextureParam(ssGICS, currentKernel, HDShaderIDs._IndirectDiffuseHitPointTextureRW, m_IndirectDiffuseHitPointBuffer); var info = m_SharedRTManager.GetDepthBufferMipChainInfo(); cmd.SetComputeBufferParam(ssGICS, currentKernel, HDShaderIDs._DepthPyramidMipLevelOffsets, info.GetOffsetBufferData(m_DepthPyramidMipLevelOffsetsBuffer)); cmd.SetGlobalBuffer(HDShaderIDs.g_vLightListGlobal, m_TileAndClusterData.lightList); // Do the ray marching cmd.DispatchCompute(ssGICS, currentKernel, numTilesXHR, numTilesYHR, hdCamera.viewCount); // Fetch the right kernel to use currentKernel = giSettings.fullResolutionSS ? m_ReprojectGlobalIlluminationKernel : m_ReprojectGlobalIlluminationHalfKernel; // 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 udpated here. m_ShaderVariablesRayTracingCB._RaytracingIntensityClamp = giSettings.clampValueSS; ConstantBuffer.PushGlobal(cmd, m_ShaderVariablesRayTracingCB, HDShaderIDs._ShaderVariablesRaytracing); // Inject all the input scalars cmd.SetComputeVectorParam(ssGICS, HDShaderIDs._ColorPyramidUvScaleAndLimitPrevFrame, HDUtils.ComputeViewportScaleAndLimit(hdCamera.historyRTHandleProperties.previousViewportSize, hdCamera.historyRTHandleProperties.previousRenderTargetSize)); // Bind all the input buffers cmd.SetComputeTextureParam(ssGICS, currentKernel, HDShaderIDs._DepthTexture, m_SharedRTManager.GetDepthStencilBuffer()); cmd.SetComputeTextureParam(ssGICS, currentKernel, HDShaderIDs._NormalBufferTexture, m_SharedRTManager.GetNormalBuffer()); cmd.SetComputeTextureParam(ssGICS, currentKernel, HDShaderIDs._IndirectDiffuseHitPointTexture, m_IndirectDiffuseHitPointBuffer); var previousColorPyramid = hdCamera.GetPreviousFrameRT((int)HDCameraFrameHistoryType.ColorBufferMipChain); cmd.SetComputeTextureParam(ssGICS, currentKernel, HDShaderIDs._ColorPyramidTexture, previousColorPyramid != null ? previousColorPyramid : TextureXR.GetBlackTexture()); var historyDepthBuffer = hdCamera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.Depth); cmd.SetComputeTextureParam(ssGICS, currentKernel, HDShaderIDs._HistoryDepthTexture, historyDepthBuffer != null ? historyDepthBuffer : TextureXR.GetBlackTexture()); cmd.SetComputeBufferParam(ssGICS, currentKernel, HDShaderIDs._DepthPyramidMipLevelOffsets, info.GetOffsetBufferData(m_DepthPyramidMipLevelOffsetsBuffer)); // Bind the output texture cmd.SetComputeTextureParam(ssGICS, currentKernel, HDShaderIDs._IndirectDiffuseTextureRW, buffer1); // Do the reprojection cmd.DispatchCompute(ssGICS, currentKernel, numTilesXHR, numTilesYHR, hdCamera.viewCount); float historyValidity = 1.0f; #if UNITY_HDRP_DXR_TESTS_DEFINE if (Application.isPlaying) { historyValidity = 0.0f; } else #endif // We need to check if something invalidated the history buffers historyValidity *= ValidRayTracingHistory(hdCamera) ? 1.0f : 0.0f; // Do the denoising part SSGIDenoiser ssgiDenoiser = GetSSGIDenoiser(); ssgiDenoiser.Denoise(cmd, hdCamera, buffer1, buffer0, halfResolution: !giSettings.fullResolutionSS, historyValidity: historyValidity); // If this was a half resolution effect, we still have to upscale it if (!giSettings.fullResolutionSS) { ComputeShader bilateralUpsampleCS = m_Asset.renderPipelineResources.shaders.bilateralUpsampleCS; // Re-evaluate the dispatch parameters (we are evaluating the upsample in full resolution) numTilesXHR = (hdCamera.actualWidth + (areaTileSize - 1)) / areaTileSize; numTilesYHR = (hdCamera.actualHeight + (areaTileSize - 1)) / areaTileSize; // Inject the input scalars cmd.SetComputeVectorParam(bilateralUpsampleCS, HDShaderIDs._HalfScreenSize, halfScreenSize); firstMipOffset.Set(HDShadowUtils.Asfloat((uint)info.mipLevelOffsets[1].x), HDShadowUtils.Asfloat((uint)info.mipLevelOffsets[1].y)); cmd.SetComputeVectorParam(bilateralUpsampleCS, HDShaderIDs._DepthPyramidFirstMipLevelOffset, firstMipOffset); // Inject all the input buffers cmd.SetComputeTextureParam(bilateralUpsampleCS, m_BilateralUpSampleColorTMKernel, HDShaderIDs._DepthTexture, m_SharedRTManager.GetDepthTexture()); cmd.SetComputeTextureParam(bilateralUpsampleCS, m_BilateralUpSampleColorTMKernel, HDShaderIDs._LowResolutionTexture, buffer1); cmd.SetComputeBufferParam(bilateralUpsampleCS, m_BilateralUpSampleColorTMKernel, HDShaderIDs._DepthPyramidMipLevelOffsets, info.GetOffsetBufferData(m_DepthPyramidMipLevelOffsetsBuffer)); // Inject the output textures cmd.SetComputeTextureParam(bilateralUpsampleCS, m_BilateralUpSampleColorTMKernel, HDShaderIDs._OutputUpscaledTexture, buffer0); // Upscale the buffer to full resolution cmd.DispatchCompute(bilateralUpsampleCS, m_BilateralUpSampleColorTMKernel, numTilesXHR, numTilesYHR, hdCamera.viewCount); } (RenderPipelineManager.currentPipeline as HDRenderPipeline).PushFullScreenDebugTexture(hdCamera, cmd, m_IndirectDiffuseBuffer0, FullScreenDebugMode.ScreenSpaceGlobalIllumination); } }
void EvaluateClusterDebugView(CommandBuffer cmd, HDCamera hdCamera, HDRaytracingEnvironment currentEnv) { ComputeShader lightClusterDebugCS = m_RenderPipelineRayTracingResources.lightClusterDebugCS; if (lightClusterDebugCS == null) { return; } Texture2D gradientTexture = m_RenderPipelineResources.textures.colorGradient; if (gradientTexture == null) { return; } // Grab the kernel int m_LightClusterDebugKernel = lightClusterDebugCS.FindKernel("DebugLightCluster"); // Inject all the parameters to the debug compute cmd.SetComputeBufferParam(lightClusterDebugCS, m_LightClusterDebugKernel, HDShaderIDs._RaytracingLightCluster, m_LightCluster); cmd.SetComputeVectorParam(lightClusterDebugCS, HDShaderIDs._MinClusterPos, minClusterPos); cmd.SetComputeVectorParam(lightClusterDebugCS, HDShaderIDs._MaxClusterPos, maxClusterPos); cmd.SetComputeVectorParam(lightClusterDebugCS, _ClusterCellSize, clusterCellSize); cmd.SetComputeFloatParam(lightClusterDebugCS, HDShaderIDs._LightPerCellCount, HDShadowUtils.Asfloat(numLightsPerCell)); cmd.SetComputeTextureParam(lightClusterDebugCS, m_LightClusterDebugKernel, _DebugColorGradientTexture, gradientTexture); cmd.SetComputeTextureParam(lightClusterDebugCS, m_LightClusterDebugKernel, HDShaderIDs._CameraDepthTexture, m_SharedRTManager.GetDepthStencilBuffer()); // Target output texture cmd.SetComputeTextureParam(lightClusterDebugCS, m_LightClusterDebugKernel, _DebutLightClusterTexture, m_DebugLightClusterTexture); // Texture dimensions int texWidth = hdCamera.actualWidth; int texHeight = hdCamera.actualHeight; // Dispatch the compute int lightVolumesTileSize = 8; int numTilesX = (texWidth + (lightVolumesTileSize - 1)) / lightVolumesTileSize; int numTilesY = (texHeight + (lightVolumesTileSize - 1)) / lightVolumesTileSize; cmd.DispatchCompute(lightClusterDebugCS, m_LightClusterDebugKernel, numTilesX, numTilesY, 1); }