static void ResetLight(MenuCommand menuCommand)
        {
            GameObject go = ((Light)menuCommand.context).gameObject;

            Assert.IsNotNull(go);

            Light light = go.GetComponent <Light>();
            HDAdditionalLightData lightAdditionalData = go.GetComponent <HDAdditionalLightData>();
            HDLightType           lightType           = lightAdditionalData.type;

            Assert.IsNotNull(light);
            Assert.IsNotNull(lightAdditionalData);

            Undo.RecordObjects(new UnityEngine.Object[] { light, lightAdditionalData }, "Reset HD Light");
            light.Reset();
            // To avoid duplicating init code we copy default settings to Reset additional data
            // Note: we can't call this code inside the HDAdditionalLightData, thus why we don't wrap it in a Reset() function
            HDUtils.s_DefaultHDAdditionalLightData.CopyTo(lightAdditionalData);
            lightAdditionalData.type = lightType;

            //reinit default intensity
            HDAdditionalLightData.InitDefaultHDAdditionalLightData(lightAdditionalData);

            //patch missing cookie texture reset in built-in light reset
            light.cookie = null;
        }
        // ------------------------ Public API -------------------------------

        /// <summary>
        /// This function verifies if a shadow map of resolution shadowResolution for a light of type lightType would fit in the atlas when inserted.
        /// </summary>
        /// <param name="shadowResolution">The resolution of the hypothetical shadow map that we are assessing.</param>
        /// <param name="lightType">The type of the light that cast the hypothetical shadow map that we are assessing.</param>
        /// <returns>True if the shadow map would fit in the atlas, false otherwise.</returns>
        public bool WouldFitInAtlas(int shadowResolution, HDLightType lightType)
        {
            bool fits = true;
            int  x, y;

            if (lightType == HDLightType.Point)
            {
                for (int i = 0; i < 6; ++i)
                {
                    fits = fits && HDShadowManager.cachedShadowManager.punctualShadowAtlas.FindSlotInAtlas(shadowResolution, out x, out y);
                }
            }

            if (lightType == HDLightType.Spot)
            {
                fits = fits && HDShadowManager.cachedShadowManager.punctualShadowAtlas.FindSlotInAtlas(shadowResolution, out x, out y);
            }

            if (lightType == HDLightType.Area)
            {
                fits = fits && HDShadowManager.cachedShadowManager.areaShadowAtlas.FindSlotInAtlas(shadowResolution, out x, out y);
            }

            return(fits);
        }
示例#3
0
 // Helper for punctual and area light unit conversion
 /// <summary>
 /// Convert a punctual light intensity in Lumen to Candela
 /// </summary>
 /// <param name="lightType"></param>
 /// <param name="lumen"></param>
 /// <param name="initialIntensity"></param>
 /// <param name="enableSpotReflector"></param>
 /// <returns></returns>
 public static float ConvertPunctualLightLumenToCandela(HDLightType lightType, float lumen, float initialIntensity, bool enableSpotReflector)
 {
     if (lightType == HDLightType.Spot && enableSpotReflector)
     {
         // We have already calculate the correct value, just assign it
         return(initialIntensity);
     }
     return(ConvertPointLightLumenToCandela(lumen));
 }
        /// <summary>
        ///  Add a new HDRP Light to a GameObject
        /// </summary>
        /// <param name="gameObject">The GameObject on which the light is going to be added</param>
        /// <param name="lightType">The Type of the HDRP light to Add</param>
        /// <returns>The created HDRP Light component</returns>
        public static HDAdditionalLightData AddHDLight(this GameObject gameObject, HDLightType lightType)
        {
            var hdLight = gameObject.AddComponent <HDAdditionalLightData>();

            HDAdditionalLightData.InitDefaultHDAdditionalLightData(hdLight);

            hdLight.SetLightType(lightType);

            return(hdLight);
        }
 /// <summary>
 /// If a light is added after a scene is loaded, its placement in the atlas might be not optimal and the suboptimal placement might prevent a light to find a place in the atlas.
 /// This function will force a defragmentation of the atlas containing lights of type lightType and redistributes the shadows inside so that the placement is optimal. Note however that this will also mark the shadow maps
 /// as dirty and they will be re-rendered as soon the light will come into view for the first time after this function call.
 /// </summary>
 /// <param name="lightType">The type of the light contained in the atlas that need defragmentation.</param>
 public void DefragAtlas(HDLightType lightType)
 {
     if (lightType == HDLightType.Area)
     {
         instance.areaShadowAtlas.DefragmentAtlasAndReRender(instance.m_InitParams);
     }
     if (lightType == HDLightType.Point || lightType == HDLightType.Spot)
     {
         instance.punctualShadowAtlas.DefragmentAtlasAndReRender(instance.m_InitParams);
     }
 }
        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);
            }
        }
