Exemplo n.º 1
0
    public void OnEnable( )
    {
        Lightmapping.RequestLightsDelegate testDel = (Light [] requests, Unity.Collections.NativeArray <LightDataGI> lightsOutput) =>
        {
            DirectionalLight dLight = new DirectionalLight( );
            PointLight       point  = new PointLight( );
            SpotLight        spot   = new SpotLight( );
            RectangleLight   rect   = new RectangleLight( );
            LightDataGI      ld     = new LightDataGI( );

            for (int i = 0; i < requests.Length; i++)
            {
                Light l = requests [i];
                switch (l.type)
                {
                case UnityEngine.LightType.Directional: LightmapperUtils.Extract(l, ref dLight); ld.Init(ref dLight); break;

                case UnityEngine.LightType.Point: LightmapperUtils.Extract(l, ref point); ld.Init(ref point); break;

                case UnityEngine.LightType.Spot: LightmapperUtils.Extract(l, ref spot); ld.Init(ref spot); break;

                case UnityEngine.LightType.Area: LightmapperUtils.Extract(l, ref rect); ld.Init(ref rect); break;

                default: ld.InitNoBake(l.GetInstanceID( )); break;
                }

                ld.falloff       = FalloffType.InverseSquared;
                lightsOutput [i] = ld;
            }
        };

        Lightmapping.SetDelegate(testDel);
    }
        void InitializeLightConstants(List <VisibleLight> lights, int lightIndex, out Vector4 lightPos, out Vector4 lightColor, out Vector4 lightDistanceAttenuation, out Vector4 lightSpotDir,
                                      out Vector4 lightSpotAttenuation)
        {
            lightPos   = k_DefaultLightPosition;
            lightColor = k_DefaultLightColor;
            lightDistanceAttenuation = k_DefaultLightSpotAttenuation;
            lightSpotDir             = k_DefaultLightSpotDirection;
            lightSpotAttenuation     = k_DefaultLightAttenuation;

            // When no lights are visible, main light will be set to -1.
            // In this case we initialize it to default values and return
            if (lightIndex < 0)
            {
                return;
            }

            VisibleLight lightData = lights[lightIndex];

            if (lightData.lightType == LightType.Directional)
            {
                Vector4 dir = -lightData.localToWorld.GetColumn(2);
                lightPos = new Vector4(dir.x, dir.y, dir.z, 0.0f);
            }
            else
            {
                Vector4 pos = lightData.localToWorld.GetColumn(3);
                lightPos = new Vector4(pos.x, pos.y, pos.z, 1.0f);
            }

            // VisibleLight.finalColor already returns color in active color space
            lightColor = lightData.finalColor;

            // Directional Light attenuation is initialize so distance attenuation always be 1.0
            if (lightData.lightType != LightType.Directional)
            {
                // Light attenuation in lightweight matches the unity vanilla one.
                // attenuation = 1.0 / 1.0 + distanceToLightSqr * quadraticAttenuation
                // then a smooth factor is applied to linearly fade attenuation to light range
                // the attenuation smooth factor starts having effect at 80% of light range
                // smoothFactor = (lightRangeSqr - distanceToLightSqr) / (lightRangeSqr - fadeStartDistanceSqr)
                // We rewrite smoothFactor to be able to pre compute the constant terms below and apply the smooth factor
                // with one MAD instruction
                // smoothFactor =  distanceSqr * (1.0 / (fadeDistanceSqr - lightRangeSqr)) + (-lightRangeSqr / (fadeDistanceSqr - lightRangeSqr)
                //                 distanceSqr *           oneOverFadeRangeSqr             +              lightRangeSqrOverFadeRangeSqr
                float lightRangeSqr                 = lightData.range * lightData.range;
                float fadeStartDistanceSqr          = 0.8f * 0.8f * lightRangeSqr;
                float fadeRangeSqr                  = (fadeStartDistanceSqr - lightRangeSqr);
                float oneOverFadeRangeSqr           = 1.0f / fadeRangeSqr;
                float lightRangeSqrOverFadeRangeSqr = -lightRangeSqr / fadeRangeSqr;
                float quadAtten = 25.0f / lightRangeSqr;
                lightDistanceAttenuation = new Vector4(quadAtten, oneOverFadeRangeSqr, lightRangeSqrOverFadeRangeSqr, 1.0f);
            }

            if (lightData.lightType == LightType.Spot)
            {
                Vector4 dir = lightData.localToWorld.GetColumn(2);
                lightSpotDir = new Vector4(-dir.x, -dir.y, -dir.z, 0.0f);

                // Spot Attenuation with a linear falloff can be defined as
                // (SdotL - cosOuterAngle) / (cosInnerAngle - cosOuterAngle)
                // This can be rewritten as
                // invAngleRange = 1.0 / (cosInnerAngle - cosOuterAngle)
                // SdotL * invAngleRange + (-cosOuterAngle * invAngleRange)
                // If we precompute the terms in a MAD instruction
                float cosOuterAngle = Mathf.Cos(Mathf.Deg2Rad * lightData.spotAngle * 0.5f);
                // We neeed to do a null check for particle lights
                // This should be changed in the future
                // Particle lights will use an inline function
                float cosInnerAngle;
                if (lightData.light != null)
                {
                    cosInnerAngle = Mathf.Cos(LightmapperUtils.ExtractInnerCone(lightData.light) * 0.5f);
                }
                else
                {
                    cosInnerAngle = Mathf.Cos((2.0f * Mathf.Atan(Mathf.Tan(lightData.spotAngle * 0.5f * Mathf.Deg2Rad) * (64.0f - 18.0f) / 64.0f)) * 0.5f);
                }
                float smoothAngleRange = Mathf.Max(0.001f, cosInnerAngle - cosOuterAngle);
                float invAngleRange    = 1.0f / smoothAngleRange;
                float add = -cosOuterAngle * invAngleRange;
                lightSpotAttenuation = new Vector4(invAngleRange, add, 0.0f);
            }

            Light light = lightData.light;

            // TODO: Add support to shadow mask
            if (light != null && light.bakingOutput.mixedLightingMode == MixedLightingMode.Subtractive && light.bakingOutput.lightmapBakeType == LightmapBakeType.Mixed)
            {
                if (m_MixedLightingSetup == MixedLightingSetup.None && lightData.light.shadows != LightShadows.None)
                {
                    m_MixedLightingSetup       = MixedLightingSetup.Subtractive;
                    lightDistanceAttenuation.w = 0.0f;
                }
            }
        }
        // Return true if the light must be added to the baking
        public static bool LightDataGIExtract(Light l, ref LightDataGI ld)
        {
            var add = l.GetComponent <HDAdditionalLightData>();

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

            // TODO: Only take into account the light dimmer when we have real time GI.

            ld.instanceID    = l.GetInstanceID();
            ld.color         = add.affectDiffuse ? LinearColor.Convert(l.color, l.intensity) : LinearColor.Black();
            ld.indirectColor = add.affectDiffuse ? LightmapperUtils.ExtractIndirect(l) : LinearColor.Black();

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

            ld.mode = LightmapperUtils.Extract(l.lightmapBakeType);

            ld.shadow = (byte)(l.shadows != LightShadows.None ? 1 : 0);

            if (add.lightTypeExtent == LightTypeExtent.Punctual)
            {
                // 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.
                ld.color.intensity         /= Mathf.PI;
                ld.indirectColor.intensity /= Mathf.PI;

                switch (l.type)
                {
                case LightType.Directional:
                    ld.orientation.SetLookRotation(l.transform.forward, Vector3.up);
                    ld.position       = Vector3.zero;
                    ld.range          = 0.0f;
                    ld.coneAngle      = 0.0f;
                    ld.innerConeAngle = 0.0f;
#if UNITY_EDITOR
                    ld.shape0 = l.shadows != LightShadows.None ? (Mathf.Deg2Rad * l.shadowAngle) : 0.0f;
#else
                    ld.shape0 = 0.0f;
#endif
                    ld.shape1  = 0.0f;
                    ld.type    = UnityEngine.Experimental.GlobalIllumination.LightType.Directional;
                    ld.falloff = FalloffType.Undefined;
                    break;

                case LightType.Spot:

                    ld.orientation    = l.transform.rotation;
                    ld.position       = l.transform.position;
                    ld.range          = l.range;
                    ld.coneAngle      = l.spotAngle * Mathf.Deg2Rad; // coneAngle is the full angle
                    ld.innerConeAngle = l.spotAngle * Mathf.Deg2Rad * add.GetInnerSpotPercent01();
#if UNITY_EDITOR
                    ld.shape0 = l.shadows != LightShadows.None ? l.shadowRadius : 0.0f;
#else
                    ld.shape0 = 0.0f;
#endif
                    ld.shape1  = 0.0f;
                    ld.type    = UnityEngine.Experimental.GlobalIllumination.LightType.Spot;
                    ld.falloff = add.applyRangeAttenuation ? FalloffType.InverseSquared : FalloffType.InverseSquaredNoRangeAttenuation;

                    /*
                     * switch (add.spotLightShape)
                     * {
                     *  case SpotLightShape.Cone:
                     *      break;
                     *  case SpotLightShape.Pyramid:
                     *      break;
                     *  case SpotLightShape.Box:
                     *      break;
                     *  default:
                     *      Debug.Assert(false, "Encountered an unknown SpotLightShape.");
                     *      break;
                     * }
                     */
                    break;

                case LightType.Point:
                    ld.orientation    = Quaternion.identity;
                    ld.position       = l.transform.position;
                    ld.range          = l.range;
                    ld.coneAngle      = 0.0f;
                    ld.innerConeAngle = 0.0f;

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

                // Note: We don't support this type in HDRP, but ini just in case
                case LightType.Area:
                    ld.orientation    = l.transform.rotation;
                    ld.position       = l.transform.position;
                    ld.range          = l.range;
                    ld.coneAngle      = 0.0f;
                    ld.innerConeAngle = 0.0f;
#if UNITY_EDITOR
                    ld.shape0 = l.areaSize.x;
                    ld.shape1 = l.areaSize.y;
#else
                    ld.shape0 = 0.0f;
                    ld.shape1 = 0.0f;
#endif
                    ld.type    = UnityEngine.Experimental.GlobalIllumination.LightType.Rectangle;
                    ld.falloff = FalloffType.Undefined;
                    break;

                default:
                    Debug.Assert(false, "Encountered an unknown LightType.");
                    break;
                }
            }
            else if (add.lightTypeExtent == LightTypeExtent.Rectangle)
            {
                ld.orientation    = l.transform.rotation;
                ld.position       = l.transform.position;
                ld.range          = l.range;
                ld.coneAngle      = 0.0f;
                ld.innerConeAngle = 0.0f;
#if UNITY_EDITOR
                ld.shape0 = l.areaSize.x;
                ld.shape1 = l.areaSize.y;
#else
                ld.shape0 = 0.0f;
                ld.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!
                ld.type    = UnityEngine.Experimental.GlobalIllumination.LightType.Rectangle;
                ld.falloff = add.applyRangeAttenuation ? FalloffType.InverseSquared : FalloffType.InverseSquaredNoRangeAttenuation;
            }
            else if (add.lightTypeExtent == LightTypeExtent.Line)
            {
                ld.InitNoBake(ld.instanceID);
            }
            else
            {
                Debug.Assert(false, "Encountered an unknown LightType.");
            }

            return(true);
        }
        void InitializeLightConstants(NativeArray <VisibleLight> lights, int lightIndex, out Vector4 lightPos, out Vector4 lightColor, out Vector4 lightAttenuation, out Vector4 lightSpotDir, out Vector4 lightOcclusionProbeChannel)
        {
            lightPos                   = k_DefaultLightPosition;
            lightColor                 = k_DefaultLightColor;
            lightAttenuation           = k_DefaultLightAttenuation;
            lightSpotDir               = k_DefaultLightSpotDirection;
            lightOcclusionProbeChannel = k_DefaultLightsProbeChannel;

            // When no lights are visible, main light will be set to -1.
            // In this case we initialize it to default values and return
            if (lightIndex < 0)
            {
                return;
            }

            VisibleLight lightData = lights[lightIndex];

            if (lightData.lightType == LightType.Directional)
            {
                Vector4 dir = -lightData.localToWorldMatrix.GetColumn(2);
                lightPos = new Vector4(dir.x, dir.y, dir.z, 1.0f);
            }
            else
            {
                Vector4 pos = lightData.localToWorldMatrix.GetColumn(3);
                lightPos = new Vector4(pos.x, pos.y, pos.z, 1.0f);
            }

            // VisibleLight.finalColor already returns color in active color space
            lightColor = lightData.finalColor;

            // Directional Light attenuation is initialize so distance attenuation always be 1.0
            if (lightData.lightType != LightType.Directional)
            {
                // Light attenuation in universal matches the unity vanilla one.
                // attenuation = 1.0 / distanceToLightSqr
                // We offer two different smoothing factors.
                // The smoothing factors make sure that the light intensity is zero at the light range limit.
                // The first smoothing factor is a linear fade starting at 80 % of the light range.
                // smoothFactor = (lightRangeSqr - distanceToLightSqr) / (lightRangeSqr - fadeStartDistanceSqr)
                // We rewrite smoothFactor to be able to pre compute the constant terms below and apply the smooth factor
                // with one MAD instruction
                // smoothFactor =  distanceSqr * (1.0 / (fadeDistanceSqr - lightRangeSqr)) + (-lightRangeSqr / (fadeDistanceSqr - lightRangeSqr)
                //                 distanceSqr *           oneOverFadeRangeSqr             +              lightRangeSqrOverFadeRangeSqr

                // The other smoothing factor matches the one used in the Unity lightmapper but is slower than the linear one.
                // smoothFactor = (1.0 - saturate((distanceSqr * 1.0 / lightrangeSqr)^2))^2
                float lightRangeSqr                 = lightData.range * lightData.range;
                float fadeStartDistanceSqr          = 0.8f * 0.8f * lightRangeSqr;
                float fadeRangeSqr                  = (fadeStartDistanceSqr - lightRangeSqr);
                float oneOverFadeRangeSqr           = 1.0f / fadeRangeSqr;
                float lightRangeSqrOverFadeRangeSqr = -lightRangeSqr / fadeRangeSqr;
                float oneOverLightRangeSqr          = 1.0f / Mathf.Max(0.0001f, lightData.range * lightData.range);

                // On mobile: Use the faster linear smoothing factor.
                // On other devices: Use the smoothing factor that matches the GI.
                lightAttenuation.x = Application.isMobilePlatform ? oneOverFadeRangeSqr : oneOverLightRangeSqr;
                lightAttenuation.y = lightRangeSqrOverFadeRangeSqr;
            }

            if (lightData.lightType == LightType.Spot)
            {
                Vector4 dir = lightData.localToWorldMatrix.GetColumn(2);
                lightSpotDir = new Vector4(-dir.x, -dir.y, -dir.z, 0.0f);

                // Spot Attenuation with a linear falloff can be defined as
                // (SdotL - cosOuterAngle) / (cosInnerAngle - cosOuterAngle)
                // This can be rewritten as
                // invAngleRange = 1.0 / (cosInnerAngle - cosOuterAngle)
                // SdotL * invAngleRange + (-cosOuterAngle * invAngleRange)
                // If we precompute the terms in a MAD instruction
                float cosOuterAngle = Mathf.Cos(Mathf.Deg2Rad * lightData.spotAngle * 0.5f);
                // We neeed to do a null check for particle lights
                // This should be changed in the future
                // Particle lights will use an inline function
                float cosInnerAngle;
                if (lightData.light != null)
                {
                    cosInnerAngle = Mathf.Cos(LightmapperUtils.ExtractInnerCone(lightData.light) * 0.5f);
                }
                else
                {
                    cosInnerAngle = Mathf.Cos((2.0f * Mathf.Atan(Mathf.Tan(lightData.spotAngle * 0.5f * Mathf.Deg2Rad) * (64.0f - 18.0f) / 64.0f)) * 0.5f);
                }
                float smoothAngleRange = Mathf.Max(0.001f, cosInnerAngle - cosOuterAngle);
                float invAngleRange    = 1.0f / smoothAngleRange;
                float add = -cosOuterAngle * invAngleRange;
                lightAttenuation.z = invAngleRange;
                lightAttenuation.w = add;
            }

            Light light = lightData.light;

            // Set the occlusion probe channel.
            int occlusionProbeChannel = light != null ? light.bakingOutput.occlusionMaskChannel : -1;

            // If we have baked the light, the occlusion channel is the index we need to sample in 'unity_ProbesOcclusion'
            // If we have not baked the light, the occlusion channel is -1.
            // In case there is no occlusion channel is -1, we set it to zero, and then set the second value in the
            // input to one. We then, in the shader max with the second value for non-occluded lights.
            lightOcclusionProbeChannel.x = occlusionProbeChannel == -1 ? 0f : occlusionProbeChannel;
            lightOcclusionProbeChannel.y = occlusionProbeChannel == -1 ? 1f : 0f;

            // TODO: Add support to shadow mask
            if (light != null && light.bakingOutput.mixedLightingMode == MixedLightingMode.Subtractive && light.bakingOutput.lightmapBakeType == LightmapBakeType.Mixed)
            {
                if (m_MixedLightingSetup == MixedLightingSetup.None && lightData.light.shadows != LightShadows.None)
                {
                    m_MixedLightingSetup = MixedLightingSetup.Subtractive;
                }
            }
        }
