Exemple #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;
            }
        }
        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) || hdCamera.camera.cameraType == CameraType.Preview)
            {
                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 <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
                    m_RayTracedShadowsRequired        |= (hdLight.useRayTracedShadows && screenSpaceShadowsSupported);
                    m_RayTracedContactShadowsRequired |= (hdLight.useContactShadow.@override && hdLight.rayTraceContactShadow);

                    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 <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          = hdCamera.volumeStack.GetComponent <AmbientOcclusion>();
            bool                  rtAOEnabled         = aoSettings.rayTracing.value && hdCamera.frameSettings.IsEnabled(FrameSettingsField.SSAO);
            ScreenSpaceReflection reflSettings        = hdCamera.volumeStack.GetComponent <ScreenSpaceReflection>();
            bool                  rtREnabled          = reflSettings.enabled.value && reflSettings.rayTracing.value && hdCamera.frameSettings.IsEnabled(FrameSettingsField.SSR);
            GlobalIllumination    giSettings          = hdCamera.volumeStack.GetComponent <GlobalIllumination>();
            bool                  rtGIEnabled         = giSettings.enable.value && giSettings.rayTracing.value && hdCamera.frameSettings.IsEnabled(FrameSettingsField.SSGI);
            RecursiveRendering    recursiveSettings   = hdCamera.volumeStack.GetComponent <RecursiveRendering>();
            bool                  rrEnabled           = recursiveSettings.enable.value;
            SubSurfaceScattering  sssSettings         = hdCamera.volumeStack.GetComponent <SubSurfaceScattering>();
            bool                  rtSSSEnabled        = sssSettings.rayTracing.value && hdCamera.frameSettings.IsEnabled(FrameSettingsField.SubsurfaceScattering);
            PathTracing           pathTracingSettings = hdCamera.volumeStack.GetComponent <PathTracing>();
            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 <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,
                                             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];
                        // 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 <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 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);

            // build the acceleration structure
            m_CurrentRAS.Build();

            // tag the structures as valid
            m_ValidRayTracingState = true;
        }
        public void RenderLightVolumes(RenderGraph renderGraph, LightingDebugSettings lightingDebugSettings, TextureHandle destination, TextureHandle depthBuffer, CullingResults cullResults, HDCamera hdCamera)
        {
            using (var builder = renderGraph.AddRenderPass <RenderLightVolumesPassData>("LightVolumes", out var passData))
            {
                bool lightOverlapEnabled = CoreUtils.IsLightOverlapDebugEnabled(hdCamera.camera);
                bool useColorAndEdge     = lightingDebugSettings.lightVolumeDebugByCategory == LightVolumeDebug.ColorAndEdge || lightOverlapEnabled;

                passData.hdCamera    = hdCamera;
                passData.cullResults = cullResults;
                passData.debugLightVolumeMaterial = m_DebugLightVolumeMaterial;
                passData.debugLightVolumeCS       = m_DebugLightVolumeCompute;
                passData.debugLightVolumeKernel   = useColorAndEdge ? m_DebugLightVolumeColorsKernel : m_DebugLightVolumeGradientKernel;
                passData.maxDebugLightCount       = (int)lightingDebugSettings.maxDebugLightCount;
                passData.borderRadius             = lightOverlapEnabled ? 0.5f : 1f;
                passData.colorGradientTexture     = m_ColorGradientTexture;
                passData.lightOverlapEnabled      = lightOverlapEnabled;
                passData.lightCountBuffer         = builder.CreateTransientTexture(new TextureDesc(Vector2.one, true, true)
                {
                    colorFormat = GraphicsFormat.R32_SFloat, clearBuffer = true, clearColor = Color.black, name = "LightVolumeCount"
                });
                passData.colorAccumulationBuffer = builder.CreateTransientTexture(new TextureDesc(Vector2.one, true, true)
                {
                    colorFormat = GraphicsFormat.R16G16B16A16_SFloat, clearBuffer = true, clearColor = Color.black, name = "LightVolumeColorAccumulation"
                });
                passData.debugLightVolumesTexture = builder.CreateTransientTexture(new TextureDesc(Vector2.one, true, true)
                {
                    colorFormat = GraphicsFormat.R16G16B16A16_SFloat, clearBuffer = true, clearColor = Color.black, enableRandomWrite = true, name = "LightVolumeDebugLightVolumesTexture"
                });
                passData.depthBuffer = builder.UseDepthBuffer(depthBuffer, DepthAccess.ReadWrite);
                passData.destination = builder.WriteTexture(destination);

                builder.SetRenderFunc(
                    (RenderLightVolumesPassData data, RenderGraphContext ctx) =>
                {
                    var mpb = ctx.renderGraphPool.GetTempMaterialPropertyBlock();
                    RenderTargetIdentifier[] mrt = ctx.renderGraphPool.GetTempArray <RenderTargetIdentifier>(2);
                    mrt[0] = data.lightCountBuffer;
                    mrt[1] = data.colorAccumulationBuffer;

                    if (data.lightOverlapEnabled)
                    {
                        // We only need the accumulation buffer, not the color (we only display the outline of the light shape in this mode).
                        CoreUtils.SetRenderTarget(ctx.cmd, mrt[0], depthBuffer);

                        // The cull result doesn't contains overlapping lights so we use a custom list
                        foreach (var overlappingHDLight in HDAdditionalLightData.s_overlappingHDLights)
                        {
                            RenderLightVolume(ctx.cmd, data.debugLightVolumeMaterial, overlappingHDLight, overlappingHDLight.legacyLight, mpb);
                        }
                    }
                    else
                    {
                        // Set the render target array
                        CoreUtils.SetRenderTarget(ctx.cmd, mrt, depthBuffer);

                        // First of all let's do the regions for the light sources (we only support Punctual and Area)
                        int numLights = data.cullResults.visibleLights.Length;
                        for (int lightIdx = 0; lightIdx < numLights; ++lightIdx)
                        {
                            // Let's build the light's bounding sphere matrix
                            Light currentLegacyLight = data.cullResults.visibleLights[lightIdx].light;
                            if (currentLegacyLight == null)
                            {
                                continue;
                            }
                            HDAdditionalLightData currentHDRLight = currentLegacyLight.GetComponent <HDAdditionalLightData>();
                            if (currentHDRLight == null)
                            {
                                continue;
                            }

                            RenderLightVolume(ctx.cmd, data.debugLightVolumeMaterial, currentHDRLight, currentLegacyLight, mpb);
                        }

                        // When we enable the light overlap mode we hide probes as they can't be baked in shadow masks
                        if (!data.lightOverlapEnabled)
                        {
                            // Now let's do the same but for reflection probes
                            int numProbes = data.cullResults.visibleReflectionProbes.Length;
                            for (int probeIdx = 0; probeIdx < numProbes; ++probeIdx)
                            {
                                // Let's build the light's bounding sphere matrix
                                ReflectionProbe currentLegacyProbe        = data.cullResults.visibleReflectionProbes[probeIdx].reflectionProbe;
                                HDAdditionalReflectionData currentHDProbe = currentLegacyProbe.GetComponent <HDAdditionalReflectionData>();

                                if (!currentHDProbe)
                                {
                                    continue;
                                }

                                MaterialPropertyBlock m_MaterialProperty = new MaterialPropertyBlock();
                                Mesh targetMesh = null;
                                if (currentHDProbe.influenceVolume.shape == InfluenceShape.Sphere)
                                {
                                    m_MaterialProperty.SetVector(_RangeShaderID, new Vector3(currentHDProbe.influenceVolume.sphereRadius, currentHDProbe.influenceVolume.sphereRadius, currentHDProbe.influenceVolume.sphereRadius));
                                    targetMesh = DebugShapes.instance.RequestSphereMesh();
                                }
                                else
                                {
                                    m_MaterialProperty.SetVector(_RangeShaderID, new Vector3(currentHDProbe.influenceVolume.boxSize.x, currentHDProbe.influenceVolume.boxSize.y, currentHDProbe.influenceVolume.boxSize.z));
                                    targetMesh = DebugShapes.instance.RequestBoxMesh();
                                }

                                m_MaterialProperty.SetColor(_ColorShaderID, new Color(1.0f, 1.0f, 0.0f, 1.0f));
                                m_MaterialProperty.SetVector(_OffsetShaderID, new Vector3(0, 0, 0));
                                Matrix4x4 positionMat = Matrix4x4.Translate(currentLegacyProbe.transform.position);
                                ctx.cmd.DrawMesh(targetMesh, positionMat, data.debugLightVolumeMaterial, 0, 0, m_MaterialProperty);
                            }
                        }
                    }

                    // Set the input params for the compute
                    ctx.cmd.SetComputeTextureParam(data.debugLightVolumeCS, data.debugLightVolumeKernel, _DebugLightCountBufferShaderID, data.lightCountBuffer);
                    ctx.cmd.SetComputeTextureParam(data.debugLightVolumeCS, data.debugLightVolumeKernel, _DebugColorAccumulationBufferShaderID, data.colorAccumulationBuffer);
                    ctx.cmd.SetComputeTextureParam(data.debugLightVolumeCS, data.debugLightVolumeKernel, _DebugLightVolumesTextureShaderID, data.debugLightVolumesTexture);
                    ctx.cmd.SetComputeTextureParam(data.debugLightVolumeCS, data.debugLightVolumeKernel, _ColorGradientTextureShaderID, data.colorGradientTexture);
                    ctx.cmd.SetComputeIntParam(data.debugLightVolumeCS, _MaxDebugLightCountShaderID, data.maxDebugLightCount);
                    ctx.cmd.SetComputeFloatParam(data.debugLightVolumeCS, _BorderRadiusShaderID, data.borderRadius);

                    // Texture dimensions
                    int texWidth  = data.hdCamera.actualWidth;
                    int texHeight = data.hdCamera.actualHeight;

                    // Dispatch the compute
                    int lightVolumesTileSize = 8;
                    int numTilesX            = (texWidth + (lightVolumesTileSize - 1)) / lightVolumesTileSize;
                    int numTilesY            = (texHeight + (lightVolumesTileSize - 1)) / lightVolumesTileSize;
                    ctx.cmd.DispatchCompute(data.debugLightVolumeCS, data.debugLightVolumeKernel, numTilesX, numTilesY, data.hdCamera.viewCount);

                    // Blit this into the camera target
                    CoreUtils.SetRenderTarget(ctx.cmd, destination);
                    mpb.SetTexture(HDShaderIDs._BlitTexture, data.debugLightVolumesTexture);
                    ctx.cmd.DrawProcedural(Matrix4x4.identity, data.debugLightVolumeMaterial, 1, MeshTopology.Triangles, 3, 1, mpb);
                });
            }
        }