示例#7
0
 public void Draw(HDLightType type, LightUnit lightUnit, SerializedProperty value, Rect rect, SerializedHDLight light, Editor owner)
 {
     using (new EditorGUI.IndentLevelScope(-EditorGUI.indentLevel))
     {
         if (type == HDLightType.Directional)
         {
             DrawDirectionalUnitSlider(value, rect);
         }
         else
         {
             DrawPunctualLightUnitSlider(lightUnit, value, rect, light, owner);
         }
     }
 }
        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;
            }
        }
示例#9
0
        protected override void OnSceneGUI()
        {
            // Each handles manipulate only one light
            // Thus do not rely on serialized properties
            HDLightType lightType = targetAdditionalData.type;

            if (lightType == HDLightType.Directional ||
                lightType == HDLightType.Point ||
                lightType == HDLightType.Area && targetAdditionalData.areaLightShape == AreaLightShape.Disc)
            {
                base.OnSceneGUI();
            }
            else
            {
                HDLightUI.DrawHandles(targetAdditionalData, this);
            }
        }
        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);
            }
        }
        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);
            }
        }
示例#12
0
        private void AddLightListToRecordList(Dictionary <int, HDAdditionalLightData> lightList, HDShadowInitParameters initParams, ref List <CachedShadowRecord> recordList)
        {
            foreach (var currentLightData in lightList.Values)
            {
                int resolution = 0;

                resolution = currentLightData.GetResolutionFromSettings(m_ShadowType, initParams);

                HDLightType lightType       = currentLightData.type;
                int         numberOfShadows = (lightType == HDLightType.Point) ? 6 : 1;

                for (int i = 0; i < numberOfShadows; ++i)
                {
                    CachedShadowRecord record;
                    record.shadowIndex   = currentLightData.lightIdxForCachedShadows + i;
                    record.viewportSize  = resolution;
                    record.offsetInAtlas = new Vector4(-1, -1, -1, -1); // Will be set later.

                    recordList.Add(record);
                }
            }
        }
示例#13
0
        /// <summary>
        /// Convert a punctual light intensity in Candela to Lumen
        /// </summary>
        /// <param name="lightType"></param>
        /// <param name="spotLightShape"></param>
        /// <param name="candela"></param>
        /// <param name="enableSpotReflector"></param>
        /// <param name="spotAngle"></param>
        /// <param name="aspectRatio"></param>
        /// <returns></returns>
        public static float ConvertPunctualLightCandelaToLumen(HDLightType lightType, SpotLightShape spotLightShape, float candela, bool enableSpotReflector, float spotAngle, float aspectRatio)
        {
            if (lightType == HDLightType.Spot && enableSpotReflector)
            {
                // We just need to multiply candela by solid angle in this case
                if (spotLightShape == SpotLightShape.Cone)
                {
                    return(ConvertSpotLightCandelaToLumen(candela, spotAngle * Mathf.Deg2Rad, true));
                }
                else if (spotLightShape == SpotLightShape.Pyramid)
                {
                    float angleA, angleB;
                    CalculateAnglesForPyramid(aspectRatio, spotAngle * Mathf.Deg2Rad, out angleA, out angleB);

                    return(ConvertFrustrumLightCandelaToLumen(candela, angleA, angleB));
                }
                else // Box
                {
                    return(ConvertPointLightCandelaToLumen(candela));
                }
            }
            return(ConvertPointLightCandelaToLumen(candela));
        }