Exemplo n.º 5
0
        // Return true if the light must be added to the baking
        public static bool LightDataGIExtract(Light l, ref LightDataGI ld)
        {
            var add = l.GetComponent <HDAdditionalLightData>();

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

            // 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(l.colorTemperature);
            }
#endif

            // TODO: Only take into account the light dimmer when we have real time GI.
            ld.instanceID = l.GetInstanceID();
            LinearColor directColor, indirectColor;
            directColor          = add.affectDiffuse ? LinearColor.Convert(l.color, l.intensity) : LinearColor.Black();
            directColor.red     *= cct.r;
            directColor.green   *= cct.g;
            directColor.blue    *= cct.b;
            indirectColor        = add.affectDiffuse ? LightmapperUtils.ExtractIndirect(l) : LinearColor.Black();
            indirectColor.red   *= cct.r;
            indirectColor.green *= cct.g;
            indirectColor.blue  *= cct.b;
#if UNITY_EDITOR
            LightMode lightMode = LightmapperUtils.Extract(l.lightmapBakeType);
#else
            LightMode lightMode = LightmapperUtils.Extract(l.bakingOutput.lightmapBakeType);
#endif

            ld.color         = directColor;
            ld.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
            ld.mode = LightmapperUtils.Extract(l.lightmapBakeType);