Exemple #4
0
        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;

            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 || (hdLight.useContactShadow.@override && hdLight.rayTraceContactShadow));

                    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;
                    }
                }
            }

            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          = hdCamera.volumeStack.GetComponent <AmbientOcclusion>();
            ScreenSpaceReflection reflSettings        = hdCamera.volumeStack.GetComponent <ScreenSpaceReflection>();
            GlobalIllumination    giSettings          = hdCamera.volumeStack.GetComponent <GlobalIllumination>();
            RecursiveRendering    recursiveSettings   = hdCamera.volumeStack.GetComponent <RecursiveRendering>();
            PathTracing           pathTracingSettings = hdCamera.volumeStack.GetComponent <PathTracing>();

            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;
        }
        void CollectLightsForRayTracing(HDCamera hdCamera, ref bool transformDirty)
        {
            // fetch all the lights in the scene
            HDLightRenderDatabase lightEntities = HDLightRenderDatabase.instance;

            for (int lightIdx = 0; lightIdx < lightEntities.lightCount; ++lightIdx)
            {
                HDLightRenderEntity   lightRenderEntity = lightEntities.lightEntities[lightIdx];
                HDAdditionalLightData hdLight           = lightEntities.hdAdditionalLightData[lightIdx];
                if (hdLight != null && hdLight.enabled && hdLight != HDUtils.s_DefaultHDAdditionalLightData)
                {
                    // Flag that needs to be overriden by the light and tells us if the light will need the RTAS
                    bool hasRayTracedShadows = false;

                    // Indicates that a transform has changed in our scene (mesh or light)
                    transformDirty |= hdLight.transform.hasChanged;
                    hdLight.transform.hasChanged = false;

                    switch (hdLight.type)
                    {
                    case HDLightType.Directional:
                    {
                        hasRayTracedShadows = hdLight.ShadowsEnabled() && hdLight.useScreenSpaceShadows && hdLight.useRayTracedShadows;
                        m_RayTracingLights.hdDirectionalLightArray.Add(hdLight);
                    }
                    break;

                    case HDLightType.Point:
                    case HDLightType.Spot:
                    {
                        hasRayTracedShadows = hdLight.ShadowsEnabled() && hdLight.useRayTracedShadows;
                        m_RayTracingLights.hdPointLightArray.Add(lightRenderEntity);
                    }
                    break;

                    case HDLightType.Area:
                    {
                        hasRayTracedShadows = hdLight.ShadowsEnabled() && hdLight.useRayTracedShadows;
                        switch (hdLight.areaLightShape)
                        {
                        case AreaLightShape.Rectangle:
                            m_RayTracingLights.hdRectLightArray.Add(lightRenderEntity);
                            break;

                        case AreaLightShape.Tube:
                            m_RayTracingLights.hdLineLightArray.Add(lightRenderEntity);
                            break;
                            //TODO: case AreaLightShape.Disc:
                        }
                        break;
                    }
                    }

                    // Check if there is a ray traced shadow in the scene
                    m_RayTracedShadowsRequired        |= hasRayTracedShadows;
                    m_RayTracedContactShadowsRequired |= (hdLight.useContactShadow.@override && hdLight.rayTraceContactShadow);
                }
            }

            // Add the lights to the structure
            m_RayTracingLights.hdLightEntityArray.AddRange(m_RayTracingLights.hdPointLightArray);
            m_RayTracingLights.hdLightEntityArray.AddRange(m_RayTracingLights.hdLineLightArray);
            m_RayTracingLights.hdLightEntityArray.AddRange(m_RayTracingLights.hdRectLightArray);

            // Process the lights
            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
                // Skip the probe if the probe has never rendered (in real time cases) or if texture is null
                if (reflectionProbe != null &&
                    reflectionProbe.enabled &&
                    reflectionProbe.ReflectionProbeIsEnabled() &&
                    reflectionProbe.gameObject.activeSelf &&
                    reflectionProbe.HasValidRenderedData())
                {
                    m_RayTracingLights.reflectionProbeArray.Add(reflectionProbe);
                }
            }

            m_RayTracingLights.lightCount = m_RayTracingLights.hdPointLightArray.Count
                                            + m_RayTracingLights.hdLineLightArray.Count
                                            + m_RayTracingLights.hdRectLightArray.Count
                                            + m_RayTracingLights.reflectionProbeArray.Count;
        }