internal bool LightIsPendingPlacement(HDAdditionalLightData light, ShadowMapType shadowMapType)
        {
            if (shadowMapType == ShadowMapType.PunctualAtlas)
            {
                return(punctualShadowAtlas.LightIsPendingPlacement(light));
            }
            if (shadowMapType == ShadowMapType.AreaLightAtlas)
            {
                return(areaShadowAtlas.LightIsPendingPlacement(light));
            }

            return(false);
        }
        internal void RemoveTransformFromCache(HDAdditionalLightData lightData)
        {
            HDLightType lightType = lightData.type;

            if (lightType == HDLightType.Spot || lightType == HDLightType.Point)
            {
                punctualShadowAtlas.RemoveTransformFromCache(lightData);
            }
            if (ShaderConfig.s_AreaLights == 1 && lightType == HDLightType.Area)
            {
                areaShadowAtlas.RemoveTransformFromCache(lightData);
            }
        }
        public void ReserveCookieAtlasSlots(HDRayTracingLights rayTracingLights)
        {
            for (int lightIdx = 0; lightIdx < rayTracingLights.hdLightArray.Count; ++lightIdx)
            {
                // Grab the additional light data to process
                HDAdditionalLightData additionalLightData = rayTracingLights.hdLightArray[lightIdx];

                // Fetch the light component for this light
                additionalLightData.gameObject.TryGetComponent(out lightComponent);

                // Reserve the cookie resolution in the 2D atlas
                m_RenderPipeline.ReserveCookieAtlasTexture(additionalLightData, lightComponent, additionalLightData.type);
            }
        }
Example #4
0
        internal bool FullLightShadowHasRenderedAtLeastOnce(HDAdditionalLightData lightData)
        {
            int cachedShadowIdx = lightData.lightIdxForCachedShadows;

            if (lightData.type == HDLightType.Point)
            {
                bool allRendered = true;
                for (int i = 0; i < 6; ++i)
                {
                    allRendered = allRendered && m_ShadowsWithValidData.ContainsKey(cachedShadowIdx + i);
                }

                return(allRendered);
            }
            return(m_ShadowsWithValidData.ContainsKey(cachedShadowIdx));
        }
        internal void RegisterTransformToCache(HDAdditionalLightData lightData)
        {
            HDLightType lightType = lightData.type;

            if (lightType == HDLightType.Spot || lightType == HDLightType.Point)
            {
                punctualShadowAtlas.RegisterTransformCacheSlot(lightData);
            }
            if (ShaderConfig.s_AreaLights == 1 && lightType == HDLightType.Area)
            {
                areaShadowAtlas.RegisterTransformCacheSlot(lightData);
            }
            if (lightType == HDLightType.Directional)
            {
                m_CachedDirectionalAngles = lightData.transform.eulerAngles;
            }
        }
        internal void ScheduleShadowUpdate(HDAdditionalLightData light)
        {
            var lightType = light.type;

            if (lightType == HDLightType.Point || lightType == HDLightType.Spot)
            {
                punctualShadowAtlas.ScheduleShadowUpdate(light);
            }
            else if (lightType == HDLightType.Area)
            {
                areaShadowAtlas.ScheduleShadowUpdate(light);
            }
            else if (lightType == HDLightType.Directional)
            {
                MarkAllDirectionalShadowsForUpdate();
            }
        }
        internal void EvictLight(HDAdditionalLightData lightData)
        {
            HDLightType lightType = lightData.type;

            if (lightType == HDLightType.Directional)
            {
                lightData.lightIdxForCachedShadows = -1;
                MarkAllDirectionalShadowsForUpdate();
            }

            if (lightType == HDLightType.Spot || lightType == HDLightType.Point)
            {
                punctualShadowAtlas.EvictLight(lightData);
            }

            if (ShaderConfig.s_AreaLights == 1 && lightType == HDLightType.Area)
            {
                areaShadowAtlas.EvictLight(lightData);
            }
        }
        internal void RegisterLight(HDAdditionalLightData lightData)
        {
            HDLightType lightType = lightData.type;

            if (lightType == HDLightType.Directional)
            {
                lightData.lightIdxForCachedShadows = 0;
                MarkAllDirectionalShadowsForUpdate();
            }

            if (lightType == HDLightType.Spot || lightType == HDLightType.Point)
            {
                punctualShadowAtlas.RegisterLight(lightData);
            }

            if (ShaderConfig.s_AreaLights == 1 && lightType == HDLightType.Area && lightData.areaLightShape == AreaLightShape.Rectangle)
            {
                areaShadowAtlas.RegisterLight(lightData);
            }
        }
Example #9
0
        internal void RegisterLight(HDAdditionalLightData lightData)
        {
            // If we are trying to register something that we have already placed, we do nothing
            if (lightData.lightIdxForCachedShadows >= 0 && m_PlacedShadows.ContainsKey(lightData.lightIdxForCachedShadows))
            {
                return;
            }

            // We register only if not already pending placement and if enabled.
            if (!m_RegisteredLightDataPendingPlacement.ContainsKey(lightData.lightIdxForCachedShadows) && lightData.isActiveAndEnabled)
            {
#if UNITY_2020_2_OR_NEWER
                lightData.legacyLight.useViewFrustumForShadowCasterCull = false;
#endif
                lightData.lightIdxForCachedShadows = GetNextLightIdentifier();
                RegisterTransformCacheSlot(lightData);
                m_RegisteredLightDataPendingPlacement.Add(lightData.lightIdxForCachedShadows, lightData);
                m_CanTryPlacement = true;
            }
        }