#else
            ld.mode = LightmapperUtils.Extract(l.bakingOutput.lightmapBakeType);
#endif

            ld.shadow = (byte)(l.shadows != LightShadows.None ? 1 : 0);

            if (add.lightTypeExtent == LightTypeExtent.Punctual)
            {
                // 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.
                ld.color.intensity         /= Mathf.PI;
                ld.indirectColor.intensity /= Mathf.PI;
                directColor.intensity      /= Mathf.PI;
                indirectColor.intensity    /= Mathf.PI;

                switch (l.type)
                {
                case LightType.Directional:
                    ld.orientation.SetLookRotation(l.transform.forward, Vector3.up);
                    ld.position       = Vector3.zero;
                    ld.range          = 0.0f;
                    ld.coneAngle      = 0.0f;
                    ld.innerConeAngle = 0.0f;
#if UNITY_EDITOR
                    ld.shape0 = l.shadows != LightShadows.None ? (Mathf.Deg2Rad * l.shadowAngle) : 0.0f;
#else
                    ld.shape0 = 0.0f;
#endif
                    ld.shape1  = 0.0f;
                    ld.type    = UnityEngine.Experimental.GlobalIllumination.LightType.Directional;
                    ld.falloff = FalloffType.Undefined;
                    break;

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

                    case SpotLightShape.Pyramid:
                    {
                        SpotLightPyramidShape pyramid;
                        pyramid.instanceID    = l.GetInstanceID();
                        pyramid.shadow        = l.shadows != LightShadows.None;
                        pyramid.mode          = lightMode;
                        pyramid.position      = l.transform.position;
                        pyramid.orientation   = l.transform.rotation;
                        pyramid.color         = directColor;
                        pyramid.indirectColor = indirectColor;
                        pyramid.range         = l.range;
                        pyramid.angle         = l.spotAngle * Mathf.Deg2Rad;
                        pyramid.aspectRatio   = add.aspectRatio;
                        pyramid.falloff       = add.applyRangeAttenuation ? FalloffType.InverseSquared : FalloffType.InverseSquaredNoRangeAttenuation;
                        ld.Init(ref pyramid);
                    }
                    break;

                    case SpotLightShape.Box:
                    {
                        SpotLightBoxShape box;
                        box.instanceID    = l.GetInstanceID();
                        box.shadow        = l.shadows != LightShadows.None;
                        box.mode          = lightMode;
                        box.position      = l.transform.position;
                        box.orientation   = l.transform.rotation;
                        box.color         = directColor;
                        box.indirectColor = indirectColor;
                        box.range         = l.range;
                        box.width         = add.shapeWidth;
                        box.height        = add.shapeHeight;
                        ld.Init(ref box);
                    }
                    break;

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

                case LightType.Point:
                    ld.orientation    = Quaternion.identity;
                    ld.position       = l.transform.position;
                    ld.range          = l.range;
                    ld.coneAngle      = 0.0f;
                    ld.innerConeAngle = 0.0f;

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

                // Note: We don't support this type in HDRP, but ini just in case
                case LightType.Rectangle:
                    ld.orientation    = l.transform.rotation;
                    ld.position       = l.transform.position;
                    ld.range          = l.range;
                    ld.coneAngle      = 0.0f;
                    ld.innerConeAngle = 0.0f;
#if UNITY_EDITOR
                    ld.shape0 = l.areaSize.x;
                    ld.shape1 = l.areaSize.y;
#else
                    ld.shape0 = 0.0f;
                    ld.shape1 = 0.0f;
#endif
                    ld.type    = UnityEngine.Experimental.GlobalIllumination.LightType.Rectangle;
                    ld.falloff = FalloffType.Undefined;
                    break;

                default:
                    Debug.Assert(false, "Encountered an unknown LightType.");
                    break;
                }
            }
            else if (add.lightTypeExtent == LightTypeExtent.Rectangle)
            {
                ld.orientation    = l.transform.rotation;
                ld.position       = l.transform.position;
                ld.range          = l.range;
                ld.coneAngle      = 0.0f;
                ld.innerConeAngle = 0.0f;
#if UNITY_EDITOR
                ld.shape0 = l.areaSize.x;
                ld.shape1 = l.areaSize.y;
#else
                ld.shape0 = 0.0f;
                ld.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!
                ld.type    = UnityEngine.Experimental.GlobalIllumination.LightType.Rectangle;
                ld.falloff = add.applyRangeAttenuation ? FalloffType.InverseSquared : FalloffType.InverseSquaredNoRangeAttenuation;
            }
            else if (add.lightTypeExtent == LightTypeExtent.Tube)
            {
                ld.InitNoBake(ld.instanceID);
            }
            else
            {
                Debug.Assert(false, "Encountered an unknown LightType.");
            }

            return(true);
        }
        void InitializeLightConstants(NativeArray <VisibleLight> lights, int lightIndex, out Vector4 lightPos, out Vector4 lightColor, out Vector4 lightAttenuation, out Vector4 lightSpotDir, out LightCookie cookie)
        {
            lightPos         = k_DefaultLightPosition;
            lightColor       = k_DefaultLightColor;
            lightAttenuation = k_DefaultLightAttenuation;
            lightSpotDir     = k_DefaultLightSpotDirection;
            cookie           = null;
            // When no lights are visible, main light will be set to -1.
            // In this case we initialize it to default values and return
            if (lightIndex < 0)
            {
                return;
            }

            VisibleLight lightData = lights[lightIndex];

            if (lightData.lightType == LightType.Directional)
            {
                Vector4 dir = -lightData.localToWorldMatrix.GetColumn(2);
                lightPos = new Vector4(dir.x, dir.y, dir.z, 1.0f);
            }
            else
            {
                Vector4 pos = lightData.localToWorldMatrix.GetColumn(3);
                lightPos = new Vector4(pos.x, pos.y, pos.z, 1.0f);
            }

            // VisibleLight.finalColor already returns color in active color space
            lightColor = lightData.finalColor;

            // Directional Light attenuation is initialize so distance attenuation always be 1.0
            if (lightData.lightType != LightType.Directional)
            {
                // Light attenuation in lightweight matches the unity vanilla one.
                // attenuation = 1.0 / distanceToLightSqr
                // We offer two different smoothing factors.
                // The smoothing factors make sure that the light intensity is zero at the light range limit.
                // The first smoothing factor is a linear fade starting at 80 % of the light range.
                // smoothFactor = (lightRangeSqr - distanceToLightSqr) / (lightRangeSqr - fadeStartDistanceSqr)
                // We rewrite smoothFactor to be able to pre compute the constant terms below and apply the smooth factor
                // with one MAD instruction
                // smoothFactor =  distanceSqr * (1.0 / (fadeDistanceSqr - lightRangeSqr)) + (-lightRangeSqr / (fadeDistanceSqr - lightRangeSqr)
                //                 distanceSqr *           oneOverFadeRangeSqr             +              lightRangeSqrOverFadeRangeSqr

                // The other smoothing factor matches the one used in the Unity lightmapper but is slower than the linear one.
                // smoothFactor = (1.0 - saturate((distanceSqr * 1.0 / lightrangeSqr)^2))^2
                float lightRangeSqr                 = lightData.range * lightData.range;
                float fadeStartDistanceSqr          = 0.8f * 0.8f * lightRangeSqr;
                float fadeRangeSqr                  = (fadeStartDistanceSqr - lightRangeSqr);
                float oneOverFadeRangeSqr           = 1.0f / fadeRangeSqr;
                float lightRangeSqrOverFadeRangeSqr = -lightRangeSqr / fadeRangeSqr;
                float oneOverLightRangeSqr          = 1.0f / Mathf.Max(0.0001f, lightData.range * lightData.range);

                // On mobile: Use the faster linear smoothing factor.
                // On other devices: Use the smoothing factor that matches the GI.
                lightAttenuation.x = Application.isMobilePlatform ? oneOverFadeRangeSqr : oneOverLightRangeSqr;
                lightAttenuation.y = lightRangeSqrOverFadeRangeSqr;
            }

            if (lightData.lightType == LightType.Spot)
            {
                Vector4 dir = lightData.localToWorldMatrix.GetColumn(2);
                lightSpotDir = new Vector4(-dir.x, -dir.y, -dir.z, 0.0f);

                // Spot Attenuation with a linear falloff can be defined as
                // (SdotL - cosOuterAngle) / (cosInnerAngle - cosOuterAngle)
                // This can be rewritten as
                // invAngleRange = 1.0 / (cosInnerAngle - cosOuterAngle)
                // SdotL * invAngleRange + (-cosOuterAngle * invAngleRange)
                // If we precompute the terms in a MAD instruction
                float cosOuterAngle = Mathf.Cos(Mathf.Deg2Rad * lightData.spotAngle * 0.5f);
                // We neeed to do a null check for particle lights
                // This should be changed in the future
                // Particle lights will use an inline function
                float cosInnerAngle;
                if (lightData.light != null)
                {
                    cosInnerAngle = Mathf.Cos(LightmapperUtils.ExtractInnerCone(lightData.light) * 0.5f);
                }
                else
                {
                    cosInnerAngle = Mathf.Cos((2.0f * Mathf.Atan(Mathf.Tan(lightData.spotAngle * 0.5f * Mathf.Deg2Rad) * (64.0f - 18.0f) / 64.0f)) * 0.5f);
                }
                float smoothAngleRange = Mathf.Max(0.001f, cosInnerAngle - cosOuterAngle);
                float invAngleRange    = 1.0f / smoothAngleRange;
                float add = -cosOuterAngle * invAngleRange;
                lightAttenuation.z = invAngleRange;
                lightAttenuation.w = add;
            }

            Light   light                = lightData.light;
            Texture lightTex             = light.cookie;
            LWRPAdditionalLightData data = light.gameObject.GetComponent <LWRPAdditionalLightData>();

            if (lightTex && data)
            {
                cookie = new LightCookie
                {
                    Tex         = lightTex,
                    LightMat    = light.transform.worldToLocalMatrix,
                    CookieSize  = light.cookieSize,
                    Falloff     = data.lightCookieFalloff,
                    cookieColor = data.lightCookieColor,
                };
            }
            if (light != null && light.bakingOutput.mixedLightingMode == MixedLightingMode.Subtractive && light.bakingOutput.lightmapBakeType == LightmapBakeType.Mixed)
            {
                if (m_MixedLightingSetup == MixedLightingSetup.None && lightData.light.shadows != LightShadows.None)
                {
                    m_MixedLightingSetup = MixedLightingSetup.Subtractive;
                }
            }
        }
Exemplo n.º 7
0
        // 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;

            Color cct = new Color(1.0f, 1.0f, 1.0f);

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

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