예제 #1
0
        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;
        }