using UnityEngine.Experimental.Rendering; namespace UnityEngine.Rendering.HighDefinition { public partial class HDRenderPipeline { // Tile of the side used to dispatch the various compute shader kernels const int rtReflectionsComputeTileSize = 8; // String values const string m_RayGenIntegrationName = "RayGenIntegration"; const string m_RayGenIntegrationTransparentName = "RayGenIntegrationTransparent"; // Kernels int m_RaytracingReflectionsFullResKernel; int m_RaytracingReflectionsHalfResKernel; int m_RaytracingReflectionsTransparentFullResKernel; int m_RaytracingReflectionsTransparentHalfResKernel; int m_ReflectionAdjustWeightKernel; int m_ReflectionRescaleAndAdjustWeightKernel; int m_ReflectionUpscaleKernel; void InitRayTracedReflections() { ComputeShader reflectionShaderCS = m_Asset.renderPipelineRayTracingResources.reflectionRaytracingCS; ComputeShader reflectionBilateralFilterCS = m_Asset.renderPipelineRayTracingResources.reflectionBilateralFilterCS; // Grab all the kernels we shall be using m_RaytracingReflectionsFullResKernel = reflectionShaderCS.FindKernel("RaytracingReflectionsFullRes"); m_RaytracingReflectionsHalfResKernel = reflectionShaderCS.FindKernel("RaytracingReflectionsHalfRes"); m_RaytracingReflectionsTransparentFullResKernel = reflectionShaderCS.FindKernel("RaytracingReflectionsTransparentFullRes"); m_RaytracingReflectionsTransparentHalfResKernel = reflectionShaderCS.FindKernel("RaytracingReflectionsTransparentHalfRes"); m_ReflectionAdjustWeightKernel = reflectionBilateralFilterCS.FindKernel("ReflectionAdjustWeight"); m_ReflectionUpscaleKernel = reflectionBilateralFilterCS.FindKernel("ReflectionUpscale"); } static RTHandle ReflectionHistoryBufferAllocatorFunction(string viewName, int frameIndex, RTHandleSystem rtHandleSystem) { return rtHandleSystem.Alloc(Vector2.one, TextureXR.slices, colorFormat: GraphicsFormat.R16G16B16A16_SFloat, dimension: TextureXR.dimension, enableRandomWrite: true, useMipMap: false, autoGenerateMips: false, name: string.Format("{0}_ReflectionHistoryBuffer{1}", viewName, frameIndex)); } private float EvaluateRayTracedReflectionHistoryValidity(HDCamera hdCamera, bool fullResolution, bool rayTraced) { // Evaluate the history validity float effectHistoryValidity = hdCamera.EffectHistoryValidity(HDCamera.HistoryEffectSlot.RayTracedReflections, fullResolution, rayTraced) ? 1.0f : 0.0f; return EvaluateHistoryValidity(hdCamera) * effectHistoryValidity; } private void PropagateRayTracedReflectionsHistoryValidity(HDCamera hdCamera, bool fullResolution, bool rayTraced) { hdCamera.PropagateEffectHistoryValidity(HDCamera.HistoryEffectSlot.RayTracedReflections, fullResolution, rayTraced); } #region Direction Generation struct RTReflectionDirGenParameters { // Camera parameters public int texWidth; public int texHeight; public int viewCount; // Generation parameters public float minSmoothness; // Additional resources public ComputeShader directionGenCS; public int dirGenKernel; public BlueNoise.DitheredTextureSet ditheredTextureSet; public ShaderVariablesRaytracing shaderVariablesRayTracingCB; } RTReflectionDirGenParameters PrepareRTReflectionDirGenParameters(HDCamera hdCamera, bool transparent, ScreenSpaceReflection settings) { RTReflectionDirGenParameters rtrDirGenParams = new RTReflectionDirGenParameters(); // Set the camera parameters rtrDirGenParams.texWidth = settings.fullResolution ? hdCamera.actualWidth : hdCamera.actualWidth / 2; rtrDirGenParams.texHeight = settings.fullResolution ? hdCamera.actualHeight : hdCamera.actualHeight / 2; rtrDirGenParams.viewCount = hdCamera.viewCount; // Set the generation parameters rtrDirGenParams.minSmoothness = settings.minSmoothness; // Grab the right kernel rtrDirGenParams.directionGenCS = m_Asset.renderPipelineRayTracingResources.reflectionRaytracingCS; if (settings.fullResolution) rtrDirGenParams.dirGenKernel = transparent ? m_RaytracingReflectionsTransparentFullResKernel : m_RaytracingReflectionsFullResKernel; else rtrDirGenParams.dirGenKernel = transparent ? m_RaytracingReflectionsTransparentHalfResKernel : m_RaytracingReflectionsHalfResKernel; // Grab the additional parameters BlueNoise blueNoise = GetBlueNoiseManager(); rtrDirGenParams.ditheredTextureSet = blueNoise.DitheredTextureSet8SPP(); rtrDirGenParams.shaderVariablesRayTracingCB = m_ShaderVariablesRayTracingCB; return rtrDirGenParams; } struct RTReflectionDirGenResources { // Input buffers public RTHandle depthBuffer; public RTHandle normalBuffer; public RTHandle stencilBuffer; public RenderTargetIdentifier clearCoatMaskTexture; // Output buffers public RTHandle outputBuffer; } static void RTReflectionDirectionGeneration(CommandBuffer cmd, RTReflectionDirGenParameters rtrDirGenParams, RTReflectionDirGenResources rtrDirGenResources) { // TODO: check if this is required, i do not think so CoreUtils.SetRenderTarget(cmd, rtrDirGenResources.outputBuffer, ClearFlag.Color, clearColor: Color.black); // Inject the ray-tracing sampling data BlueNoise.BindDitheredTextureSet(cmd, rtrDirGenParams.ditheredTextureSet); // Bind all the required scalars to the CB rtrDirGenParams.shaderVariablesRayTracingCB._RaytracingReflectionMinSmoothness = rtrDirGenParams.minSmoothness; ConstantBuffer.PushGlobal(cmd, rtrDirGenParams.shaderVariablesRayTracingCB, HDShaderIDs._ShaderVariablesRaytracing); // Bind all the required textures cmd.SetComputeTextureParam(rtrDirGenParams.directionGenCS, rtrDirGenParams.dirGenKernel, HDShaderIDs._DepthTexture, rtrDirGenResources.depthBuffer); cmd.SetComputeTextureParam(rtrDirGenParams.directionGenCS, rtrDirGenParams.dirGenKernel, HDShaderIDs._NormalBufferTexture, rtrDirGenResources.normalBuffer); cmd.SetComputeTextureParam(rtrDirGenParams.directionGenCS, rtrDirGenParams.dirGenKernel, HDShaderIDs._SsrClearCoatMaskTexture, rtrDirGenResources.clearCoatMaskTexture); cmd.SetComputeIntParam(rtrDirGenParams.directionGenCS, HDShaderIDs._SsrStencilBit, (int)StencilUsage.TraceReflectionRay); cmd.SetComputeTextureParam(rtrDirGenParams.directionGenCS, rtrDirGenParams.dirGenKernel, HDShaderIDs._StencilTexture, rtrDirGenResources.stencilBuffer, 0, RenderTextureSubElement.Stencil); // Bind the output buffers cmd.SetComputeTextureParam(rtrDirGenParams.directionGenCS, rtrDirGenParams.dirGenKernel, HDShaderIDs._RaytracingDirectionBuffer, rtrDirGenResources.outputBuffer); // Evaluate the dispatch parameters int numTilesX = (rtrDirGenParams.texWidth + (rtReflectionsComputeTileSize - 1)) / rtReflectionsComputeTileSize; int numTilesY = (rtrDirGenParams.texHeight + (rtReflectionsComputeTileSize - 1)) / rtReflectionsComputeTileSize; // Compute the directions cmd.DispatchCompute(rtrDirGenParams.directionGenCS, rtrDirGenParams.dirGenKernel, numTilesX, numTilesY, rtrDirGenParams.viewCount); } #endregion #region Deferred Lighting DeferredLightingRTParameters PrepareReflectionDeferredLightingRTParameters(HDCamera hdCamera) { DeferredLightingRTParameters deferredParameters = new DeferredLightingRTParameters(); // Fetch the GI volume component var settings = hdCamera.volumeStack.GetComponent(); RayTracingSettings rTSettings = hdCamera.volumeStack.GetComponent(); // Make sure the binning buffer has the right size CheckBinningBuffersSize(hdCamera); // Generic attributes deferredParameters.rayBinning = true; deferredParameters.layerMask.value = (int)RayTracingRendererFlag.Reflection; deferredParameters.diffuseLightingOnly = false; deferredParameters.halfResolution = !settings.fullResolution; deferredParameters.rayCountType = (int)RayCountValues.ReflectionDeferred; // Camera data deferredParameters.width = hdCamera.actualWidth; deferredParameters.height = hdCamera.actualHeight; deferredParameters.viewCount = hdCamera.viewCount; // Compute buffers deferredParameters.rayBinResult = m_RayBinResult; deferredParameters.rayBinSizeResult = m_RayBinSizeResult; deferredParameters.accelerationStructure = RequestAccelerationStructure(); deferredParameters.lightCluster = RequestLightCluster(); // Shaders deferredParameters.gBufferRaytracingRT = m_Asset.renderPipelineRayTracingResources.gBufferRaytracingRT; deferredParameters.deferredRaytracingCS = m_Asset.renderPipelineRayTracingResources.deferredRaytracingCS; deferredParameters.rayBinningCS = m_Asset.renderPipelineRayTracingResources.rayBinningCS; // XRTODO: add ray binning support for single-pass if (deferredParameters.viewCount > 1 && deferredParameters.rayBinning) { deferredParameters.rayBinning = false; } // Make a copy of the previous values that were defined in the CB deferredParameters.raytracingCB = m_ShaderVariablesRayTracingCB; // Override the ones we need to deferredParameters.raytracingCB._RaytracingRayMaxLength = settings.rayLength; deferredParameters.raytracingCB._RaytracingIntensityClamp = settings.clampValue; deferredParameters.raytracingCB._RaytracingIncludeSky = settings.reflectSky.value ? 1 : 0; deferredParameters.raytracingCB._RaytracingPreExposition = 0; deferredParameters.raytracingCB._RayTracingDiffuseLightingOnly = 0; return deferredParameters; } #endregion #region AdjustWeight struct RTRAdjustWeightParameters { // Camera parameters public int texWidth; public int texHeight; public int viewCount; public float minSmoothness; public float smoothnessFadeStart; // Other parameters public ComputeShader reflectionFilterCS; public int adjustWeightKernel; public ShaderVariablesRaytracing shaderVariablesRayTracingCB; } RTRAdjustWeightParameters PrepareRTRAdjustWeightParameters(HDCamera hdCamera, ScreenSpaceReflection settings) { RTRAdjustWeightParameters parameters = new RTRAdjustWeightParameters(); // Camera parameters parameters.texWidth = settings.fullResolution ? hdCamera.actualWidth : hdCamera.actualWidth / 2; parameters.texHeight = settings.fullResolution ? hdCamera.actualHeight : hdCamera.actualHeight / 2; parameters.viewCount = hdCamera.viewCount; // Requires parameters parameters.minSmoothness = settings.minSmoothness; parameters.smoothnessFadeStart = settings.smoothnessFadeStart; // Other parameters parameters.reflectionFilterCS = m_Asset.renderPipelineRayTracingResources.reflectionBilateralFilterCS; parameters.adjustWeightKernel = settings.fullResolution ? m_ReflectionAdjustWeightKernel : m_ReflectionRescaleAndAdjustWeightKernel; parameters.shaderVariablesRayTracingCB = m_ShaderVariablesRayTracingCB; return parameters; } struct RTRAdjustWeightResources { public RTHandle depthStencilBuffer; public RTHandle normalBuffer; public RTHandle lightingTexture; public RTHandle directionTexture; public RTHandle outputTexture; public RenderTargetIdentifier clearCoatMaskTexture; } static void AdjustWeightRTReflections(CommandBuffer cmd, RTRAdjustWeightParameters parameters, RTRAdjustWeightResources resources) { // Bind all the required scalars to the CB parameters.shaderVariablesRayTracingCB._RaytracingReflectionMinSmoothness = parameters.minSmoothness; parameters.shaderVariablesRayTracingCB._RaytracingReflectionSmoothnessFadeStart = parameters.smoothnessFadeStart; ConstantBuffer.PushGlobal(cmd, parameters.shaderVariablesRayTracingCB, HDShaderIDs._ShaderVariablesRaytracing); // Source input textures cmd.SetComputeTextureParam(parameters.reflectionFilterCS, parameters.adjustWeightKernel, HDShaderIDs._DepthTexture, resources.depthStencilBuffer); cmd.SetComputeTextureParam(parameters.reflectionFilterCS, parameters.adjustWeightKernel, HDShaderIDs._SsrClearCoatMaskTexture, resources.clearCoatMaskTexture); cmd.SetComputeTextureParam(parameters.reflectionFilterCS, parameters.adjustWeightKernel, HDShaderIDs._NormalBufferTexture, resources.normalBuffer); cmd.SetComputeTextureParam(parameters.reflectionFilterCS, parameters.adjustWeightKernel, HDShaderIDs._DirectionPDFTexture, resources.directionTexture); // Lighting textures cmd.SetComputeTextureParam(parameters.reflectionFilterCS, parameters.adjustWeightKernel, HDShaderIDs._SsrLightingTextureRW, resources.lightingTexture); // Output texture cmd.SetComputeTextureParam(parameters.reflectionFilterCS, parameters.adjustWeightKernel, HDShaderIDs._RaytracingReflectionTexture, resources.outputTexture); // Compute the texture int numTilesXHR = (parameters.texWidth + (rtReflectionsComputeTileSize - 1)) / rtReflectionsComputeTileSize; int numTilesYHR = (parameters.texHeight + (rtReflectionsComputeTileSize - 1)) / rtReflectionsComputeTileSize; cmd.DispatchCompute(parameters.reflectionFilterCS, parameters.adjustWeightKernel, numTilesXHR, numTilesYHR, parameters.viewCount); } #endregion #region Upscale struct RTRUpscaleParameters { // Camera parameters public int texWidth; public int texHeight; public int viewCount; // Other parameters public ComputeShader reflectionFilterCS; public int upscaleKernel; } RTRUpscaleParameters PrepareRTRUpscaleParameters(HDCamera hdCamera, ScreenSpaceReflection settings) { RTRUpscaleParameters parameters = new RTRUpscaleParameters(); // Camera parameters parameters.texWidth = hdCamera.actualWidth; parameters.texHeight = hdCamera.actualHeight; parameters.viewCount = hdCamera.viewCount; // Other parameters parameters.reflectionFilterCS = m_Asset.renderPipelineRayTracingResources.reflectionBilateralFilterCS; parameters.upscaleKernel = m_ReflectionUpscaleKernel; return parameters; } struct RTRUpscaleResources { public RTHandle depthStencilBuffer; public RTHandle lightingTexture; public RTHandle outputTexture; } static void UpscaleRTR(CommandBuffer cmd, RTRUpscaleParameters parameters, RTRUpscaleResources resources) { // Input textures cmd.SetComputeTextureParam(parameters.reflectionFilterCS, parameters.upscaleKernel, HDShaderIDs._DepthTexture, resources.depthStencilBuffer); cmd.SetComputeTextureParam(parameters.reflectionFilterCS, parameters.upscaleKernel, HDShaderIDs._SsrLightingTextureRW, resources.lightingTexture); // Output texture cmd.SetComputeTextureParam(parameters.reflectionFilterCS, parameters.upscaleKernel, HDShaderIDs._RaytracingReflectionTexture, resources.outputTexture); // Compute the texture int numTilesXHR = (parameters.texWidth + (rtReflectionsComputeTileSize - 1)) / rtReflectionsComputeTileSize; int numTilesYHR = (parameters.texHeight + (rtReflectionsComputeTileSize - 1)) / rtReflectionsComputeTileSize; cmd.DispatchCompute(parameters.reflectionFilterCS, parameters.upscaleKernel, numTilesXHR, numTilesYHR, parameters.viewCount); } #endregion #region Quality RTR struct RTRQualityRenderingParameters { // Camera parameters public int texWidth; public int texHeight; public int viewCount; // Reflection evaluation parameters public float clampValue; public int reflectSky; public float rayLength; public int sampleCount; public int bounceCount; public bool transparent; public float minSmoothness; public float smoothnessFadeStart; // Other parameters public RayTracingAccelerationStructure accelerationStructure; public HDRaytracingLightCluster lightCluster; public BlueNoise.DitheredTextureSet ditheredTextureSet; public ShaderVariablesRaytracing shaderVariablesRayTracingCB; public Texture skyTexture; public RayTracingShader reflectionShader; }; RTRQualityRenderingParameters PrepareRTRQualityRenderingParameters(HDCamera hdCamera, ScreenSpaceReflection settings, bool transparent) { RTRQualityRenderingParameters rtrQualityRenderingParameters = new RTRQualityRenderingParameters(); // Camera parameters rtrQualityRenderingParameters.texWidth = hdCamera.actualWidth; rtrQualityRenderingParameters.texHeight = hdCamera.actualHeight; rtrQualityRenderingParameters.viewCount = hdCamera.viewCount; // Reflection evaluation parameters rtrQualityRenderingParameters.clampValue = settings.clampValue; rtrQualityRenderingParameters.reflectSky = settings.reflectSky.value ? 1 : 0; rtrQualityRenderingParameters.rayLength = settings.rayLength; rtrQualityRenderingParameters.sampleCount = settings.sampleCount.value; rtrQualityRenderingParameters.bounceCount = settings.bounceCount.value; rtrQualityRenderingParameters.transparent = transparent; rtrQualityRenderingParameters.minSmoothness = settings.minSmoothness; rtrQualityRenderingParameters.smoothnessFadeStart = settings.smoothnessFadeStart; // Other parameters rtrQualityRenderingParameters.accelerationStructure = RequestAccelerationStructure(); rtrQualityRenderingParameters.lightCluster = RequestLightCluster(); BlueNoise blueNoise = GetBlueNoiseManager(); rtrQualityRenderingParameters.ditheredTextureSet = blueNoise.DitheredTextureSet8SPP(); rtrQualityRenderingParameters.shaderVariablesRayTracingCB = m_ShaderVariablesRayTracingCB; rtrQualityRenderingParameters.skyTexture = m_SkyManager.GetSkyReflection(hdCamera); rtrQualityRenderingParameters.reflectionShader = m_Asset.renderPipelineRayTracingResources.reflectionRaytracingRT; return rtrQualityRenderingParameters; } struct RTRQualityRenderingResources { // Input texture public RTHandle depthBuffer; public RTHandle normalBuffer; public RTHandle stencilBuffer; public RenderTargetIdentifier clearCoatMaskTexture; // Debug texture public RTHandle rayCountTexture; // Output texture public RTHandle outputTexture; } static void RenderQualityRayTracedReflections(CommandBuffer cmd, RTRQualityRenderingParameters rtrQRenderingParameters, RTRQualityRenderingResources rtrQRenderingResources) { // Define the shader pass to use for the reflection pass cmd.SetRayTracingShaderPass(rtrQRenderingParameters.reflectionShader, "IndirectDXR"); // Set the acceleration structure for the pass cmd.SetRayTracingAccelerationStructure(rtrQRenderingParameters.reflectionShader, HDShaderIDs._RaytracingAccelerationStructureName, rtrQRenderingParameters.accelerationStructure); // Global reflection parameters rtrQRenderingParameters.shaderVariablesRayTracingCB._RaytracingIntensityClamp = rtrQRenderingParameters.clampValue; rtrQRenderingParameters.shaderVariablesRayTracingCB._RaytracingIncludeSky = rtrQRenderingParameters.reflectSky; // Inject the ray generation data rtrQRenderingParameters.shaderVariablesRayTracingCB._RaytracingRayMaxLength = rtrQRenderingParameters.rayLength; rtrQRenderingParameters.shaderVariablesRayTracingCB._RaytracingNumSamples = rtrQRenderingParameters.sampleCount; // Set the number of bounces for reflections #if NO_RAY_RECURSION rtrQRenderingParameters.shaderVariablesRayTracingCB._RaytracingMaxRecursion = 1; #else rtrQRenderingParameters.shaderVariablesRayTracingCB._RaytracingMaxRecursion = rtrQRenderingParameters.bounceCount; #endif rtrQRenderingParameters.shaderVariablesRayTracingCB._RayTracingDiffuseLightingOnly = 0; // Bind all the required scalars to the CB rtrQRenderingParameters.shaderVariablesRayTracingCB._RaytracingReflectionMinSmoothness = rtrQRenderingParameters.minSmoothness; rtrQRenderingParameters.shaderVariablesRayTracingCB._RaytracingReflectionSmoothnessFadeStart = rtrQRenderingParameters.smoothnessFadeStart; ConstantBuffer.PushGlobal(cmd, rtrQRenderingParameters.shaderVariablesRayTracingCB, HDShaderIDs._ShaderVariablesRaytracing); // Inject the ray-tracing sampling data BlueNoise.BindDitheredTextureSet(cmd, rtrQRenderingParameters.ditheredTextureSet); // Set the data for the ray generation cmd.SetRayTracingTextureParam(rtrQRenderingParameters.reflectionShader, HDShaderIDs._SsrLightingTextureRW, rtrQRenderingResources.outputTexture); cmd.SetRayTracingTextureParam(rtrQRenderingParameters.reflectionShader, HDShaderIDs._DepthTexture, rtrQRenderingResources.depthBuffer); cmd.SetRayTracingTextureParam(rtrQRenderingParameters.reflectionShader, HDShaderIDs._NormalBufferTexture, rtrQRenderingResources.normalBuffer); cmd.SetGlobalTexture(HDShaderIDs._StencilTexture, rtrQRenderingResources.stencilBuffer, RenderTextureSubElement.Stencil); cmd.SetRayTracingIntParams(rtrQRenderingParameters.reflectionShader, HDShaderIDs._SsrStencilBit, (int)StencilUsage.TraceReflectionRay); // Set ray count texture cmd.SetRayTracingTextureParam(rtrQRenderingParameters.reflectionShader, HDShaderIDs._RayCountTexture, rtrQRenderingResources.rayCountTexture); // Bind the lightLoop data rtrQRenderingParameters.lightCluster.BindLightClusterData(cmd); // Evaluate the clear coat mask texture based on the lit shader mode cmd.SetRayTracingTextureParam(rtrQRenderingParameters.reflectionShader, HDShaderIDs._SsrClearCoatMaskTexture, rtrQRenderingResources.clearCoatMaskTexture); // Set the data for the ray miss cmd.SetRayTracingTextureParam(rtrQRenderingParameters.reflectionShader, HDShaderIDs._SkyTexture, rtrQRenderingParameters.skyTexture); // Only use the shader variant that has multi bounce if the bounce count > 1 CoreUtils.SetKeyword(cmd, "MULTI_BOUNCE_INDIRECT", rtrQRenderingParameters.bounceCount > 1); // Run the computation cmd.DispatchRays(rtrQRenderingParameters.reflectionShader, rtrQRenderingParameters.transparent ? m_RayGenIntegrationTransparentName : m_RayGenIntegrationName, (uint)rtrQRenderingParameters.texWidth, (uint)rtrQRenderingParameters.texHeight, (uint)rtrQRenderingParameters.viewCount); // Disable multi-bounce CoreUtils.SetKeyword(cmd, "MULTI_BOUNCE_INDIRECT", false); } #endregion } }