示例#14
0
        private void AddLightListToRecordList(Dictionary <int, HDAdditionalLightData> lightList, HDShadowInitParameters initParams, ref List <CachedShadowRecord> recordList)
        {
            foreach (var currentLightData in lightList.Values)
            {
                int resolution = 0;

                resolution = currentLightData.GetResolutionFromSettings(m_ShadowType, initParams);

                HDLightType lightType       = currentLightData.type;
                int         numberOfShadows = (lightType == HDLightType.Point) ? 6 : 1;

                for (int i = 0; i < numberOfShadows; ++i)
                {
                    CachedShadowRecord record;
                    record.shadowIndex   = currentLightData.lightIdxForCachedShadows + i;
                    record.viewportSize  = resolution;
                    record.offsetInAtlas = new Vector4(-1, -1, -1, -1); // Will be set later.
                    // Only situation in which we allow not to render on placement if it is OnDemand and onDemandShadowRenderOnPlacement is false
                    record.rendersOnPlacement = (currentLightData.shadowUpdateMode == ShadowUpdateMode.OnDemand) ? (currentLightData.forceRenderOnPlacement || currentLightData.onDemandShadowRenderOnPlacement) : true;
                    currentLightData.forceRenderOnPlacement = false; // reset the force flag as we scheduled the rendering forcefully already.
                    recordList.Add(record);
                }
            }
        }
示例#15
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;
        }
示例#16
0
        // This is not correct, we use candela instead of luminance but this is request from artists to support EV100 on punctual light
        /// <summary>
        /// Convert a punctual light intensity in Lumen to EV100.
        /// This is not physically correct but it's handy to have EV100 for punctual lights.
        /// </summary>
        /// <param name="lightType"></param>
        /// <param name="lumen"></param>
        /// <param name="initialIntensity"></param>
        /// <param name="enableSpotReflector"></param>
        /// <returns></returns>
        public static float ConvertPunctualLightLumenToEv(HDLightType lightType, float lumen, float initialIntensity, bool enableSpotReflector)
        {
            float candela = ConvertPunctualLightLumenToCandela(lightType, lumen, initialIntensity, enableSpotReflector);

            return(ConvertCandelaToEv(candela));
        }
示例#17
0
        // This is not correct, we use candela instead of luminance but this is request from artists to support EV100 on punctual light
        /// <summary>
        /// Convert a punctual light intensity in EV100 to Lumen.
        /// This is not physically correct but it's handy to have EV100 for punctual lights.
        /// </summary>
        /// <param name="lightType"></param>
        /// <param name="spotLightShape"></param>
        /// <param name="ev"></param>
        /// <param name="enableSpotReflector"></param>
        /// <param name="spotAngle"></param>
        /// <param name="aspectRatio"></param>
        /// <returns></returns>
        public static float ConvertPunctualLightEvToLumen(HDLightType lightType, SpotLightShape spotLightShape, float ev, bool enableSpotReflector, float spotAngle, float aspectRatio)
        {
            float candela = ConvertEvToCandela(ev);

            return(ConvertPunctualLightCandelaToLumen(lightType, spotLightShape, candela, enableSpotReflector, spotAngle, aspectRatio));
        }
