public HDRaytracingLightCluster RequestLightCluster(LayerMask layerMask) { HDRayTracingSubScene currentSubScene = null; if (m_SubScenes.TryGetValue(layerMask.value, out currentSubScene)) { return(currentSubScene.valid ? currentSubScene.lightCluster : null); } return(null); }
public HDRayTracingSubScene RequestSubScene(LayerMask layerMask) { HDRayTracingSubScene currentSubScene = null; if (m_SubScenes.TryGetValue(layerMask.value, out currentSubScene)) { return(currentSubScene.valid ? currentSubScene : null); } return(null); }
public RaytracingAccelerationStructure RequestAccelerationStructure(LayerMask layerMask) { HDRayTracingSubScene currentSubScene = null; if (m_SubScenes.TryGetValue(layerMask.value, out currentSubScene)) { return(currentSubScene.valid ? currentSubScene.accelerationStructure : null); } return(null); }
// This function finds which sub-scenes are going to be used for the camera and computes their light clusters public void UpdateCameraData(CommandBuffer cmd, HDCamera hdCamera) { // Set all the acceleration structures that are currently allocated to not updated foreach (var subScene in m_SubScenes) { subScene.Value.needUpdate = false; } // Grab the current environment HDRaytracingEnvironment rtEnv = CurrentEnvironment(); if (rtEnv == null) { return; } // If Reflection is on flag its light cluster // if (rtEnv.raytracedReflections) { HDRayTracingSubScene currentSubScene = RequestSubScene(rtEnv.reflLayerMask); currentSubScene.needUpdate = true; } // If Primary Visibility is on flag its light cluster // if (rtEnv.raytracedObjects) { HDRayTracingSubScene currentSubScene = RequestSubScene(rtEnv.raytracedLayerMask); currentSubScene.needUpdate = true; } // If indirect diffuse is on flag its light cluster // if (rtEnv.raytracedIndirectDiffuse) { HDRayTracingSubScene currentSubScene = RequestSubScene(rtEnv.indirectDiffuseLayerMask); currentSubScene.needUpdate = true; } // Let's go through all the sub-scenes that are flagged needUpdate and update their light clusters foreach (var subScene in m_SubScenes) { HDRayTracingSubScene currentSubScene = subScene.Value; // If it need update, go through it if (currentSubScene.needUpdate) { // Evaluate the light cluster currentSubScene.lightCluster.EvaluateLightClusters(cmd, hdCamera, currentSubScene.lights); // It doesn't need RAS update anymore currentSubScene.needUpdate = false; } } }
public void DestroySubSceneStructure(ref HDRayTracingSubScene subScene) { if (subScene.accelerationStructure != null) { subScene.accelerationStructure.Dispose(); subScene.targetRenderers = null; subScene.accelerationStructure = null; subScene.hdLightArray = null; subScene.lightCluster.ReleaseResources(); subScene.lightCluster = null; } }
public void DestroySubSceneStructure(ref HDRayTracingSubScene subScene) { if (subScene.accelerationStructure != null) { for (var i = 0; i < subScene.targetRenderers.Count; i++) { subScene.accelerationStructure.RemoveInstance(subScene.targetRenderers[i]); } subScene.accelerationStructure.Dispose(); subScene.targetRenderers = null; subScene.accelerationStructure = null; } }
public void Release() { // Destroy all the sub-scenes foreach (var subScene in m_SubScenes) { HDRayTracingSubScene currentSubScene = subScene.Value; DestroySubSceneStructure(ref currentSubScene); } // Clear the sub-scenes list m_SubScenes.Clear(); m_RayCountManager.Release(); }
// This function is to be called when the layers used for an effect have changed. It is called either through the inspector or using the scripting API public void UpdateEnvironmentSubScenes() { // Grab the current environment HDRaytracingEnvironment rtEnv = CurrentEnvironment(); // We do not have any current environment, we need to clear all the subscenes we have and leave. if (rtEnv == null) { foreach (var subScene in m_SubScenes) { // Destroy the sub-scene to remove HDRayTracingSubScene currentSubscene = subScene.Value; DestroySubSceneStructure(ref currentSubscene); } m_SubScenes.Clear(); return; } // Update the references for the sub-scenes UpdateEffectSubScene(rtEnv.aoLayerMask.value, 0); UpdateEffectSubScene(rtEnv.reflLayerMask.value, 1); UpdateEffectSubScene(rtEnv.shadowLayerMask.value, 2); UpdateEffectSubScene(rtEnv.raytracedLayerMask.value, 3); UpdateEffectSubScene(rtEnv.indirectDiffuseLayerMask.value, 4); // Let's now go through all the sub-scenes and delete the ones that are not referenced by anyone var nonReferencedSubScenes = m_SubScenes.Where(x => x.Value.references == 0).ToArray(); foreach (var subScene in nonReferencedSubScenes) { // Destroy the sub-scene to remove HDRayTracingSubScene currentSubscene = subScene.Value; DestroySubSceneStructure(ref currentSubscene); // Remove it from the array m_SubScenes.Remove(subScene.Key); } }
public void UpdateSubSceneData(CommandBuffer cmd, HDCamera hdCamera) { HDRayTracingSubScene subScene = RequestSubScene(hdCamera); if (subScene != null) { // Update the acceleration structure if (subScene.accelerationStructure != null) { for (var i = 0; i < subScene.targetRenderers.Count; i++) { if (subScene.targetRenderers[i] != null) { subScene.accelerationStructure.UpdateInstanceTransform(subScene.targetRenderers[i]); } } subScene.accelerationStructure.Update(); } // Evaluate the light cluster subScene.lightCluster.EvaluateLightClusters(cmd, hdCamera, subScene.hdLightArray); } }
public void BuildSubSceneStructure(ref HDRayTracingSubScene subScene) { // Destroy the acceleration structure subScene.targetRenderers = new List <Renderer>(); // Create the acceleration structure subScene.accelerationStructure = new RaytracingAccelerationStructure(); // Grab all the renderers from the scene var rendererArray = UnityEngine.GameObject.FindObjectsOfType <Renderer>(); for (var i = 0; i < rendererArray.Length; i++) { // Convert the object's layer to an int int objectLayerValue = 1 << rendererArray[i].gameObject.layer; // Is this object in one of the allowed layers ? if ((objectLayerValue & subScene.mask.value) != 0) { // Add this fella to the renderer list subScene.targetRenderers.Add(rendererArray[i]); } } // If any object build the acceleration structure if (subScene.targetRenderers.Count != 0) { for (var i = 0; i < subScene.targetRenderers.Count; i++) { // Add it to the acceleration structure subScene.accelerationStructure.AddInstance(subScene.targetRenderers[i]); } } // build the acceleration structure subScene.accelerationStructure.Build(); }
public void InitAccelerationStructures() { // Create the sub-scene structure m_SubScenes = new Dictionary <int, HDRayTracingSubScene>(); // Grab all the ray tracing graphs in the scene HDRayTracingFilter[] tracingGraphs = UnityEngine.Object.FindObjectsOfType <HDRayTracingFilter>(); m_LayerMasks = new List <int>(); // Build an array with all the layer combinations that are requested for (var filterIndex = 0; filterIndex < tracingGraphs.Length; filterIndex++) { // Grab the current graph HDRayTracingFilter currentFilter = tracingGraphs[filterIndex]; // Fetch or create the sub-scene HDRayTracingSubScene currentSubScene = null; if (!m_SubScenes.TryGetValue(currentFilter.layermask.value, out currentSubScene)) { currentSubScene = new HDRayTracingSubScene(); currentSubScene.mask = currentFilter.layermask.value; m_SubScenes.Add(currentFilter.layermask.value, currentSubScene); m_LayerMasks.Add(currentFilter.layermask.value); } // Mark the current graph for a reference currentSubScene.referenceFilters.Add(currentFilter); } // Create all the ray tracing for (var subSceneIndex = 0; subSceneIndex < m_LayerMasks.Count; subSceneIndex++) { HDRayTracingSubScene currentSubScene = m_SubScenes[m_LayerMasks[subSceneIndex]]; BuildSubSceneStructure(ref currentSubScene); } }
public void BuildSubSceneStructure(ref HDRayTracingSubScene subScene) { // If there is no render environments, then we should not generate acceleration structure if (m_Environments.Count > 0) { // This structure references all the renderers that are considered to be processed Dictionary <int, int> rendererReference = new Dictionary <int, int>(); // Destroy the acceleration structure subScene.targetRenderers = new List <Renderer>(); // Create the acceleration structure subScene.accelerationStructure = new Experimental.Rendering.RayTracingAccelerationStructure(); // We need to define the maximal number of meshes for our geometries int maxNumSubMeshes = 1; // First of all let's process all the LOD groups LODGroup[] lodGroupArray = UnityEngine.GameObject.FindObjectsOfType <LODGroup>(); 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 first fella if (lodIdx == 0) { for (int rendererIdx = 0; rendererIdx < currentLOD.renderers.Length; ++rendererIdx) { // Convert the object's layer to an int int objectLayerValue = 1 << currentLOD.renderers[rendererIdx].gameObject.layer; // Is this object in one of the allowed layers ? if ((objectLayerValue & subScene.mask.value) != 0) { Renderer currentRenderer = currentLOD.renderers[rendererIdx]; // Add this fella to the renderer list subScene.targetRenderers.Add(currentRenderer); // Also, we need to contribute to the maximal number of sub-meshes MeshFilter currentFilter = currentRenderer.GetComponent <MeshFilter>(); if (currentFilter != null && currentFilter.sharedMesh != null) { maxNumSubMeshes = Mathf.Max(maxNumSubMeshes, currentFilter.sharedMesh.subMeshCount); } } } } // Add them to the processed set for (int rendererIdx = 0; rendererIdx < currentLOD.renderers.Length; ++rendererIdx) { Renderer currentRenderer = currentLOD.renderers[rendererIdx]; // Add this fella to the renderer list rendererReference.Add(currentRenderer.GetInstanceID(), 1); } } } // Grab all the renderers from the scene var rendererArray = UnityEngine.GameObject.FindObjectsOfType <Renderer>(); 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, jsut skip if (rendererReference.ContainsKey(currentRenderer.GetInstanceID())) { continue; } // Does this object have a reflection probe component? if yes we do not want to see it in the raytracing environment ReflectionProbe targetProbe = gameObject.GetComponent <ReflectionProbe>(); if (targetProbe != null) { continue; } // Convert the object's layer to an int int objectLayerValue = 1 << currentRenderer.gameObject.layer; // Is this object in one of the allowed layers ? if ((objectLayerValue & subScene.mask.value) != 0) { // Add this fella to the renderer list subScene.targetRenderers.Add(currentRenderer); } // Also, we need to contribute to the maximal number of sub-meshes MeshFilter currentFilter = currentRenderer.GetComponent <MeshFilter>(); if (currentFilter != null && currentFilter.sharedMesh != null) { maxNumSubMeshes = Mathf.Max(maxNumSubMeshes, currentFilter.sharedMesh.subMeshCount); } } bool[] subMeshFlagArray = new bool[maxNumSubMeshes]; bool[] subMeshCutoffArray = new bool[maxNumSubMeshes]; // If any object build the acceleration structure if (subScene.targetRenderers.Count != 0) { // For all the renderers that we need to push in the acceleration structure for (var i = 0; i < subScene.targetRenderers.Count; i++) { // Grab the current renderer Renderer currentRenderer = subScene.targetRenderers[i]; bool singleSided = false; if (currentRenderer.sharedMaterials != null) { // For every sub-mesh/sub-material let's build the right flags int numSubMeshes = currentRenderer.sharedMaterials.Length; // We need to build the instance flag for this renderer uint instanceFlag = 0x00; // Incorporate the shadow casting flag instanceFlag |= ((currentRenderer.shadowCastingMode == ShadowCastingMode.On) ? (uint)(1 << 2) : 0x00); for (int meshIdx = 0; meshIdx < numSubMeshes; ++meshIdx) { Material currentMaterial = currentRenderer.sharedMaterials[meshIdx]; // The material is transparent if either it has the requested keyword or is in the transparent queue range if (currentMaterial != null) { subMeshFlagArray[meshIdx] = true; // Is the material transparent? bool materialIsTransparent = currentMaterial.IsKeywordEnabled("_SURFACE_TYPE_TRANSPARENT") || (HDRenderQueue.k_RenderQueue_Transparent.lowerBound <= currentMaterial.renderQueue && HDRenderQueue.k_RenderQueue_Transparent.upperBound >= currentMaterial.renderQueue) || (HDRenderQueue.k_RenderQueue_AllTransparentRaytracing.lowerBound <= currentMaterial.renderQueue && HDRenderQueue.k_RenderQueue_AllTransparentRaytracing.upperBound >= currentMaterial.renderQueue); // Propagate the right mask instanceFlag |= materialIsTransparent ? (uint)(1 << 1) : (uint)(1 << 0); // 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); // Force it to be non single sided if it has the keyword if there is a reason bool doubleSided = currentMaterial.doubleSidedGI || currentMaterial.IsKeywordEnabled("_DOUBLESIDED_ON"); singleSided |= !doubleSided; } else { subMeshFlagArray[meshIdx] = false; subMeshCutoffArray[meshIdx] = false; singleSided = true; } } // Add it to the acceleration structure subScene.accelerationStructure.AddInstance(currentRenderer, subMeshMask: subMeshFlagArray, subMeshTransparencyFlags: subMeshCutoffArray, enableTriangleCulling: singleSided, mask: instanceFlag); } } } // build the acceleration structure subScene.accelerationStructure.Build(); // Allocate the array for the lights subScene.lights = new HDRayTracingLights(); subScene.lights.hdLightArray = new List <HDAdditionalLightData>(); subScene.lights.hdDirectionalLightArray = new List <HDAdditionalLightData>(); // fetch all the lights HDAdditionalLightData[] hdLightArray = UnityEngine.GameObject.FindObjectsOfType <HDAdditionalLightData>(); // Here an important thing is to make sure that the point lights are first in the list then line then area List <HDAdditionalLightData> pointLights = new List <HDAdditionalLightData>(); List <HDAdditionalLightData> lineLights = new List <HDAdditionalLightData>(); List <HDAdditionalLightData> rectLights = new List <HDAdditionalLightData>(); for (int lightIdx = 0; lightIdx < hdLightArray.Length; ++lightIdx) { HDAdditionalLightData hdLight = hdLightArray[lightIdx]; if (hdLight.enabled) { // Convert the object's layer to an int int lightayerValue = 1 << hdLight.gameObject.layer; if ((lightayerValue & subScene.mask.value) != 0) { if (hdLight.GetComponent <Light>().type == LightType.Directional) { subScene.lights.hdDirectionalLightArray.Add(hdLight); } else { if (hdLight.lightTypeExtent == LightTypeExtent.Punctual) { pointLights.Add(hdLight); } else if (hdLight.lightTypeExtent == LightTypeExtent.Tube) { lineLights.Add(hdLight); } else { rectLights.Add(hdLight); } } } } } subScene.lights.hdLightArray.AddRange(pointLights); subScene.lights.hdLightArray.AddRange(lineLights); subScene.lights.hdLightArray.AddRange(rectLights); // Fetch all the reflection probes in the scene subScene.lights.reflectionProbeArray = new List <HDProbe>(); HDAdditionalReflectionData[] reflectionProbeArray = UnityEngine.GameObject.FindObjectsOfType <HDAdditionalReflectionData>(); for (int reflIdx = 0; reflIdx < reflectionProbeArray.Length; ++reflIdx) { HDAdditionalReflectionData reflectionProbe = reflectionProbeArray[reflIdx]; // Add it to the list if enabled if (reflectionProbe.enabled) { subScene.lights.reflectionProbeArray.Add(reflectionProbe); } } // Build the light cluster subScene.lightCluster = new HDRaytracingLightCluster(); subScene.lightCluster.Initialize(m_Resources, m_RTResources, this, m_SharedRTManager, m_RenderPipeline); // Mark this sub-scene as valid subScene.valid = true; } else { subScene.valid = false; } }
// This function defines which acceleration structures are going to be used during the following frame // and updates their RAS public void UpdateFrameData() { // Set all the acceleration structures that are currently allocated to not updated foreach (var subScene in m_SubScenes) { subScene.Value.needUpdate = false; } // Grab the current environment HDRaytracingEnvironment rtEnv = CurrentEnvironment(); if (rtEnv == null) { return; } // If AO is on flag its RAS needUpdate // if (rtEnv.raytracedAO) { HDRayTracingSubScene currentSubScene = RequestSubScene(rtEnv.aoLayerMask); currentSubScene.needUpdate = true; } // If Reflection is on flag its RAS needUpdate // if (rtEnv.raytracedReflections) { HDRayTracingSubScene currentSubScene = RequestSubScene(rtEnv.reflLayerMask); currentSubScene.needUpdate = true; } // If Area Shadow is on flag its RAS needUpdate //if (rtEnv.raytracedShadows) { HDRayTracingSubScene currentSubScene = RequestSubScene(rtEnv.shadowLayerMask); currentSubScene.needUpdate = true; } // If Primary Visibility is on flag its RAS needUpdate // if (rtEnv.raytracedObjects) { HDRayTracingSubScene currentSubScene = RequestSubScene(rtEnv.raytracedLayerMask); currentSubScene.needUpdate = true; } // If indirect diffuse is on flag its RAS needUpdate // if (rtEnv.raytracedIndirectDiffuse) { HDRayTracingSubScene currentSubScene = RequestSubScene(rtEnv.indirectDiffuseLayerMask); currentSubScene.needUpdate = true; } // Let's go through all the sub-scenes that are flagged needUpdate and update their RAS foreach (var subScene in m_SubScenes) { HDRayTracingSubScene currentSubScene = subScene.Value; if (currentSubScene.accelerationStructure != null && currentSubScene.needUpdate) { for (var i = 0; i < currentSubScene.targetRenderers.Count; i++) { if (currentSubScene.targetRenderers[i] != null) { currentSubScene.accelerationStructure.UpdateInstanceTransform(currentSubScene.targetRenderers[i]); } } currentSubScene.accelerationStructure.Update(); // It doesn't need RAS update anymore currentSubScene.needUpdate = false; } } }
public void CheckSubScenes() { // Here there is two options, either the full things needs to be rebuilded or we should only rebuild the ones that have been flagged obsolete if (m_DirtyEnvironment) { // First of let's reset all the obsolescence flags int numFilters = m_Filters.Count; for (int filterIdx = 0; filterIdx < numFilters; ++filterIdx) { // Grab the target graph component HDRayTracingFilter filterComponent = m_Filters[filterIdx]; // If this camera had a graph component had an obsolete flag if (filterComponent != null) { filterComponent.ResetDirty(); } } // Also let's mark all the sub-scenes as obsolete for (var subSceneIndex = 0; subSceneIndex < m_LayerMasks.Count; subSceneIndex++) { HDRayTracingSubScene currentSubScene = m_SubScenes[m_LayerMasks[subSceneIndex]]; currentSubScene.obsolete = true; } m_DirtyEnvironment = false; } else { // First of all propagate the obsolete flags to the sub scenes int numGraphs = m_Filters.Count; for (int filterIdx = 0; filterIdx < numGraphs; ++filterIdx) { // Grab the target graph component HDRayTracingFilter filterComponent = m_Filters[filterIdx]; // If this camera had a graph component had an obsolete flag if (filterComponent != null && filterComponent.IsDirty()) { // Get the sub-scene that matches HDRayTracingSubScene currentSubScene = null; if (m_SubScenes.TryGetValue(filterComponent.layermask, out currentSubScene)) { currentSubScene.obsolete = true; } filterComponent.ResetDirty(); } } } // Rebuild all the obsolete scenes for (var subSceneIndex = 0; subSceneIndex < m_LayerMasks.Count; subSceneIndex++) { // Grab the current sub-scene HDRayTracingSubScene subScene = m_SubScenes[m_LayerMasks[subSceneIndex]]; // Does this scene need rebuilding? if (subScene.obsolete) { DestroySubSceneStructure(ref subScene); BuildSubSceneStructure(ref subScene); subScene.obsolete = false; } } }