Example #10
0
        bool RenderLightScreenSpaceShadows(HDCamera hdCamera, CommandBuffer cmd)
        {
            using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.RaytracingLightShadow)))
            {
                using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.RaytracingLightShadow)))
                {
                    // Loop through all the potential screen space light shadows
                    for (int lightIdx = 0; lightIdx < m_ScreenSpaceShadowIndex; ++lightIdx)
                    {
                        // This matches the directional light
                        if (!m_CurrentScreenSpaceShadowData[lightIdx].valid)
                        {
                            continue;
                        }

                        // Fetch the light data and additional light data
                        LightData             currentLight = m_lightList.lights[m_CurrentScreenSpaceShadowData[lightIdx].lightDataIndex];
                        HDAdditionalLightData currentAdditionalLightData = m_CurrentScreenSpaceShadowData[lightIdx].additionalLightData;

                        // Trigger the right algorithm based on the light type
                        switch (currentLight.lightType)
                        {
                        case GPULightType.Rectangle:
                        {
                            RenderAreaScreenSpaceShadow(cmd, hdCamera, currentLight, currentAdditionalLightData, m_CurrentScreenSpaceShadowData[lightIdx].lightDataIndex);
                        }
                        break;

                        case GPULightType.Point:
                        case GPULightType.Spot:
                        {
                            RenderPunctualScreenSpaceShadow(cmd, hdCamera, currentLight, currentAdditionalLightData, m_CurrentScreenSpaceShadowData[lightIdx].lightDataIndex);
                        }
                        break;
                        }
                    }
                }
                return(true);
            }
        }
        // We do our own hash here because Unity does not provide correct hash for builtin types
        // Moreover, we don't want to test every single parameters of the light so we filter them here in this specific function.
        int GetSunLightHashCode(Light light)
        {
            HDAdditionalLightData ald = light.GetComponent <HDAdditionalLightData>();

            unchecked
            {
                // Sun could influence the sky (like for procedural sky). We need to handle this possibility. If sun property change, then we need to update the sky
                int hash = 13;
                hash = hash * 23 + light.transform.position.GetHashCode();
                hash = hash * 23 + light.transform.rotation.GetHashCode();
                hash = hash * 23 + light.color.GetHashCode();
                hash = hash * 23 + light.colorTemperature.GetHashCode();
                hash = hash * 23 + light.intensity.GetHashCode();
                // Note: We don't take into account cookie as it doesn't influence GI
                if (ald != null)
                {
                    hash = hash * 23 + ald.lightDimmer.GetHashCode();
                }

                return(hash);
            }
        }
        internal bool NeedRenderingDueToTransformChange(HDAdditionalLightData lightData, HDLightType lightType)
        {
            if (lightData.updateUponLightMovement)
            {
                if (lightType == HDLightType.Directional)
                {
                    float   angleDiffThreshold = lightData.cachedShadowAngleUpdateThreshold;
                    Vector3 angleDiff          = m_CachedDirectionalAngles - lightData.transform.eulerAngles;
                    return(Mathf.Abs(angleDiff.x) > angleDiffThreshold || Mathf.Abs(angleDiff.y) > angleDiffThreshold || Mathf.Abs(angleDiff.z) > angleDiffThreshold);
                }
                else if (lightType == HDLightType.Area)
                {
                    return(areaShadowAtlas.NeedRenderingDueToTransformChange(lightData, lightType));
                }
                else
                {
                    return(punctualShadowAtlas.NeedRenderingDueToTransformChange(lightData, lightType));
                }
            }

            return(false);
        }
Example #13
0
        bool RenderLightScreenSpaceShadows(RenderGraph renderGraph, HDCamera hdCamera,
                                           PrepassOutput prepassOutput, TextureHandle depthBuffer, TextureHandle normalBuffer, TextureHandle motionVectorsBuffer, TextureHandle historyValidityBuffer,
                                           TextureHandle rayCountTexture, TextureHandle screenSpaceShadowArray)
        {
            // Loop through all the potential screen space light shadows
            for (int lightIdx = 0; lightIdx < m_ScreenSpaceShadowIndex; ++lightIdx)
            {
                // This matches the directional light
                if (!m_CurrentScreenSpaceShadowData[lightIdx].valid)
                {
                    continue;
                }

                // Fetch the light data and additional light data
                LightData             currentLight = m_GpuLightsBuilder.lights[m_CurrentScreenSpaceShadowData[lightIdx].lightDataIndex];
                HDAdditionalLightData currentAdditionalLightData = m_CurrentScreenSpaceShadowData[lightIdx].additionalLightData;

                // Trigger the right algorithm based on the light type
                switch (currentLight.lightType)
                {
                case GPULightType.Rectangle:
                {
                    RenderAreaScreenSpaceShadow(renderGraph, hdCamera, currentLight, currentAdditionalLightData, m_CurrentScreenSpaceShadowData[lightIdx].lightDataIndex,
                                                prepassOutput, depthBuffer, normalBuffer, motionVectorsBuffer, rayCountTexture, screenSpaceShadowArray);
                }
                break;

                case GPULightType.Point:
                case GPULightType.Spot:
                {
                    RenderPunctualScreenSpaceShadow(renderGraph, hdCamera, currentLight, currentAdditionalLightData, m_CurrentScreenSpaceShadowData[lightIdx].lightDataIndex,
                                                    prepassOutput, depthBuffer, normalBuffer, motionVectorsBuffer, historyValidityBuffer, rayCountTexture, screenSpaceShadowArray);
                }
                break;
                }
            }
            return(true);
        }
        internal void ScheduleShadowUpdate(HDAdditionalLightData light, int subShadowIndex)
        {
            var lightType = light.type;

            if (lightType == HDLightType.Spot)
            {
                punctualShadowAtlas.ScheduleShadowUpdate(light);
            }
            if (lightType == HDLightType.Area)
            {
                areaShadowAtlas.ScheduleShadowUpdate(light);
            }
            if (lightType == HDLightType.Point)
            {
                Debug.Assert(subShadowIndex < 6);
                punctualShadowAtlas.ScheduleShadowUpdate(light.lightIdxForCachedShadows + subShadowIndex);
            }
            if (lightType == HDLightType.Directional)
            {
                Debug.Assert(subShadowIndex < m_MaxShadowCascades);
                m_DirectionalShadowPendingUpdate[subShadowIndex] = true;
            }
        }
