using System.Collections.Generic; using UnityEngine.Experimental.Rendering; using UnityEngine.Experimental.Rendering.RenderGraphModule; namespace UnityEngine.Rendering.HighDefinition { [GenerateHLSL] internal enum RayTracingRendererFlag { Opaque = 0x01, CastShadowTransparent = 0x02, CastShadowOpaque = 0x04, CastShadow = CastShadowOpaque | CastShadowTransparent, AmbientOcclusion = 0x08, Reflection = 0x10, GlobalIllumination = 0x20, RecursiveRendering = 0x40, PathTracing = 0x80 } internal enum AccelerationStructureStatus { Clear = 0x0, Added = 0x1, Excluded = 0x02, TransparencyIssue = 0x04, NullMaterial = 0x08, MissingMesh = 0x10 } class HDRayTracingLights { // The list of non-directional lights in the sub-scene public List hdPointLightArray = new List(); public List hdLineLightArray = new List(); public List hdRectLightArray = new List(); public List hdLightArray = new List(); // The list of directional lights in the sub-scene public List hdDirectionalLightArray = new List(); // The list of reflection probes public List reflectionProbeArray = new List(); // Counter of the current number of lights public int lightCount; } public partial class HDRenderPipeline { // Data used for runtime evaluation RayTracingAccelerationStructure m_CurrentRAS = new RayTracingAccelerationStructure(); HDRaytracingLightCluster m_RayTracingLightCluster; HDRayTracingLights m_RayTracingLights = new HDRayTracingLights(); bool m_ValidRayTracingState = false; bool m_ValidRayTracingCluster = false; bool m_ValidRayTracingClusterCulling = false; bool m_RayTracedShadowsRequired = false; bool m_RayTracedContactShadowsRequired = false; // Denoisers HDTemporalFilter m_TemporalFilter; HDSimpleDenoiser m_SimpleDenoiser; HDDiffuseDenoiser m_DiffuseDenoiser; HDReflectionDenoiser m_ReflectionDenoiser; HDDiffuseShadowDenoiser m_DiffuseShadowDenoiser; SSGIDenoiser m_SSGIDenoiser; // Ray-count manager data RayCountManager m_RayCountManager; const int maxNumSubMeshes = 32; Dictionary m_RayTracingRendererReference = new Dictionary(); bool[] subMeshFlagArray = new bool[maxNumSubMeshes]; bool[] subMeshCutoffArray = new bool[maxNumSubMeshes]; bool[] subMeshTransparentArray = new bool[maxNumSubMeshes]; ReflectionProbe reflectionProbe = new ReflectionProbe(); List materialArray = new List(maxNumSubMeshes); Dictionary m_ShaderValidityCache = new Dictionary(); // Used to detect material and transform changes for Path Tracing Dictionary m_MaterialCRCs = new Dictionary(); bool m_MaterialsDirty = false; bool m_TransformDirty = false; ShaderVariablesRaytracingLightLoop m_ShaderVariablesRaytracingLightLoopCB = new ShaderVariablesRaytracingLightLoop(); internal void InitRayTracingManager() { // Init the ray count manager m_RayCountManager = new RayCountManager(); m_RayCountManager.Init(m_Asset.renderPipelineRayTracingResources); // Build the light cluster m_RayTracingLightCluster = new HDRaytracingLightCluster(); m_RayTracingLightCluster.Initialize(this); } internal void ReleaseRayTracingManager() { if (m_RayTracingLightCluster != null) m_RayTracingLightCluster.ReleaseResources(); if (m_RayCountManager != null) m_RayCountManager.Release(); if (m_ReflectionDenoiser != null) m_ReflectionDenoiser.Release(); if (m_TemporalFilter != null) m_TemporalFilter.Release(); if (m_SimpleDenoiser != null) m_SimpleDenoiser.Release(); if (m_SSGIDenoiser != null) m_SSGIDenoiser.Release(); if (m_DiffuseShadowDenoiser != null) m_DiffuseShadowDenoiser.Release(); if (m_DiffuseDenoiser != null) m_DiffuseDenoiser.Release(); } bool IsValidRayTracedMaterial(Material currentMaterial) { if (currentMaterial == null || currentMaterial.shader == null) return false; bool isValid; // We use a cache, to speed up the case where materials/shaders are reused many times int shaderId = currentMaterial.shader.GetInstanceID(); if (m_ShaderValidityCache.TryGetValue(shaderId, out isValid)) return isValid; // For the time being, we only consider non-decal HDRP materials as valid isValid = currentMaterial.GetTag("RenderPipeline", false) == "HDRenderPipeline" && !DecalSystem.IsDecalMaterial(currentMaterial); m_ShaderValidityCache.Add(shaderId, isValid); return isValid; } static bool IsTransparentMaterial(Material currentMaterial) { return currentMaterial.IsKeywordEnabled("_SURFACE_TYPE_TRANSPARENT") || (HDRenderQueue.k_RenderQueue_Transparent.lowerBound <= currentMaterial.renderQueue && HDRenderQueue.k_RenderQueue_Transparent.upperBound >= currentMaterial.renderQueue); } static bool IsAlphaTestedMaterial(Material currentMaterial) { return currentMaterial.IsKeywordEnabled("_ALPHATEST_ON") || (HDRenderQueue.k_RenderQueue_OpaqueAlphaTest.lowerBound <= currentMaterial.renderQueue && HDRenderQueue.k_RenderQueue_OpaqueAlphaTest.upperBound >= currentMaterial.renderQueue); } AccelerationStructureStatus AddInstanceToRAS(Renderer currentRenderer, bool rayTracedShadow, bool aoEnabled, int aoLayerValue, bool reflEnabled, int reflLayerValue, bool giEnabled, int giLayerValue, bool recursiveEnabled, int rrLayerValue, bool pathTracingEnabled, int ptLayerValue) { // Get all the materials of the mesh renderer currentRenderer.GetSharedMaterials(materialArray); // If the array is null, we are done if (materialArray == null) return AccelerationStructureStatus.NullMaterial; // For every sub-mesh/sub-material let's build the right flags int numSubMeshes = 1; if (!(currentRenderer.GetType() == typeof(SkinnedMeshRenderer))) { currentRenderer.TryGetComponent(out MeshFilter meshFilter); if (meshFilter == null || meshFilter.sharedMesh == null) return AccelerationStructureStatus.MissingMesh; numSubMeshes = meshFilter.sharedMesh.subMeshCount; } else { SkinnedMeshRenderer skinnedMesh = (SkinnedMeshRenderer)currentRenderer; if (skinnedMesh.sharedMesh == null) return AccelerationStructureStatus.MissingMesh; numSubMeshes = skinnedMesh.sharedMesh.subMeshCount; } // Let's clamp the number of sub-meshes to avoid throwing an unwated error numSubMeshes = Mathf.Min(numSubMeshes, maxNumSubMeshes); // Get the layer of this object int objectLayerValue = 1 << currentRenderer.gameObject.layer; // We need to build the instance flag for this renderer uint instanceFlag = 0x00; bool doubleSided = false; bool materialIsOnlyTransparent = true; bool hasTransparentSubMaterial = false; // We disregard the ray traced shadows option when in Path Tracing rayTracedShadow &= !pathTracingEnabled; // Deactivate Path Tracing if the object does not belong to the path traced layer(s) pathTracingEnabled &= (bool)((ptLayerValue & objectLayerValue) != 0); for (int meshIdx = 0; meshIdx < numSubMeshes; ++meshIdx) { // Initially we consider the potential mesh as invalid bool validMesh = false; if (materialArray.Count > meshIdx) { // Grab the material for the current sub-mesh Material currentMaterial = materialArray[meshIdx]; // Make sure that the material is HDRP's and non-decal if (IsValidRayTracedMaterial(currentMaterial)) { // Mesh is valid given that all requirements are ok validMesh = true; subMeshFlagArray[meshIdx] = true; // Is the sub material transparent? subMeshTransparentArray[meshIdx] = currentMaterial.IsKeywordEnabled("_SURFACE_TYPE_TRANSPARENT") || (HDRenderQueue.k_RenderQueue_Transparent.lowerBound <= currentMaterial.renderQueue && HDRenderQueue.k_RenderQueue_Transparent.upperBound >= currentMaterial.renderQueue); // Aggregate the transparency info materialIsOnlyTransparent &= subMeshTransparentArray[meshIdx]; hasTransparentSubMaterial |= subMeshTransparentArray[meshIdx]; // Is the material alpha tested? subMeshCutoffArray[meshIdx] = currentMaterial.IsKeywordEnabled("_ALPHATEST_ON") || (HDRenderQueue.k_RenderQueue_OpaqueAlphaTest.lowerBound <= currentMaterial.renderQueue && HDRenderQueue.k_RenderQueue_OpaqueAlphaTest.upperBound >= currentMaterial.renderQueue); // Check if we want to enable double-sidedness for the mesh // (note that a mix of single and double-sided materials will result in a double-sided mesh in the AS) doubleSided |= currentMaterial.doubleSidedGI || currentMaterial.IsKeywordEnabled("_DOUBLESIDED_ON"); // Check if the material has changed since last time we were here if (!m_MaterialsDirty) { int matId = currentMaterial.GetInstanceID(); int matPrevCRC, matCurCRC = currentMaterial.ComputeCRC(); if (m_MaterialCRCs.TryGetValue(matId, out matPrevCRC)) { m_MaterialCRCs[matId] = matCurCRC; m_MaterialsDirty |= (matCurCRC != matPrevCRC); } else { m_MaterialCRCs.Add(matId, matCurCRC); } } } } // If the mesh was not valid, exclude it (without affecting sidedness) if (!validMesh) { subMeshFlagArray[meshIdx] = false; subMeshCutoffArray[meshIdx] = false; } } // If the material is considered opaque, but has some transparent sub-materials if (!materialIsOnlyTransparent && hasTransparentSubMaterial) { for (int meshIdx = 0; meshIdx < numSubMeshes; ++meshIdx) { subMeshCutoffArray[meshIdx] = subMeshTransparentArray[meshIdx] ? true : subMeshCutoffArray[meshIdx]; } } // Propagate the opacity mask only if all sub materials are opaque bool isOpaque = !hasTransparentSubMaterial; if (isOpaque) { instanceFlag |= (uint)(RayTracingRendererFlag.Opaque); } if (rayTracedShadow || pathTracingEnabled) { if (hasTransparentSubMaterial) { // Raise the shadow casting flag if needed instanceFlag |= ((currentRenderer.shadowCastingMode != ShadowCastingMode.Off) ? (uint)(RayTracingRendererFlag.CastShadowTransparent) : 0x00); } else { // Raise the shadow casting flag if needed instanceFlag |= ((currentRenderer.shadowCastingMode != ShadowCastingMode.Off) ? (uint)(RayTracingRendererFlag.CastShadowOpaque) : 0x00); } } // We consider a mesh visible by reflection, gi, etc if it is not in the shadow only mode. bool meshIsVisible = currentRenderer.shadowCastingMode != ShadowCastingMode.ShadowsOnly; if (aoEnabled && !materialIsOnlyTransparent && meshIsVisible) { // Raise the Ambient Occlusion flag if needed instanceFlag |= ((aoLayerValue & objectLayerValue) != 0) ? (uint)(RayTracingRendererFlag.AmbientOcclusion) : 0x00; } if (reflEnabled && !materialIsOnlyTransparent && meshIsVisible) { // Raise the Screen Space Reflection flag if needed instanceFlag |= ((reflLayerValue & objectLayerValue) != 0) ? (uint)(RayTracingRendererFlag.Reflection) : 0x00; } if (giEnabled && !materialIsOnlyTransparent && meshIsVisible) { // Raise the Global Illumination flag if needed instanceFlag |= ((giLayerValue & objectLayerValue) != 0) ? (uint)(RayTracingRendererFlag.GlobalIllumination) : 0x00; } if (recursiveEnabled && meshIsVisible) { // Raise the Recursive Rendering flag if needed instanceFlag |= ((rrLayerValue & objectLayerValue) != 0) ? (uint)(RayTracingRendererFlag.RecursiveRendering) : 0x00; } if (pathTracingEnabled && meshIsVisible) { // Raise the Path Tracing flag if needed instanceFlag |= (uint)(RayTracingRendererFlag.PathTracing); } // If the object was not referenced if (instanceFlag == 0) return AccelerationStructureStatus.Added; // Add it to the acceleration structure m_CurrentRAS.AddInstance(currentRenderer, subMeshMask: subMeshFlagArray, subMeshTransparencyFlags: subMeshCutoffArray, enableTriangleCulling: !doubleSided, mask: instanceFlag); // Indicates that a transform has changed in our scene (mesh or light) m_TransformDirty |= currentRenderer.transform.hasChanged; currentRenderer.transform.hasChanged = false; // return the status return (!materialIsOnlyTransparent && hasTransparentSubMaterial) ? AccelerationStructureStatus.TransparencyIssue : AccelerationStructureStatus.Added; } internal void BuildRayTracingAccelerationStructure(HDCamera hdCamera) { // Clear all the per frame-data m_RayTracingRendererReference.Clear(); m_RayTracingLights.hdDirectionalLightArray.Clear(); m_RayTracingLights.hdPointLightArray.Clear(); m_RayTracingLights.hdLineLightArray.Clear(); m_RayTracingLights.hdRectLightArray.Clear(); m_RayTracingLights.hdLightArray.Clear(); m_RayTracingLights.reflectionProbeArray.Clear(); m_RayTracingLights.lightCount = 0; m_CurrentRAS.Dispose(); m_CurrentRAS = new RayTracingAccelerationStructure(); m_ValidRayTracingState = false; m_ValidRayTracingCluster = false; m_ValidRayTracingClusterCulling = false; m_RayTracedShadowsRequired = false; m_RayTracedContactShadowsRequired = false; // If the camera does not have a ray tracing frame setting or it is a preview camera (due to the fact that the sphere does not exist as a game object we can't create the RTAS) we do not want to build a RTAS if (!hdCamera.frameSettings.IsEnabled(FrameSettingsField.RayTracing)) return; // We only support ray traced shadows if the camera supports ray traced shadows bool screenSpaceShadowsSupported = hdCamera.frameSettings.IsEnabled(FrameSettingsField.ScreenSpaceShadows); // fetch all the lights in the scene HDAdditionalLightData[] hdLightArray = UnityEngine.GameObject.FindObjectsOfType(); for (int lightIdx = 0; lightIdx < hdLightArray.Length; ++lightIdx) { HDAdditionalLightData hdLight = hdLightArray[lightIdx]; if (hdLight.enabled) { // Check if there is a ray traced shadow in the scene m_RayTracedShadowsRequired |= (hdLight.useRayTracedShadows && screenSpaceShadowsSupported); m_RayTracedContactShadowsRequired |= (hdLight.useContactShadow.@override && hdLight.rayTraceContactShadow); // Indicates that a transform has changed in our scene (mesh or light) m_TransformDirty |= hdLight.transform.hasChanged; hdLight.transform.hasChanged = false; switch (hdLight.type) { case HDLightType.Directional: m_RayTracingLights.hdDirectionalLightArray.Add(hdLight); break; case HDLightType.Point: case HDLightType.Spot: m_RayTracingLights.hdPointLightArray.Add(hdLight); break; case HDLightType.Area: switch (hdLight.areaLightShape) { case AreaLightShape.Rectangle: m_RayTracingLights.hdRectLightArray.Add(hdLight); break; case AreaLightShape.Tube: m_RayTracingLights.hdLineLightArray.Add(hdLight); break; //TODO: case AreaLightShape.Disc: } break; } } } // Aggregate the shadow requirement bool rayTracedShadows = m_RayTracedShadowsRequired || m_RayTracedContactShadowsRequired; m_RayTracingLights.hdLightArray.AddRange(m_RayTracingLights.hdPointLightArray); m_RayTracingLights.hdLightArray.AddRange(m_RayTracingLights.hdLineLightArray); m_RayTracingLights.hdLightArray.AddRange(m_RayTracingLights.hdRectLightArray); HDAdditionalReflectionData[] reflectionProbeArray = UnityEngine.GameObject.FindObjectsOfType(); for (int reflIdx = 0; reflIdx < reflectionProbeArray.Length; ++reflIdx) { HDAdditionalReflectionData reflectionProbe = reflectionProbeArray[reflIdx]; // Add it to the list if enabled if (reflectionProbe.enabled) { m_RayTracingLights.reflectionProbeArray.Add(reflectionProbe); } } m_RayTracingLights.lightCount = m_RayTracingLights.hdPointLightArray.Count + m_RayTracingLights.hdLineLightArray.Count + m_RayTracingLights.hdRectLightArray.Count + m_RayTracingLights.reflectionProbeArray.Count; AmbientOcclusion aoSettings = hdCamera.volumeStack.GetComponent(); bool rtAOEnabled = aoSettings.rayTracing.value && hdCamera.frameSettings.IsEnabled(FrameSettingsField.SSAO); ScreenSpaceReflection reflSettings = hdCamera.volumeStack.GetComponent(); bool rtREnabled = reflSettings.enabled.value && reflSettings.rayTracing.value && hdCamera.frameSettings.IsEnabled(FrameSettingsField.SSR); GlobalIllumination giSettings = hdCamera.volumeStack.GetComponent(); bool rtGIEnabled = giSettings.enable.value && giSettings.rayTracing.value && hdCamera.frameSettings.IsEnabled(FrameSettingsField.SSGI); RecursiveRendering recursiveSettings = hdCamera.volumeStack.GetComponent(); bool rrEnabled = recursiveSettings.enable.value; SubSurfaceScattering sssSettings = hdCamera.volumeStack.GetComponent(); bool rtSSSEnabled = sssSettings.rayTracing.value && hdCamera.frameSettings.IsEnabled(FrameSettingsField.SubsurfaceScattering); PathTracing pathTracingSettings = hdCamera.volumeStack.GetComponent(); bool ptEnabled = pathTracingSettings.enable.value; // We need to check if we should be building the ray tracing acceleration structure (if required by any effect) bool rayTracingRequired = rtAOEnabled || rtREnabled || rtGIEnabled || rrEnabled || rtSSSEnabled || ptEnabled || rayTracedShadows; if (!rayTracingRequired) return; // We need to process the emissive meshes of the rectangular area lights for (var i = 0; i < m_RayTracingLights.hdRectLightArray.Count; i++) { // Fetch the current renderer of the rectangular area light (if any) MeshRenderer currentRenderer = m_RayTracingLights.hdRectLightArray[i].emissiveMeshRenderer; // If there is none it means that there is no emissive mesh for this light if (currentRenderer == null) continue; // This objects should be included into the RAS AddInstanceToRAS(currentRenderer, rayTracedShadows, rtAOEnabled, aoSettings.layerMask.value, rtREnabled, reflSettings.layerMask.value, rtGIEnabled, giSettings.layerMask.value, rrEnabled, recursiveSettings.layerMask.value, ptEnabled, pathTracingSettings.layerMask.value); } int matCount = m_MaterialCRCs.Count; LODGroup[] lodGroupArray = UnityEngine.GameObject.FindObjectsOfType(); for (var i = 0; i < lodGroupArray.Length; i++) { // Grab the current LOD group LODGroup lodGroup = lodGroupArray[i]; // Get the set of LODs LOD[] lodArray = lodGroup.GetLODs(); for (int lodIdx = 0; lodIdx < lodArray.Length; ++lodIdx) { LOD currentLOD = lodArray[lodIdx]; // We only want to push to the acceleration structure the lod0, we do not have defined way to select the right LOD at the moment if (lodIdx == 0) { for (int rendererIdx = 0; rendererIdx < currentLOD.renderers.Length; ++rendererIdx) { // Fetch the renderer that we are interested in Renderer currentRenderer = currentLOD.renderers[rendererIdx]; // This objects should but included into the RAS AddInstanceToRAS(currentRenderer, rayTracedShadows, aoSettings.rayTracing.value, aoSettings.layerMask.value, reflSettings.rayTracing.value, reflSettings.layerMask.value, giSettings.rayTracing.value, giSettings.layerMask.value, recursiveSettings.enable.value, recursiveSettings.layerMask.value, pathTracingSettings.enable.value, pathTracingSettings.layerMask.value); } } // Add them to the processed set so that they are not taken into account when processing all the renderers for (int rendererIdx = 0; rendererIdx < currentLOD.renderers.Length; ++rendererIdx) { Renderer currentRenderer = currentLOD.renderers[rendererIdx]; if (currentRenderer == null) continue; // Add this fella to the renderer list // Unfortunately, we need to check that this renderer was not already pushed into the list (happens if the user uses the same mesh renderer // for two LODs) if (!m_RayTracingRendererReference.ContainsKey(currentRenderer.GetInstanceID())) m_RayTracingRendererReference.Add(currentRenderer.GetInstanceID(), 1); } } } // Grab all the renderers from the scene var rendererArray = UnityEngine.GameObject.FindObjectsOfType(); for (var i = 0; i < rendererArray.Length; i++) { // Fetch the current renderer Renderer currentRenderer = rendererArray[i]; // If it is not active skip it if (currentRenderer.enabled == false) continue; // Grab the current game object GameObject gameObject = currentRenderer.gameObject; // Has this object already been processed, just skip it if (m_RayTracingRendererReference.ContainsKey(currentRenderer.GetInstanceID())) { continue; } // Does this object have a reflection probe component? if yes we do not want to have it in the acceleration structure if (gameObject.TryGetComponent(out reflectionProbe)) continue; // This objects should be included into the RAS AddInstanceToRAS(currentRenderer, rayTracedShadows, aoSettings.rayTracing.value, aoSettings.layerMask.value, reflSettings.rayTracing.value, reflSettings.layerMask.value, giSettings.rayTracing.value, giSettings.layerMask.value, recursiveSettings.enable.value, recursiveSettings.layerMask.value, pathTracingSettings.enable.value, pathTracingSettings.layerMask.value); } // Check if the amount of materials being tracked has changed m_MaterialsDirty |= (matCount != m_MaterialCRCs.Count); if (ShaderConfig.s_CameraRelativeRendering != 0) m_CurrentRAS.Build(hdCamera.camera.transform.position); else m_CurrentRAS.Build(); // tag the structures as valid m_ValidRayTracingState = true; } static internal bool ValidRayTracingHistory(HDCamera hdCamera) { return hdCamera.historyRTHandleProperties.previousViewportSize.x == hdCamera.actualWidth && hdCamera.historyRTHandleProperties.previousViewportSize.y == hdCamera.actualHeight; } internal int RayTracingFrameIndex(HDCamera hdCamera) { #if UNITY_HDRP_DXR_TESTS_DEFINE if (Application.isPlaying) return 0; else #endif return (int)hdCamera.GetCameraFrameCount() % 8; } internal int RayTracingFrameIndex(HDCamera hdCamera, int targetFrameCount = 8) { #if UNITY_HDRP_DXR_TESTS_DEFINE if (Application.isPlaying) return 0; else #endif return (int)hdCamera.GetCameraFrameCount() % targetFrameCount; } internal bool RayTracingLightClusterRequired(HDCamera hdCamera) { ScreenSpaceReflection reflSettings = hdCamera.volumeStack.GetComponent(); GlobalIllumination giSettings = hdCamera.volumeStack.GetComponent(); RecursiveRendering recursiveSettings = hdCamera.volumeStack.GetComponent(); PathTracing pathTracingSettings = hdCamera.volumeStack.GetComponent(); SubSurfaceScattering subSurface = hdCamera.volumeStack.GetComponent(); return (m_ValidRayTracingState && (reflSettings.rayTracing.value || giSettings.rayTracing.value || recursiveSettings.enable.value || pathTracingSettings.enable.value || subSurface.rayTracing.value)); } internal void CullForRayTracing(CommandBuffer cmd, HDCamera hdCamera) { if (m_ValidRayTracingState && RayTracingLightClusterRequired(hdCamera)) { m_RayTracingLightCluster.CullForRayTracing(hdCamera, m_RayTracingLights); m_ValidRayTracingClusterCulling = true; } } internal void ReserveRayTracingCookieAtlasSlots() { if (m_ValidRayTracingState && m_ValidRayTracingClusterCulling) { m_RayTracingLightCluster.ReserveCookieAtlasSlots(m_RayTracingLights); } } internal void BuildRayTracingLightData(CommandBuffer cmd, HDCamera hdCamera, DebugDisplaySettings debugDisplaySettings) { if (m_ValidRayTracingState && m_ValidRayTracingClusterCulling) { m_RayTracingLightCluster.BuildRayTracingLightData(cmd, hdCamera, m_RayTracingLights, debugDisplaySettings); m_ValidRayTracingCluster = true; UpdateShaderVariablesRaytracingLightLoopCB(hdCamera, cmd); m_RayTracingLightCluster.BuildLightClusterBuffer(cmd, hdCamera, m_RayTracingLights); } } static internal float EvaluateHistoryValidity(HDCamera hdCamera) { 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; return historyValidity; } void UpdateShaderVariablesRaytracingLightLoopCB(HDCamera hdCamera, CommandBuffer cmd) { m_ShaderVariablesRaytracingLightLoopCB._MinClusterPos = m_RayTracingLightCluster.GetMinClusterPos(); m_ShaderVariablesRaytracingLightLoopCB._LightPerCellCount = (uint)m_RayTracingLightCluster.GetLightPerCellCount(); m_ShaderVariablesRaytracingLightLoopCB._MaxClusterPos = m_RayTracingLightCluster.GetMaxClusterPos(); m_ShaderVariablesRaytracingLightLoopCB._PunctualLightCountRT = (uint)m_RayTracingLightCluster.GetPunctualLightCount(); m_ShaderVariablesRaytracingLightLoopCB._AreaLightCountRT = (uint)m_RayTracingLightCluster.GetAreaLightCount(); m_ShaderVariablesRaytracingLightLoopCB._EnvLightCountRT = (uint)m_RayTracingLightCluster.GetEnvLightCount(); ConstantBuffer.PushGlobal(cmd, m_ShaderVariablesRaytracingLightLoopCB, HDShaderIDs._ShaderVariablesRaytracingLightLoop); } internal bool RayTracedContactShadowsRequired() { return m_RayTracedContactShadowsRequired; } internal RayTracingAccelerationStructure RequestAccelerationStructure() { if (m_ValidRayTracingState) { return m_CurrentRAS; } return null; } internal HDRaytracingLightCluster RequestLightCluster() { if (m_ValidRayTracingCluster) { return m_RayTracingLightCluster; } return null; } // Ray Tracing is supported if the asset setting supports it and the platform supports it static internal bool GatherRayTracingSupport(RenderPipelineSettings rpSetting) => rpSetting.supportRayTracing && rayTracingSupportedBySystem; static internal bool rayTracingSupportedBySystem => UnityEngine.SystemInfo.supportsRayTracing #if UNITY_EDITOR && (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.StandaloneWindows64 || UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.StandaloneWindows) #endif ; internal BlueNoise GetBlueNoiseManager() { return m_BlueNoise; } internal HDTemporalFilter GetTemporalFilter() { if (m_TemporalFilter == null && m_RayTracingSupported) { m_TemporalFilter = new HDTemporalFilter(); m_TemporalFilter.Init(m_Asset.renderPipelineRayTracingResources); } return m_TemporalFilter; } internal HDSimpleDenoiser GetSimpleDenoiser() { if (m_SimpleDenoiser == null) { m_SimpleDenoiser = new HDSimpleDenoiser(); m_SimpleDenoiser.Init(m_Asset.renderPipelineRayTracingResources); } return m_SimpleDenoiser; } internal SSGIDenoiser GetSSGIDenoiser() { if (m_SSGIDenoiser == null) { m_SSGIDenoiser = new SSGIDenoiser(); m_SSGIDenoiser.Init(m_Asset.renderPipelineResources); } return m_SSGIDenoiser; } internal HDDiffuseDenoiser GetDiffuseDenoiser() { if (m_DiffuseDenoiser == null) { m_DiffuseDenoiser = new HDDiffuseDenoiser(); m_DiffuseDenoiser.Init(m_Asset.renderPipelineResources, m_Asset.renderPipelineRayTracingResources, this); } return m_DiffuseDenoiser; } internal HDReflectionDenoiser GetReflectionDenoiser() { if (m_ReflectionDenoiser == null) { m_ReflectionDenoiser = new HDReflectionDenoiser(); m_ReflectionDenoiser.Init(m_Asset.renderPipelineRayTracingResources); } return m_ReflectionDenoiser; } internal HDDiffuseShadowDenoiser GetDiffuseShadowDenoiser() { if (m_DiffuseShadowDenoiser == null) { m_DiffuseShadowDenoiser = new HDDiffuseShadowDenoiser(); m_DiffuseShadowDenoiser.Init(m_Asset.renderPipelineRayTracingResources); } return m_DiffuseShadowDenoiser; } internal bool GetRayTracingState() { return m_ValidRayTracingState; } internal bool GetRayTracingClusterState() { return m_ValidRayTracingCluster; } static internal float GetPixelSpreadTangent(float fov, int width, int height) { return Mathf.Tan(fov * Mathf.Deg2Rad * 0.5f) * 2.0f / Mathf.Min(width, height); } static internal float GetPixelSpreadAngle(float fov, int width, int height) { return Mathf.Atan(GetPixelSpreadTangent(fov, width, height)); } internal TextureHandle EvaluateHistoryValidationBuffer(RenderGraph renderGraph, HDCamera hdCamera, TextureHandle depthBuffer, TextureHandle normalBuffer, TextureHandle motionVectorsBuffer) { // Grab the temporal filter HDTemporalFilter temporalFilter = GetTemporalFilter(); // If the temporal filter is valid use it, otherwise return a white texture if (temporalFilter != null) { float historyValidity = EvaluateHistoryValidity(hdCamera); HistoryValidityParameters parameters = temporalFilter.PrepareHistoryValidityParameters(hdCamera, historyValidity); return temporalFilter.HistoryValidity(renderGraph, hdCamera, parameters, depthBuffer, normalBuffer, motionVectorsBuffer); } else return renderGraph.defaultResources.whiteTexture; } } }