示例#18
0
        /// <summary>
        /// Convert a punctual light intensity in Lux to Lumen
        /// </summary>
        /// <param name="lightType"></param>
        /// <param name="spotLightShape"></param>
        /// <param name="lux"></param>
        /// <param name="enableSpotReflector"></param>
        /// <param name="spotAngle"></param>
        /// <param name="aspectRatio"></param>
        /// <param name="distance"></param>
        /// <returns></returns>
        public static float ConvertPunctualLightLuxToLumen(HDLightType lightType, SpotLightShape spotLightShape, float lux, bool enableSpotReflector, float spotAngle, float aspectRatio, float distance)
        {
            float candela = ConvertLuxToCandela(lux, distance);

            return(ConvertPunctualLightCandelaToLumen(lightType, spotLightShape, candela, enableSpotReflector, spotAngle, aspectRatio));
        }
        void BuildLightData(CommandBuffer cmd, HDCamera hdCamera, HDRayTracingLights rayTracingLights)
        {
            // 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();

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

                HDAdditionalLightData additionalLightData = 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 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;
                LightVolumeType lightVolumeType = LightVolumeType.Count;
                HDLightType     lightType       = additionalLightData.type;
                HDRenderPipeline.EvaluateGPULightType(lightType, additionalLightData.spotLightShape, additionalLightData.areaLightShape, ref lightCategory, ref gpuLightType, ref lightVolumeType);

                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;

                lightData.boxLightSafeExtent = 1.0f;
                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 (lightType)
                    {
                    case HDLightType.Spot:
                        lightData.cookieIndex = m_RenderPipeline.m_TextureCaches.cookieTexArray.FetchSlice(cmd, light.cookie);
                        break;

                    case HDLightType.Point:
                        lightData.cookieIndex = m_RenderPipeline.m_TextureCaches.cubeCookieTexArray.FetchSlice(cmd, light.cookie);
                        break;
                    }
                }
                else if (lightType == HDLightType.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);
        }
        // Return true if the light must be added to the baking
        public static bool LightDataGIExtract(Light light, ref LightDataGI lightDataGI)
        {
            var add = light.GetComponent <HDAdditionalLightData>();

            if (add == null)
            {
                add = HDUtils.s_DefaultHDAdditionalLightData;
            }

            Cookie cookie;

            LightmapperUtils.Extract(light, out cookie);
            lightDataGI.cookieID    = cookie.instanceID;
            lightDataGI.cookieScale = cookie.scale;

            // TODO: Currently color temperature is not handled at runtime, need to expose useColorTemperature publicly
            Color cct = new Color(1.0f, 1.0f, 1.0f);

#if UNITY_EDITOR
            if (add.useColorTemperature)
            {
                cct = Mathf.CorrelatedColorTemperatureToRGB(light.colorTemperature);
            }
#endif

#if UNITY_EDITOR
            LightMode lightMode = LightmapperUtils.Extract(light.lightmapBakeType);
#else
            LightMode lightMode = LightmapperUtils.Extract(light.bakingOutput.lightmapBakeType);
#endif

            float lightDimmer = 1;

            if (lightMode == LightMode.Realtime && add.affectDiffuse)
            {
                lightDimmer = add.lightDimmer;
            }

            lightDataGI.instanceID = light.GetInstanceID();
            LinearColor directColor, indirectColor;
            directColor              = add.affectDiffuse ? LinearColor.Convert(light.color, light.intensity) : LinearColor.Black();
            directColor.red         *= cct.r;
            directColor.green       *= cct.g;
            directColor.blue        *= cct.b;
            directColor.intensity   *= lightDimmer;
            indirectColor            = add.affectDiffuse ? LightmapperUtils.ExtractIndirect(light) : LinearColor.Black();
            indirectColor.red       *= cct.r;
            indirectColor.green     *= cct.g;
            indirectColor.blue      *= cct.b;
            indirectColor.intensity *= lightDimmer;

            lightDataGI.color         = directColor;
            lightDataGI.indirectColor = indirectColor;

            // Note that the HDRI is correctly integrated in the GlobalIllumination system, we don't need to do anything regarding it.

            // The difference is that `l.lightmapBakeType` is the intent, e.g.you want a mixed light with shadowmask. But then the overlap test might detect more than 4 overlapping volumes and force a light to fallback to baked.
            // In that case `l.bakingOutput.lightmapBakeType` would be baked, instead of mixed, whereas `l.lightmapBakeType` would still be mixed. But this difference is only relevant in editor builds
#if UNITY_EDITOR
            lightDataGI.mode = LightmapperUtils.Extract(light.lightmapBakeType);
#else
            lightDataGI.mode = LightmapperUtils.Extract(light.bakingOutput.lightmapBakeType);
#endif

            lightDataGI.shadow = (byte)(light.shadows != LightShadows.None ? 1 : 0);

            HDLightType lightType = add.ComputeLightType(light);
            if (lightType != HDLightType.Area)
            {
                // For HDRP we need to divide the analytic light color by PI (HDRP do explicit PI division for Lambert, but built in Unity and the GI don't for punctual lights)
                // We apply it on both direct and indirect are they are separated, seems that direct is no used if we used mixed mode with indirect or shadowmask bake.
                lightDataGI.color.intensity         /= Mathf.PI;
                lightDataGI.indirectColor.intensity /= Mathf.PI;
                directColor.intensity   /= Mathf.PI;
                indirectColor.intensity /= Mathf.PI;
            }

            switch (lightType)
            {
            case HDLightType.Directional:
                lightDataGI.orientation    = light.transform.rotation;
                lightDataGI.position       = light.transform.position;
                lightDataGI.range          = 0.0f;
                lightDataGI.coneAngle      = add.shapeWidth;
                lightDataGI.innerConeAngle = add.shapeHeight;
#if UNITY_EDITOR
                lightDataGI.shape0 = light.shadows != LightShadows.None ? (Mathf.Deg2Rad * light.shadowAngle) : 0.0f;
#else
                lightDataGI.shape0 = 0.0f;
#endif
                lightDataGI.shape1         = 0.0f;
                lightDataGI.type           = UnityEngine.Experimental.GlobalIllumination.LightType.Directional;
                lightDataGI.falloff        = FalloffType.Undefined;
                lightDataGI.coneAngle      = add.shapeWidth;
                lightDataGI.innerConeAngle = add.shapeHeight;
                break;

            case HDLightType.Spot:
                switch (add.spotLightShape)
                {
                case SpotLightShape.Cone:
                {
                    SpotLight spot;
                    spot.instanceID = light.GetInstanceID();
                    spot.shadow     = light.shadows != LightShadows.None;
                    spot.mode       = lightMode;
#if UNITY_EDITOR
                    spot.sphereRadius = light.shadows != LightShadows.None ? light.shadowRadius : 0.0f;
#else
                    spot.sphereRadius = 0.0f;
#endif
                    spot.position       = light.transform.position;
                    spot.orientation    = light.transform.rotation;
                    spot.color          = directColor;
                    spot.indirectColor  = indirectColor;
                    spot.range          = light.range;
                    spot.coneAngle      = light.spotAngle * Mathf.Deg2Rad;
                    spot.innerConeAngle = light.spotAngle * Mathf.Deg2Rad * add.innerSpotPercent01;
                    spot.falloff        = add.applyRangeAttenuation ? FalloffType.InverseSquared : FalloffType.InverseSquaredNoRangeAttenuation;
                    spot.angularFalloff = AngularFalloffType.AnalyticAndInnerAngle;
                    lightDataGI.Init(ref spot, ref cookie);
                    lightDataGI.shape1 = (float)AngularFalloffType.AnalyticAndInnerAngle;
                    if (light.cookie != null)
                    {
                        lightDataGI.cookieID = light.cookie.GetInstanceID();
                    }
                    else if (add.IESSpot != null)
                    {
                        lightDataGI.cookieID = add.IESSpot.GetInstanceID();
                    }
                    else
                    {
                        lightDataGI.cookieID = 0;
                    }
                }
                break;

                case SpotLightShape.Pyramid:
                {
                    SpotLightPyramidShape pyramid;
                    pyramid.instanceID    = light.GetInstanceID();
                    pyramid.shadow        = light.shadows != LightShadows.None;
                    pyramid.mode          = lightMode;
                    pyramid.position      = light.transform.position;
                    pyramid.orientation   = light.transform.rotation;
                    pyramid.color         = directColor;
                    pyramid.indirectColor = indirectColor;
                    pyramid.range         = light.range;
                    pyramid.angle         = light.spotAngle * Mathf.Deg2Rad;
                    pyramid.aspectRatio   = add.aspectRatio;
                    pyramid.falloff       = add.applyRangeAttenuation ? FalloffType.InverseSquared : FalloffType.InverseSquaredNoRangeAttenuation;
                    lightDataGI.Init(ref pyramid, ref cookie);
                    if (light.cookie != null)
                    {
                        lightDataGI.cookieID = light.cookie.GetInstanceID();
                    }
                    else if (add.IESSpot != null)
                    {
                        lightDataGI.cookieID = add.IESSpot.GetInstanceID();
                    }
                    else
                    {
                        lightDataGI.cookieID = 0;
                    }
                }
                break;

                case SpotLightShape.Box:
                {
                    SpotLightBoxShape box;
                    box.instanceID    = light.GetInstanceID();
                    box.shadow        = light.shadows != LightShadows.None;
                    box.mode          = lightMode;
                    box.position      = light.transform.position;
                    box.orientation   = light.transform.rotation;
                    box.color         = directColor;
                    box.indirectColor = indirectColor;
                    box.range         = light.range;
                    box.width         = add.shapeWidth;
                    box.height        = add.shapeHeight;
                    lightDataGI.Init(ref box, ref cookie);
                    if (light.cookie != null)
                    {
                        lightDataGI.cookieID = light.cookie.GetInstanceID();
                    }
                    else if (add.IESSpot != null)
                    {
                        lightDataGI.cookieID = add.IESSpot.GetInstanceID();
                    }
                    else
                    {
                        lightDataGI.cookieID = 0;
                    }
                }
                break;

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

            case HDLightType.Point:
                lightDataGI.orientation    = light.transform.rotation;
                lightDataGI.position       = light.transform.position;
                lightDataGI.range          = light.range;
                lightDataGI.coneAngle      = 0.0f;
                lightDataGI.innerConeAngle = 0.0f;

#if UNITY_EDITOR
                lightDataGI.shape0 = light.shadows != LightShadows.None ? light.shadowRadius : 0.0f;
#else
                lightDataGI.shape0 = 0.0f;
#endif
                lightDataGI.shape1  = 0.0f;
                lightDataGI.type    = UnityEngine.Experimental.GlobalIllumination.LightType.Point;
                lightDataGI.falloff = add.applyRangeAttenuation ? FalloffType.InverseSquared : FalloffType.InverseSquaredNoRangeAttenuation;
                break;

            case HDLightType.Area:
                switch (add.areaLightShape)
                {
                case AreaLightShape.Rectangle:
                    lightDataGI.orientation    = light.transform.rotation;
                    lightDataGI.position       = light.transform.position;
                    lightDataGI.range          = light.range;
                    lightDataGI.coneAngle      = 0.0f;
                    lightDataGI.innerConeAngle = 0.0f;
                    lightDataGI.shape0         = add.shapeWidth;
                    lightDataGI.shape1         = add.shapeHeight;

                    // TEMP: for now, if we bake a rectangle type this will disable the light for runtime, need to speak with GI team about it!
                    lightDataGI.type    = UnityEngine.Experimental.GlobalIllumination.LightType.Rectangle;
                    lightDataGI.falloff = add.applyRangeAttenuation ? FalloffType.InverseSquared : FalloffType.InverseSquaredNoRangeAttenuation;
                    if (add.areaLightCookie != null)
                    {
                        lightDataGI.cookieID = add.areaLightCookie.GetInstanceID();
                    }
                    else if (add.IESSpot != null)
                    {
                        lightDataGI.cookieID = add.IESSpot.GetInstanceID();
                    }
                    else
                    {
                        lightDataGI.cookieID = 0;
                    }
                    break;

                case AreaLightShape.Tube:
                    lightDataGI.InitNoBake(lightDataGI.instanceID);
                    break;

                case AreaLightShape.Disc:
                    lightDataGI.orientation    = light.transform.rotation;
                    lightDataGI.position       = light.transform.position;
                    lightDataGI.range          = light.range;
                    lightDataGI.coneAngle      = 0.0f;
                    lightDataGI.innerConeAngle = 0.0f;
#if UNITY_EDITOR
                    lightDataGI.shape0 = light.areaSize.x;
                    lightDataGI.shape1 = light.areaSize.y;
#else
                    lightDataGI.shape0 = 0.0f;
                    lightDataGI.shape1 = 0.0f;
#endif
                    // TEMP: for now, if we bake a rectangle type this will disable the light for runtime, need to speak with GI team about it!
                    lightDataGI.type     = UnityEngine.Experimental.GlobalIllumination.LightType.Disc;
                    lightDataGI.falloff  = add.applyRangeAttenuation ? FalloffType.InverseSquared : FalloffType.InverseSquaredNoRangeAttenuation;
                    lightDataGI.cookieID = add.areaLightCookie ? add.areaLightCookie.GetInstanceID() : 0;
                    break;

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

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

            return(true);
        }
示例#21
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);
        }
        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);
        }
        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);
        }
        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
            HDLightRenderDatabase lightEntities = HDLightRenderDatabase.instance;
            var processedLightEntity            = new HDProcessedVisibleLight()
            {
                shadowMapFlags = HDProcessedVisibleLightsBuilder.ShadowMapFlags.None
            };

            var globalConfig     = HDGpuLightsBuilder.CreateGpuLightDataJobGlobalConfig.Create(hdCamera, hdShadowSettings);
            var shadowInitParams = m_RenderPipeline.currentPlatformRenderPipelineSettings.hdShadowInitParams;

            for (int lightIdx = 0; lightIdx < rayTracingLights.hdLightEntityArray.Count; ++lightIdx)
            {
                // Grab the additinal light data to process
                int dataIndex = lightEntities.GetEntityDataIndex(rayTracingLights.hdLightEntityArray[lightIdx]);
                HDAdditionalLightData additionalLightData = lightEntities.hdAdditionalLightData[dataIndex];

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

                ref HDLightRenderData lightRenderData = ref lightEntities.GetLightDataAsRef(dataIndex);

                // Build the processed light data  that we need
                processedLightEntity.dataIndex                   = dataIndex;
                processedLightEntity.gpuLightType                = gpuLightType;
                processedLightEntity.lightType                   = additionalLightData.type;
                processedLightEntity.distanceToCamera            = (additionalLightData.transform.position - hdCamera.camera.transform.position).magnitude;
                processedLightEntity.lightDistanceFade           = HDUtils.ComputeLinearDistanceFade(processedLightEntity.distanceToCamera, lightRenderData.fadeDistance);
                processedLightEntity.lightVolumetricDistanceFade = HDUtils.ComputeLinearDistanceFade(processedLightEntity.distanceToCamera, lightRenderData.volumetricFadeDistance);
                processedLightEntity.isBakedShadowMask           = HDRenderPipeline.IsBakedShadowMaskLight(lightComponent);

                // Build a visible light
                visibleLight.finalColor = LightUtils.EvaluateLightColor(lightComponent, additionalLightData);
                visibleLight.range      = lightComponent.range;
                // This should be done explicitly, 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;
                Vector3 lightDimensions = new Vector3(0.0f, 0.0f, 0.0f);

                // Use the shared code to build the light data
                HDGpuLightsBuilder.CreateGpuLightDataJob.ConvertLightToGPUFormat(
                    lightCategory, gpuLightType, globalConfig,
                    lightComponent.lightShadowCasterMode, lightComponent.bakingOutput,
                    visibleLight, processedLightEntity, lightRenderData, out var _, ref lightData);
                m_RenderPipeline.gpuLightList.ProcessLightDataShadowIndex(cmd, shadowInitParams, lightType, lightComponent, additionalLightData, shadowIndex, 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);
            }