Example #15
0
        internal bool NeedRenderingDueToTransformChange(HDAdditionalLightData lightData, HDLightType lightType)
        {
            bool needUpdate = false;

            if (m_TransformCaches.TryGetValue(lightData.lightIdxForCachedShadows, out CachedTransform cachedTransform))
            {
                float   positionThreshold = lightData.cachedShadowTranslationUpdateThreshold;
                Vector3 positionDiffVec   = cachedTransform.position - lightData.transform.position;
                float   positionDiff      = Vector3.Dot(positionDiffVec, positionDiffVec);
                if (positionDiff > positionThreshold * positionThreshold)
                {
                    needUpdate = true;
                }
                if (lightType != HDLightType.Point)
                {
                    float   angleDiffThreshold = lightData.cachedShadowAngleUpdateThreshold;
                    Vector3 angleDiff          = cachedTransform.angles - lightData.transform.eulerAngles;
                    // Any angle difference
                    if (Mathf.Abs(angleDiff.x) > angleDiffThreshold || Mathf.Abs(angleDiff.y) > angleDiffThreshold || Mathf.Abs(angleDiff.z) > angleDiffThreshold)
                    {
                        needUpdate = true;
                    }
                }

                if (needUpdate)
                {
                    // Update the record (CachedTransform is a struct, so we remove old one and replace with a new one)
                    m_TransformCaches.Remove(lightData.lightIdxForCachedShadows);
                    cachedTransform.position = lightData.transform.position;
                    cachedTransform.angles   = lightData.transform.eulerAngles;
                    m_TransformCaches.Add(lightData.lightIdxForCachedShadows, cachedTransform);
                }
            }

            return(needUpdate);
        }
        void BuildGPULightVolumes(HDCamera hdCamera, HDRayTracingLights rayTracingLights)
        {
            int totalNumLights = rayTracingLights.lightCount;

            // Make sure the light volume buffer has the right size
            if (m_LightVolumesCPUArray == null || totalNumLights != m_LightVolumesCPUArray.Length)
            {
                ResizeVolumeBuffer(totalNumLights);
            }

            // Set Light volume data to the CPU buffer
            punctualLightCount = 0;
            areaLightCount     = 0;
            envLightCount      = 0;
            totalLightCount    = 0;

            int realIndex = 0;

            for (int lightIdx = 0; lightIdx < rayTracingLights.hdLightArray.Count; ++lightIdx)
            {
                HDAdditionalLightData currentLight = rayTracingLights.hdLightArray[lightIdx];

                // When the user deletes a light source in the editor, there is a single frame where the light is null before the collection of light in the scene is triggered
                // the workaround for this is simply to not add it if it is null for that invalid frame
                if (currentLight != null)
                {
                    Light light = currentLight.gameObject.GetComponent <Light>();
                    if (light == null || !light.enabled)
                    {
                        continue;
                    }

                    if (hdCamera.frameSettings.IsEnabled(FrameSettingsField.RayTracing) && !currentLight.includeForRayTracing)
                    {
                        continue;
                    }

                    // Reserve space in the cookie atlas
                    m_RenderPipeline.ReserveCookieAtlasTexture(currentLight, light, currentLight.type);

                    // Compute the camera relative position
                    Vector3 lightPositionRWS = currentLight.gameObject.transform.position;
                    if (ShaderConfig.s_CameraRelativeRendering != 0)
                    {
                        lightPositionRWS -= hdCamera.camera.transform.position;
                    }

                    // Grab the light range
                    float lightRange = light.range;

                    if (currentLight.type != HDLightType.Area)
                    {
                        m_LightVolumesCPUArray[realIndex].range      = new Vector3(lightRange, lightRange, lightRange);
                        m_LightVolumesCPUArray[realIndex].position   = lightPositionRWS;
                        m_LightVolumesCPUArray[realIndex].active     = (currentLight.gameObject.activeInHierarchy ? 1 : 0);
                        m_LightVolumesCPUArray[realIndex].lightIndex = (uint)lightIdx;
                        m_LightVolumesCPUArray[realIndex].shape      = 0;
                        m_LightVolumesCPUArray[realIndex].lightType  = 0;
                        punctualLightCount++;
                    }
                    else
                    {
                        // let's compute the oobb of the light influence volume first
                        Vector3 oobbDimensions = new Vector3(currentLight.shapeWidth + 2 * lightRange, currentLight.shapeHeight + 2 * lightRange, lightRange); // One-sided
                        Vector3 extents        = 0.5f * oobbDimensions;
                        Vector3 oobbCenter     = lightPositionRWS + extents.z * currentLight.gameObject.transform.forward;

                        // Let's now compute an AABB that matches the previously defined OOBB
                        OOBBToAABBBounds(oobbCenter, extents, currentLight.gameObject.transform.up, currentLight.gameObject.transform.right, currentLight.gameObject.transform.forward, ref bounds);

                        // Fill the volume data
                        m_LightVolumesCPUArray[realIndex].range      = bounds.extents;
                        m_LightVolumesCPUArray[realIndex].position   = bounds.center;
                        m_LightVolumesCPUArray[realIndex].active     = (currentLight.gameObject.activeInHierarchy ? 1 : 0);
                        m_LightVolumesCPUArray[realIndex].lightIndex = (uint)lightIdx;
                        m_LightVolumesCPUArray[realIndex].shape      = 1;
                        m_LightVolumesCPUArray[realIndex].lightType  = 1;
                        areaLightCount++;
                    }
                    realIndex++;
                }
            }

            int indexOffset = realIndex;

            // Set Env Light volume data to the CPU buffer
            for (int lightIdx = 0; lightIdx < rayTracingLights.reflectionProbeArray.Count; ++lightIdx)
            {
                HDProbe currentEnvLight = rayTracingLights.reflectionProbeArray[lightIdx];

                // Compute the camera relative position
                Vector3 probePositionRWS = currentEnvLight.influenceToWorld.GetColumn(3);
                if (ShaderConfig.s_CameraRelativeRendering != 0)
                {
                    probePositionRWS -= hdCamera.camera.transform.position;
                }

                if (currentEnvLight != null)
                {
                    if (currentEnvLight.influenceVolume.shape == InfluenceShape.Sphere)
                    {
                        m_LightVolumesCPUArray[lightIdx + indexOffset].shape    = 0;
                        m_LightVolumesCPUArray[lightIdx + indexOffset].range    = new Vector3(currentEnvLight.influenceVolume.sphereRadius, currentEnvLight.influenceVolume.sphereRadius, currentEnvLight.influenceVolume.sphereRadius);
                        m_LightVolumesCPUArray[lightIdx + indexOffset].position = probePositionRWS;
                    }
                    else
                    {
                        m_LightVolumesCPUArray[lightIdx + indexOffset].shape    = 1;
                        m_LightVolumesCPUArray[lightIdx + indexOffset].range    = new Vector3(currentEnvLight.influenceVolume.boxSize.x / 2.0f, currentEnvLight.influenceVolume.boxSize.y / 2.0f, currentEnvLight.influenceVolume.boxSize.z / 2.0f);
                        m_LightVolumesCPUArray[lightIdx + indexOffset].position = probePositionRWS;
                    }
                    m_LightVolumesCPUArray[lightIdx + indexOffset].active     = (currentEnvLight.gameObject.activeInHierarchy ? 1 : 0);
                    m_LightVolumesCPUArray[lightIdx + indexOffset].lightIndex = (uint)lightIdx;
                    m_LightVolumesCPUArray[lightIdx + indexOffset].lightType  = 2;
                    envLightCount++;
                }
            }

            totalLightCount = punctualLightCount + areaLightCount + envLightCount;

            // Push the light volumes to the GPU
            m_LightVolumeGPUArray.SetData(m_LightVolumesCPUArray);
        }
