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; } }
public void BuildRayTracingAccelerationStructure() { // 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; bool rayTracedShadow = false; // fetch all the lights in the scene HDAdditionalLightData[] hdLightArray = UnityEngine.GameObject.FindObjectsOfType <HDAdditionalLightData>(); 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 rayTracedShadow |= hdLight.useRayTracedShadows; if (hdLight.GetComponent <Light>().type == LightType.Directional) { m_RayTracingLights.hdDirectionalLightArray.Add(hdLight); } else { if (hdLight.lightTypeExtent == LightTypeExtent.Punctual) { m_RayTracingLights.hdPointLightArray.Add(hdLight); } else if (hdLight.lightTypeExtent == LightTypeExtent.Tube) { m_RayTracingLights.hdLineLightArray.Add(hdLight); } else { m_RayTracingLights.hdRectLightArray.Add(hdLight); } } } } 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 <HDAdditionalReflectionData>(); 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 = VolumeManager.instance.stack.GetComponent <AmbientOcclusion>(); ScreenSpaceReflection reflSettings = VolumeManager.instance.stack.GetComponent <ScreenSpaceReflection>(); GlobalIllumination giSettings = VolumeManager.instance.stack.GetComponent <GlobalIllumination>(); RecursiveRendering recursiveSettings = VolumeManager.instance.stack.GetComponent <RecursiveRendering>(); PathTracing pathTracingSettings = VolumeManager.instance.stack.GetComponent <PathTracing>(); // 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 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, rayTracedShadow, 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]; // Add this fella to the renderer list m_RayTracingRendererReference.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, 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 <ReflectionProbe>(out reflectionProbe)) { continue; } // This objects should but included into the RAS AddInstanceToRAS(currentRenderer, rayTracedShadow, 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); } // build the acceleration structure m_CurrentRAS.Build(); // tag the structures as valid m_ValidRayTracingState = true; }