Example #17
0
        internal bool LightIsPlaced(HDAdditionalLightData lightData)
        {
            int cachedShadowIdx = lightData.lightIdxForCachedShadows;

            return(cachedShadowIdx >= 0 && m_PlacedShadows.ContainsKey(cachedShadowIdx));
        }
Example #18
0
        void GetLightGPUType(HDAdditionalLightData additionalData, Light light, ref GPULightType gpuLightType, ref LightCategory lightCategory)
        {
            lightCategory = LightCategory.Count;
            gpuLightType  = GPULightType.Point;

            if (additionalData.lightTypeExtent == LightTypeExtent.Punctual)
            {
                lightCategory = LightCategory.Punctual;

                switch (light.type)
                {
                case LightType.Spot:
                    switch (additionalData.spotLightShape)
                    {
                    case SpotLightShape.Cone:
                        gpuLightType = GPULightType.Spot;
                        break;

                    case SpotLightShape.Pyramid:
                        gpuLightType = GPULightType.ProjectorPyramid;
                        break;

                    case SpotLightShape.Box:
                        gpuLightType = GPULightType.ProjectorBox;
                        break;

                    default:
                        Debug.Assert(false, "Encountered an unknown SpotLightShape.");
                        break;
                    }
                    break;

                case LightType.Directional:
                    gpuLightType = GPULightType.Directional;
                    break;

                case LightType.Point:
                    gpuLightType = GPULightType.Point;
                    break;

                default:
                    Debug.Assert(false, "Encountered an unknown LightType.");
                    break;
                }
            }
            else
            {
                lightCategory = LightCategory.Area;

                switch (additionalData.lightTypeExtent)
                {
                case LightTypeExtent.Rectangle:
                    gpuLightType = GPULightType.Rectangle;
                    break;

                case LightTypeExtent.Tube:
                    gpuLightType = GPULightType.Tube;
                    break;

                default:
                    Debug.Assert(false, "Encountered an unknown LightType.");
                    break;
                }
            }
        }
Example #19
0
        // ------------------------------------------------------------------------------------------


        // ------------------------------------------------------------------------------------------
        //                           Functions to query and change state of a shadow
        // ------------------------------------------------------------------------------------------
        internal bool LightIsPendingPlacement(HDAdditionalLightData lightData)
        {
            return(m_RegisteredLightDataPendingPlacement.ContainsKey(lightData.lightIdxForCachedShadows) ||
                   m_RecordsPendingPlacement.ContainsKey(lightData.lightIdxForCachedShadows));
        }
Example #20
0
 internal void RemoveTransformFromCache(HDAdditionalLightData lightData)
 {
     m_TransformCaches.Remove(lightData.lightIdxForCachedShadows);
 }
 TextureHandle DenoisePunctualScreenSpaceShadow(RenderGraph renderGraph, HDCamera hdCamera,
                                                HDAdditionalLightData additionalLightData, in LightData lightData,
 /// <summary>
 /// This function can be used to register a light to the cached shadow system if not already registered. It is necessary to call this function if a light has been
 /// evicted with ForceEvictLight and it needs to be registered again. Please note that a light is automatically registered when enabled or when the shadow update changes
 /// from EveryFrame to OnDemand or OnEnable.
 /// </summary>
 /// <param name="lightData">The light to register.</param>
 public void ForceRegisterLight(HDAdditionalLightData lightData)
 {
     // Note: this is for now just calling the internal API, but having a separate API helps with future
     // changes to the process.
     RegisterLight(lightData);
 }
Example #23
0
        /// <summary>
        /// This hook allows HDRP to init the scene when creating the view
        /// </summary>
        /// <param name="SRI">The StageRuntimeInterface allowing to communicate with the LookDev</param>
        void IDataProvider.FirstInitScene(StageRuntimeInterface SRI)
        {
            Camera camera = SRI.camera;

            camera.allowHDR = true;

            var additionalCameraData = camera.gameObject.AddComponent <HDAdditionalCameraData>();

            additionalCameraData.clearColorMode       = HDAdditionalCameraData.ClearColorMode.Color;
            additionalCameraData.clearDepth           = true;
            additionalCameraData.backgroundColorHDR   = camera.backgroundColor;
            additionalCameraData.volumeAnchorOverride = camera.transform;
            additionalCameraData.volumeLayerMask      = 1 << 31; //31 is the culling layer used in LookDev

            additionalCameraData.customRenderingSettings = true;
            additionalCameraData.renderingPathCustomFrameSettings.SetEnabled(FrameSettingsField.SSR, false);
            // LookDev cameras are enabled/disabled all the time so history is destroyed each frame.
            // In this case we know we want to keep history alive as long as the camera is.
            additionalCameraData.hasPersistentHistory = true;

            Light light = SRI.sunLight;
            HDAdditionalLightData additionalLightData = light.gameObject.AddComponent <HDAdditionalLightData>();

#if UNITY_EDITOR
            HDAdditionalLightData.InitDefaultHDAdditionalLightData(additionalLightData);
#endif
            additionalLightData.intensity = 0f;
            additionalLightData.SetShadowResolution(2048);

            GameObject volumeGO = SRI.AddGameObject(persistent: true);
            volumeGO.name = "StageVolume";
            Volume volume = volumeGO.AddComponent <Volume>();
            volume.isGlobal = true;
            volume.priority = float.MaxValue;
            volume.enabled  = false;


#if UNITY_EDITOR
            // Make sure we invalidate the current volume when first loading a scene.
            int volumeProfileHash = -1;
            UpdateVolumeProfile(volume, out var visualEnvironment, out var sky, ref volumeProfileHash);

            SRI.SRPData = new LookDevDataForHDRP()
            {
                additionalCameraData = additionalCameraData,
                additionalLightData  = additionalLightData,
                visualEnvironment    = visualEnvironment,
                sky    = sky,
                volume = volume,
                currentVolumeProfileHash = volumeProfileHash
            };
#else
            //remove unassigned warnings when building
            SRI.SRPData = new LookDevDataForHDRP()
            {
                additionalCameraData = null,
                additionalLightData  = null,
                visualEnvironment    = null,
                sky    = null,
                volume = null
            };
#endif
        }
Example #24
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;
            }
        }
Example #25
0
        RTSAreaRayTraceParameters PrepareRTSAreaRayTraceParameters(HDCamera hdCamera, HDAdditionalLightData additionalLightData, LightData lightData, int lightIndex)
        {
            RTSAreaRayTraceParameters rtsartParams = new RTSAreaRayTraceParameters();

            // Set the camera parameters
            rtsartParams.texWidth  = hdCamera.actualWidth;
            rtsartParams.texHeight = hdCamera.actualHeight;
            rtsartParams.viewCount = hdCamera.viewCount;

            // Evaluation parameters
            rtsartParams.numSamples = additionalLightData.numRayTracingSamples;
            rtsartParams.lightIndex = lightIndex;
            // We need to build the world to area light matrix
            rtsartParams.worldToLocalMatrix.SetColumn(0, lightData.right);
            rtsartParams.worldToLocalMatrix.SetColumn(1, lightData.up);
            rtsartParams.worldToLocalMatrix.SetColumn(2, lightData.forward);
            // Compensate the  relative rendering if active
            Vector3 lightPositionWS = lightData.positionRWS;

            if (ShaderConfig.s_CameraRelativeRendering != 0)
            {
                lightPositionWS -= hdCamera.camera.transform.position;
            }
            rtsartParams.worldToLocalMatrix.SetColumn(3, lightPositionWS);
            rtsartParams.worldToLocalMatrix.m33 = 1.0f;
            rtsartParams.worldToLocalMatrix     = m_WorldToLocalArea.inverse;
            rtsartParams.historyValidity        = EvaluateHistoryValidity(hdCamera);
            rtsartParams.filterTracedShadow     = additionalLightData.filterTracedShadow;
            rtsartParams.areaShadowSlot         = m_lightList.lights[lightIndex].screenSpaceShadowIndex;
            rtsartParams.filterSize             = additionalLightData.filterSizeTraced;

            // Kernels
            rtsartParams.areaRaytracingShadowPrepassKernel   = m_AreaRaytracingShadowPrepassKernel;
            rtsartParams.areaRaytracingShadowNewSampleKernel = m_AreaRaytracingShadowNewSampleKernel;
            rtsartParams.areaShadowApplyTAAKernel            = m_AreaShadowApplyTAAKernel;
            rtsartParams.areaUpdateAnalyticHistoryKernel     = m_AreaUpdateAnalyticHistoryKernel;
            rtsartParams.areaUpdateShadowHistoryKernel       = m_AreaUpdateShadowHistoryKernel;
            rtsartParams.areaEstimateNoiseKernel             = m_AreaEstimateNoiseKernel;
            rtsartParams.areaFirstDenoiseKernel    = m_AreaFirstDenoiseKernel;
            rtsartParams.areaSecondDenoiseKernel   = m_AreaSecondDenoiseKernel;
            rtsartParams.areaShadowNoDenoiseKernel = m_AreaShadowNoDenoiseKernel;

            // Other parameters
            // Grab the acceleration structure for the target camera
            rtsartParams.accelerationStructure       = RequestAccelerationStructure();
            rtsartParams.shaderVariablesRayTracingCB = m_ShaderVariablesRayTracingCB;
            rtsartParams.screenSpaceShadowsCS        = m_ScreenSpaceShadowsCS;
            rtsartParams.screenSpaceShadowsRT        = m_ScreenSpaceShadowsRT;
            rtsartParams.screenSpaceShadowsFilterCS  = m_ScreenSpaceShadowsFilterCS;
            rtsartParams.scramblingTex = m_Asset.renderPipelineResources.textures.scramblingTex;
            BlueNoise blueNoise = GetBlueNoiseManager();

            rtsartParams.ditheredTextureSet = blueNoise.DitheredTextureSet8SPP();

            return(rtsartParams);
        }
Example #26
0
        internal static void ConvertLightIntensity(LightUnit oldLightUnit, LightUnit newLightUnit, HDAdditionalLightData hdLight, Light light)
        {
            float       intensity     = hdLight.intensity;
            float       luxAtDistance = hdLight.luxAtDistance;
            HDLightType lightType     = hdLight.ComputeLightType(light);

            // For punctual lights
            if (lightType != HDLightType.Area)
            {
                // Lumen ->
                if (oldLightUnit == LightUnit.Lumen && newLightUnit == LightUnit.Candela)
                {
                    intensity = LightUtils.ConvertPunctualLightLumenToCandela(lightType, intensity, light.intensity, hdLight.enableSpotReflector);
                }
                else if (oldLightUnit == LightUnit.Lumen && newLightUnit == LightUnit.Lux)
                {
                    intensity = LightUtils.ConvertPunctualLightLumenToLux(lightType, intensity, light.intensity, hdLight.enableSpotReflector, hdLight.luxAtDistance);
                }
                else if (oldLightUnit == LightUnit.Lumen && newLightUnit == LightUnit.Ev100)
                {
                    intensity = LightUtils.ConvertPunctualLightLumenToEv(lightType, intensity, light.intensity, hdLight.enableSpotReflector);
                }
                // Candela ->
                else if (oldLightUnit == LightUnit.Candela && newLightUnit == LightUnit.Lumen)
                {
                    intensity = LightUtils.ConvertPunctualLightCandelaToLumen(lightType, hdLight.spotLightShape, intensity, hdLight.enableSpotReflector, light.spotAngle, hdLight.aspectRatio);
                }
                else if (oldLightUnit == LightUnit.Candela && newLightUnit == LightUnit.Lux)
                {
                    intensity = LightUtils.ConvertCandelaToLux(intensity, hdLight.luxAtDistance);
                }
                else if (oldLightUnit == LightUnit.Candela && newLightUnit == LightUnit.Ev100)
                {
                    intensity = LightUtils.ConvertCandelaToEv(intensity);
                }
                // Lux ->
                else if (oldLightUnit == LightUnit.Lux && newLightUnit == LightUnit.Lumen)
                {
                    intensity = LightUtils.ConvertPunctualLightLuxToLumen(lightType, hdLight.spotLightShape, intensity, hdLight.enableSpotReflector,
                                                                          light.spotAngle, hdLight.aspectRatio, hdLight.luxAtDistance);
                }
                else if (oldLightUnit == LightUnit.Lux && newLightUnit == LightUnit.Candela)
                {
                    intensity = LightUtils.ConvertLuxToCandela(intensity, hdLight.luxAtDistance);
                }
                else if (oldLightUnit == LightUnit.Lux && newLightUnit == LightUnit.Ev100)
                {
                    intensity = LightUtils.ConvertLuxToEv(intensity, hdLight.luxAtDistance);
                }
                // EV100 ->
                else if (oldLightUnit == LightUnit.Ev100 && newLightUnit == LightUnit.Lumen)
                {
                    intensity = LightUtils.ConvertPunctualLightEvToLumen(lightType, hdLight.spotLightShape, intensity, hdLight.enableSpotReflector,
                                                                         light.spotAngle, hdLight.aspectRatio);
                }
                else if (oldLightUnit == LightUnit.Ev100 && newLightUnit == LightUnit.Candela)
                {
                    intensity = LightUtils.ConvertEvToCandela(intensity);
                }
                else if (oldLightUnit == LightUnit.Ev100 && newLightUnit == LightUnit.Lux)
                {
                    intensity = LightUtils.ConvertEvToLux(intensity, hdLight.luxAtDistance);
                }
            }
            else  // For area lights
            {
                if (oldLightUnit == LightUnit.Lumen && newLightUnit == LightUnit.Nits)
                {
                    intensity = LightUtils.ConvertAreaLightLumenToLuminance(hdLight.areaLightShape, intensity, hdLight.shapeWidth, hdLight.shapeHeight);
                }
                if (oldLightUnit == LightUnit.Nits && newLightUnit == LightUnit.Lumen)
                {
                    intensity = LightUtils.ConvertAreaLightLuminanceToLumen(hdLight.areaLightShape, intensity, hdLight.shapeWidth, hdLight.shapeHeight);
                }
                if (oldLightUnit == LightUnit.Nits && newLightUnit == LightUnit.Ev100)
                {
                    intensity = LightUtils.ConvertLuminanceToEv(intensity);
                }
                if (oldLightUnit == LightUnit.Ev100 && newLightUnit == LightUnit.Nits)
                {
                    intensity = LightUtils.ConvertEvToLuminance(intensity);
                }
                if (oldLightUnit == LightUnit.Ev100 && newLightUnit == LightUnit.Lumen)
                {
                    intensity = LightUtils.ConvertAreaLightEvToLumen(hdLight.areaLightShape, intensity, hdLight.shapeWidth, hdLight.shapeHeight);
                }
                if (oldLightUnit == LightUnit.Lumen && newLightUnit == LightUnit.Ev100)
                {
                    intensity = LightUtils.ConvertAreaLightLumenToEv(hdLight.areaLightShape, intensity, hdLight.shapeWidth, hdLight.shapeHeight);
                }
            }

            hdLight.intensity = intensity;
        }
        void BuildLightData(CommandBuffer cmd, HDCamera hdCamera, HDRayTracingLights rayTracingLights, DebugDisplaySettings debugDisplaySettings)
        {
            // If no lights, exit
            if (rayTracingLights.lightCount == 0)
            {
                ResizeLightDataBuffer(1);
                return;
            }

            // Also we need to build the light list data
            if (m_LightDataGPUArray == null || m_LightDataGPUArray.count != rayTracingLights.lightCount)
            {
                ResizeLightDataBuffer(rayTracingLights.lightCount);
            }

            m_LightDataCPUArray.Clear();

            // Grab the shadow settings
            var hdShadowSettings = hdCamera.volumeStack.GetComponent <HDShadowSettings>();
            BoolScalableSetting contactShadowScalableSetting = HDAdditionalLightData.ScalableSettings.UseContactShadow(m_RenderPipeline.asset);

            // Build the data for every light
            for (int lightIdx = 0; lightIdx < rayTracingLights.hdLightArray.Count; ++lightIdx)
            {
                // Grab the additinal light data to process
                HDAdditionalLightData additionalLightData = rayTracingLights.hdLightArray[lightIdx];

                LightData lightData = new LightData();
                // When the user deletes a light source in the editor, there is a single frame where the light is null before the collection of light in the scene is triggered
                // the workaround for this is simply to add an invalid light for that frame
                if (additionalLightData == null)
                {
                    m_LightDataCPUArray.Add(lightData);
                    continue;
                }

                // Evaluate all the light type data that we need
                LightCategory   lightCategory   = LightCategory.Count;
                GPULightType    gpuLightType    = GPULightType.Point;
                LightVolumeType lightVolumeType = LightVolumeType.Count;
                HDLightType     lightType       = additionalLightData.type;
                HDRenderPipeline.EvaluateGPULightType(lightType, additionalLightData.spotLightShape, additionalLightData.areaLightShape, ref lightCategory, ref gpuLightType, ref lightVolumeType);

                // Fetch the light component for this light
                additionalLightData.gameObject.TryGetComponent(out lightComponent);

                // Build the processed light data  that we need
                ProcessedLightData processedData = new ProcessedLightData();
                processedData.additionalLightData = additionalLightData;
                processedData.lightType           = additionalLightData.type;
                processedData.lightCategory       = lightCategory;
                processedData.gpuLightType        = gpuLightType;
                processedData.lightVolumeType     = lightVolumeType;
                // Both of these positions are non-camera-relative.
                processedData.distanceToCamera       = (additionalLightData.gameObject.transform.position - hdCamera.camera.transform.position).magnitude;
                processedData.lightDistanceFade      = HDUtils.ComputeLinearDistanceFade(processedData.distanceToCamera, additionalLightData.fadeDistance);
                processedData.volumetricDistanceFade = HDUtils.ComputeLinearDistanceFade(processedData.distanceToCamera, additionalLightData.volumetricFadeDistance);
                processedData.isBakedShadowMask      = HDRenderPipeline.IsBakedShadowMaskLight(lightComponent);

                // Build a visible light
                Color finalColor = lightComponent.color.linear * lightComponent.intensity;
                if (additionalLightData.useColorTemperature)
                {
                    finalColor *= Mathf.CorrelatedColorTemperatureToRGB(lightComponent.colorTemperature);
                }
                visibleLight.finalColor = finalColor;
                visibleLight.range      = lightComponent.range;
                // This should be done explicitely, localtoworld matrix doesn't work here
                localToWorldMatrix.SetColumn(3, lightComponent.gameObject.transform.position);
                localToWorldMatrix.SetColumn(2, lightComponent.transform.forward);
                localToWorldMatrix.SetColumn(1, lightComponent.transform.up);
                localToWorldMatrix.SetColumn(0, lightComponent.transform.right);
                visibleLight.localToWorldMatrix = localToWorldMatrix;
                visibleLight.spotAngle          = lightComponent.spotAngle;

                int     shadowIndex            = additionalLightData.shadowIndex;
                int     screenSpaceShadowIndex = -1;
                int     screenSpaceChannelSlot = -1;
                Vector3 lightDimensions        = new Vector3(0.0f, 0.0f, 0.0f);

                // Use the shared code to build the light data
                m_RenderPipeline.GetLightData(cmd, hdCamera, hdShadowSettings, visibleLight, lightComponent, in processedData,
                                              shadowIndex, contactShadowScalableSetting, isRasterization: false, ref lightDimensions, ref screenSpaceShadowIndex, ref screenSpaceChannelSlot, ref lightData);

                // We make the light position camera-relative as late as possible in order
                // to allow the preceding code to work with the absolute world space coordinates.
                Vector3 camPosWS = hdCamera.mainViewConstants.worldSpaceCameraPos;
                HDRenderPipeline.UpdateLightCameraRelativetData(ref lightData, camPosWS);

                // Set the data for this light
                m_LightDataCPUArray.Add(lightData);
            }

            // Push the data to the GPU
            m_LightDataGPUArray.SetData(m_LightDataCPUArray);
        }
Example #28
0
        void BuildLightData(CommandBuffer cmd, HDCamera hdCamera, List <HDAdditionalLightData> lightArray)
        {
            // If no lights, exit
            if (lightArray.Count == 0)
            {
                ResizeLightDataBuffer(1);
                return;
            }

            // Also we need to build the light list data
            if (m_LightDataGPUArray == null || m_LightDataGPUArray.count != lightArray.Count)
            {
                ResizeLightDataBuffer(lightArray.Count);
            }

            m_LightDataCPUArray.Clear();

            // Build the data for every light
            for (int lightIdx = 0; lightIdx < lightArray.Count; ++lightIdx)
            {
                var lightData = new LightData();

                HDAdditionalLightData additionalLightData = lightArray[lightIdx];
                // When the user deletes a light source in the editor, there is a single frame where the light is null before the collection of light in the scene is triggered
                // the workaround for this is simply to add an invalid light for that frame
                if (additionalLightData == null)
                {
                    m_LightDataCPUArray.Add(lightData);
                    continue;
                }
                Light light = additionalLightData.gameObject.GetComponent <Light>();

                // Both of these positions are non-camera-relative.
                float distanceToCamera  = (light.gameObject.transform.position - hdCamera.camera.transform.position).magnitude;
                float lightDistanceFade = HDUtils.ComputeLinearDistanceFade(distanceToCamera, additionalLightData.fadeDistance);

                bool contributesToLighting = ((additionalLightData.lightDimmer > 0) && (additionalLightData.affectDiffuse || additionalLightData.affectSpecular)) || (additionalLightData.volumetricDimmer > 0);
                contributesToLighting = contributesToLighting && (lightDistanceFade > 0);

                if (!contributesToLighting)
                {
                    continue;
                }

                lightData.lightLayers = additionalLightData.GetLightLayers();
                LightCategory lightCategory = LightCategory.Count;
                GPULightType  gpuLightType  = GPULightType.Point;
                GetLightGPUType(additionalLightData, light, ref gpuLightType, ref lightCategory);

                lightData.lightType = gpuLightType;

                lightData.positionRWS = light.gameObject.transform.position;

                bool applyRangeAttenuation = additionalLightData.applyRangeAttenuation && (gpuLightType != GPULightType.ProjectorBox);

                lightData.range = light.range;

                if (applyRangeAttenuation)
                {
                    lightData.rangeAttenuationScale = 1.0f / (light.range * light.range);
                    lightData.rangeAttenuationBias  = 1.0f;

                    if (lightData.lightType == GPULightType.Rectangle)
                    {
                        // Rect lights are currently a special case because they use the normalized
                        // [0, 1] attenuation range rather than the regular [0, r] one.
                        lightData.rangeAttenuationScale = 1.0f;
                    }
                }
                else // Don't apply any attenuation but do a 'step' at range
                {
                    // Solve f(x) = b - (a * x)^2 where x = (d/r)^2.
                    // f(0) = huge -> b = huge.
                    // f(1) = 0    -> huge - a^2 = 0 -> a = sqrt(huge).
                    const float hugeValue = 16777216.0f;
                    const float sqrtHuge  = 4096.0f;
                    lightData.rangeAttenuationScale = sqrtHuge / (light.range * light.range);
                    lightData.rangeAttenuationBias  = hugeValue;

                    if (lightData.lightType == GPULightType.Rectangle)
                    {
                        // Rect lights are currently a special case because they use the normalized
                        // [0, 1] attenuation range rather than the regular [0, r] one.
                        lightData.rangeAttenuationScale = sqrtHuge;
                    }
                }

                Color value = light.color.linear * light.intensity;
                if (additionalLightData.useColorTemperature)
                {
                    value *= Mathf.CorrelatedColorTemperatureToRGB(light.colorTemperature);
                }
                lightData.color = new Vector3(value.r, value.g, value.b);

                lightData.forward = light.transform.forward;
                lightData.up      = light.transform.up;
                lightData.right   = light.transform.right;

                if (lightData.lightType == GPULightType.ProjectorBox)
                {
                    // Rescale for cookies and windowing.
                    lightData.right *= 2.0f / Mathf.Max(additionalLightData.shapeWidth, 0.001f);
                    lightData.up    *= 2.0f / Mathf.Max(additionalLightData.shapeHeight, 0.001f);
                }
                else if (lightData.lightType == GPULightType.ProjectorPyramid)
                {
                    // Get width and height for the current frustum
                    var spotAngle = light.spotAngle;

                    float frustumWidth, frustumHeight;

                    if (additionalLightData.aspectRatio >= 1.0f)
                    {
                        frustumHeight = 2.0f * Mathf.Tan(spotAngle * 0.5f * Mathf.Deg2Rad);
                        frustumWidth  = frustumHeight * additionalLightData.aspectRatio;
                    }
                    else
                    {
                        frustumWidth  = 2.0f * Mathf.Tan(spotAngle * 0.5f * Mathf.Deg2Rad);
                        frustumHeight = frustumWidth / additionalLightData.aspectRatio;
                    }

                    // Rescale for cookies and windowing.
                    lightData.right *= 2.0f / frustumWidth;
                    lightData.up    *= 2.0f / frustumHeight;
                }

                if (lightData.lightType == GPULightType.Spot)
                {
                    var spotAngle = light.spotAngle;

                    var innerConePercent      = additionalLightData.innerSpotPercent01;
                    var cosSpotOuterHalfAngle = Mathf.Clamp(Mathf.Cos(spotAngle * 0.5f * Mathf.Deg2Rad), 0.0f, 1.0f);
                    var sinSpotOuterHalfAngle = Mathf.Sqrt(1.0f - cosSpotOuterHalfAngle * cosSpotOuterHalfAngle);
                    var cosSpotInnerHalfAngle = Mathf.Clamp(Mathf.Cos(spotAngle * 0.5f * innerConePercent * Mathf.Deg2Rad), 0.0f, 1.0f); // inner cone

                    var val = Mathf.Max(0.0001f, (cosSpotInnerHalfAngle - cosSpotOuterHalfAngle));
                    lightData.angleScale  = 1.0f / val;
                    lightData.angleOffset = -cosSpotOuterHalfAngle * lightData.angleScale;

                    // Rescale for cookies and windowing.
                    float cotOuterHalfAngle = cosSpotOuterHalfAngle / sinSpotOuterHalfAngle;
                    lightData.up    *= cotOuterHalfAngle;
                    lightData.right *= cotOuterHalfAngle;
                }
                else
                {
                    // These are the neutral values allowing GetAngleAnttenuation in shader code to return 1.0
                    lightData.angleScale  = 0.0f;
                    lightData.angleOffset = 1.0f;
                }

                if (lightData.lightType != GPULightType.Directional && lightData.lightType != GPULightType.ProjectorBox)
                {
                    // Store the squared radius of the light to simulate a fill light.
                    lightData.size = new Vector2(additionalLightData.shapeRadius * additionalLightData.shapeRadius, 0);
                }

                if (lightData.lightType == GPULightType.Rectangle || lightData.lightType == GPULightType.Tube)
                {
                    lightData.size = new Vector2(additionalLightData.shapeWidth, additionalLightData.shapeHeight);
                }

                lightData.lightDimmer           = lightDistanceFade * (additionalLightData.lightDimmer);
                lightData.diffuseDimmer         = lightDistanceFade * (additionalLightData.affectDiffuse ? additionalLightData.lightDimmer : 0);
                lightData.specularDimmer        = lightDistanceFade * (additionalLightData.affectSpecular ? additionalLightData.lightDimmer * hdCamera.frameSettings.specularGlobalDimmer : 0);
                lightData.volumetricLightDimmer = lightDistanceFade * (additionalLightData.volumetricDimmer);

                lightData.contactShadowMask      = 0;
                lightData.cookieIndex            = -1;
                lightData.shadowIndex            = -1;
                lightData.screenSpaceShadowIndex = -1;

                if (light != null && light.cookie != null)
                {
                    // TODO: add texture atlas support for cookie textures.
                    switch (light.type)
                    {
                    case LightType.Spot:
                        lightData.cookieIndex = m_RenderPipeline.m_TextureCaches.cookieTexArray.FetchSlice(cmd, light.cookie);
                        break;

                    case LightType.Point:
                        lightData.cookieIndex = m_RenderPipeline.m_TextureCaches.cubeCookieTexArray.FetchSlice(cmd, light.cookie);
                        break;
                    }
                }
                else if (light.type == LightType.Spot && additionalLightData.spotLightShape != SpotLightShape.Cone)
                {
                    // Projectors lights must always have a cookie texture.
                    // As long as the cache is a texture array and not an atlas, the 4x4 white texture will be rescaled to 128
                    lightData.cookieIndex = m_RenderPipeline.m_TextureCaches.cookieTexArray.FetchSlice(cmd, Texture2D.whiteTexture);
                }
                else if (lightData.lightType == GPULightType.Rectangle && additionalLightData.areaLightCookie != null)
                {
                    lightData.cookieIndex = m_RenderPipeline.m_TextureCaches.areaLightCookieManager.FetchSlice(cmd, additionalLightData.areaLightCookie);
                }

                {
                    lightData.shadowDimmer           = 1.0f;
                    lightData.volumetricShadowDimmer = 1.0f;
                }

                {
                    // fix up shadow information
                    lightData.shadowIndex = additionalLightData.shadowIndex;
                }

                // Value of max smoothness is from artists point of view, need to convert from perceptual smoothness to roughness
                lightData.minRoughness = (1.0f - additionalLightData.maxSmoothness) * (1.0f - additionalLightData.maxSmoothness);

                // No usage for the shadow masks
                lightData.shadowMaskSelector = Vector4.zero;
                {
                    // use -1 to say that we don't use shadow mask
                    lightData.shadowMaskSelector.x = -1.0f;
                    lightData.nonLightMappedOnly   = 0;
                }

                if (ShaderConfig.s_CameraRelativeRendering != 0)
                {
                    // Caution: 'LightData.positionWS' is camera-relative after this point.
                    Vector3 camPosWS = hdCamera.mainViewConstants.worldSpaceCameraPos;
                    lightData.positionRWS -= camPosWS;
                }

                // Set the data for this light
                m_LightDataCPUArray.Add(lightData);
            }

            // Push the data to the GPU
            m_LightDataGPUArray.SetData(m_LightDataCPUArray);
        }
        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;
        }
 /// <summary>
 /// This function can be used to evict a light from its atlas. The slots occupied by such light will be available to be occupied by other shadows.
 /// Note that eviction happens automatically upon light destruction and, if lightData.preserveCachedShadow is false, upon disabling of the light.
 /// </summary>
 /// <param name="lightData">The light to evict from the atlas.</param>
 public void ForceEvictLight(HDAdditionalLightData lightData)
 {
     EvictLight(lightData);
     lightData.lightIdxForCachedShadows = -1;
 }