Ejemplo n.º 1
0
        public Vector4 ReserveOtherShadows(Light light, int visibleLightIndex)
        {
            if (light.shadows != LightShadows.None && light.shadowStrength > 0f)
            {
                float             maskChannel = -1f;
                LightBakingOutput lightBaking = light.bakingOutput;
                if (lightBaking.lightmapBakeType == LightmapBakeType.Mixed &&
                    lightBaking.mixedLightingMode == MixedLightingMode.Shadowmask)
                {
                    useShadowMask = true;
                    maskChannel   = lightBaking.occlusionMaskChannel;
                }

                bool isPoint       = light.type == LightType.Point;
                int  newLightCount = shadowedOtherLightCount + (isPoint ? 6 : 1);
                if (newLightCount > maxShadowedOtherLightCount ||
                    !cullingResults.GetShadowCasterBounds(visibleLightIndex, out Bounds b))
                {
                    return(new Vector4(-light.shadowStrength, 0f, 0f, maskChannel));
                }
                shadowedOtherLights[shadowedOtherLightCount] = new ShadowedOtherLight
                {
                    visibleLightIndex = visibleLightIndex,
                    slopeScaleBias    = light.shadowBias,
                    normalBias        = light.shadowNormalBias,
                    isPoint           = isPoint
                };
                Vector4 data = new Vector4(
                    light.shadowStrength, shadowedOtherLightCount,
                    isPoint ? 1f : 0f, maskChannel);
                shadowedOtherLightCount = newLightCount;
                return(data);
            }
            return(new Vector4(0f, 0f, 0f, -1f));
        }
Ejemplo n.º 2
0
        protected override void ReadFromImpl(object obj)
        {
            base.ReadFromImpl(obj);
            Light uo = (Light)obj;

            shadows                  = uo.shadows;
            shadowStrength           = uo.shadowStrength;
            shadowResolution         = uo.shadowResolution;
            layerShadowCullDistances = uo.layerShadowCullDistances;
            cookieSize               = uo.cookieSize;
            cookie                 = ToID(uo.cookie);
            renderMode             = uo.renderMode;
            areaSize               = uo.areaSize;
            lightmapBakeType       = uo.lightmapBakeType;
            type                   = uo.type;
            spotAngle              = uo.spotAngle;
            color                  = uo.color;
            colorTemperature       = uo.colorTemperature;
            intensity              = uo.intensity;
            bounceIntensity        = uo.bounceIntensity;
            shadowCustomResolution = uo.shadowCustomResolution;
            shadowBias             = uo.shadowBias;
            shadowNormalBias       = uo.shadowNormalBias;
            shadowNearPlane        = uo.shadowNearPlane;
            range                  = uo.range;
            flare                  = ToID(uo.flare);
            bakingOutput           = uo.bakingOutput;
            cullingMask            = uo.cullingMask;
            lightShadowCasterMode  = uo.lightShadowCasterMode;
            shadowRadius           = uo.shadowRadius;
            shadowAngle            = uo.shadowAngle;
        }
        public Vector4 ReserveDirectionalShadows(Light light, int visibleLightIndex)
        {
            if (currentDirectionalLightShadowCount < maxDirectionalShadowCount && light.shadows != LightShadows.None && light.shadowStrength > 0f)
            {
                float             maskChannel;
                LightBakingOutput lightBakingOutput = light.bakingOutput;

                if (lightBakingOutput.lightmapBakeType == LightmapBakeType.Mixed && lightBakingOutput.mixedLightingMode == MixedLightingMode.Shadowmask)
                {
                    useShadowMask = true;
                    maskChannel   = lightBakingOutput.occlusionMaskChannel; // can not use the light index because it may be changed in runtime
                }

                else
                {
                    maskChannel = -1;
                }

                // GetShadowCasterBounds now returns true for directional lights even when there is nothing within the shadow range
                if (!cullingResults.GetShadowCasterBounds(visibleLightIndex, out Bounds b))
                {
                    // the shadow strength of light is negative, see GetDirectionalShadowAttenuation in WindsmoonShadow.hlsl
                    // if the stength is positive, the shader may be handle the shadow as realtime shadow
                    return(new Vector4(-light.shadowStrength, 0f, 0, maskChannel));
                }

                directionalShadows[currentDirectionalLightShadowCount] = new DirectionalShadow()
                {
                    visibleLightIndex = visibleLightIndex, slopeScaleBias = light.shadowBias, nearPlaneOffset = light.shadowNearPlane
                };
                return(new Vector4(light.shadowStrength, shadowSettings.DirectionalShadowSetting.CascadeCount * currentDirectionalLightShadowCount++, light.shadowNormalBias, maskChannel));
            }

            return(new Vector4(0f, 0f, 0f, -1));
        }
    static void ApplyRendererInfo(RendererInfo[] infos, int[] lightmapOffsetIndex, LightInfo[] lightsInfo)
    {
        for (int i = 0; i < infos.Length; i++)
        {
            var info = infos[i];

            info.renderer.lightmapIndex       = lightmapOffsetIndex[info.lightmapIndex];
            info.renderer.lightmapScaleOffset = info.lightmapOffsetScale;

            // You have to release shaders.
            Material[] mat = info.renderer.sharedMaterials;
            for (int j = 0; j < mat.Length; j++)
            {
                if (mat[j] != null && Shader.Find(mat[j].shader.name) != null)
                {
                    mat[j].shader = Shader.Find(mat[j].shader.name);
                }
            }
        }

        for (int i = 0; i < lightsInfo.Length; i++)
        {
            LightBakingOutput bakingOutput = new LightBakingOutput();
            bakingOutput.isBaked           = true;
            bakingOutput.lightmapBakeType  = (LightmapBakeType)lightsInfo[i].lightmapBaketype;
            bakingOutput.mixedLightingMode = (MixedLightingMode)lightsInfo[i].mixedLightingMode;

            lightsInfo[i].light.bakingOutput = bakingOutput;
        }
    }
Ejemplo n.º 5
0
    /// <summary>
    /// 储备方向光阴影 Vector2存取强度和光线的索引 支持四盏光的ShadowMask
    /// </summary>
    /// <param name="light"></param>
    /// <param name="visibleLightIndex"></param>
    public Vector4 ReserveDirectionalShadows(Light light, int visibleLightIndex)
    {
        //检测阴影强度 None &&cullingResults.GetShadowCasterBounds(visibleLightIndex, out Bounds b)
        if (shadowedDirLightCount < maxShadowedDirLightCount &&
            light.shadows != LightShadows.None && light.shadowStrength > 0f)
        {
            float maskChannel = -1;
            //shadowMask
            LightBakingOutput lightBaking = light.bakingOutput;
            if (lightBaking.lightmapBakeType == LightmapBakeType.Mixed && lightBaking.mixedLightingMode == MixedLightingMode.Shadowmask)
            {
                useShadowMask = true;
                maskChannel   = lightBaking.occlusionMaskChannel;
            }
            //直接Return 出去 不需要Cacade数据 阴影跑出CullSphere里面
            if (!cullingResults.GetShadowCasterBounds(visibleLightIndex, out Bounds b))
            {
                //负数防止Shader 采样ShadowMap
                return(new Vector4(-light.shadowStrength, 0f, 0f, maskChannel));
            }

            ShadowDirectionalLights[shadowedDirLightCount] = new ShadowDirectionalLight {
                visibleLightIndex = visibleLightIndex, slopeScaleBias = light.shadowBias, nearPlaneOffset = light.shadowNearPlane
            };
            //* 级联ShadowMap的数量
            return(new Vector4(light.shadowStrength, settings.directional.cascadeCount * shadowedDirLightCount++, light.shadowNormalBias, maskChannel));
        }
        return(new Vector4(0f, 0f, 0f, -1f));
    }
Ejemplo n.º 6
0
    public Vector4 ReserveDirectionalShadows(Light light, int visibleLightIndex)
    {
        if (shadowedDirectionalLightCount < maxShadowedDirectionalLightCount &&
            light.shadows != LightShadows.None && light.shadowStrength > 0f             //&&
            //cullingResults.GetShadowCasterBounds(visibleLightIndex, out Bounds b)
            )
        {
            float             maskChannel = -1;
            LightBakingOutput lightBaking = light.bakingOutput;
            if (lightBaking.lightmapBakeType == LightmapBakeType.Mixed &&
                lightBaking.mixedLightingMode == MixedLightingMode.Shadowmask)
            {
                useShadowMask = true;
                maskChannel   = lightBaking.occlusionMaskChannel;
            }

            if (!cullingResults.GetShadowCasterBounds(visibleLightIndex, out Bounds b))
            {
                return(new Vector4(-light.shadowStrength, 0f, 0f, maskChannel));
            }

            shadowedDirectionalLights[shadowedDirectionalLightCount] =
                new ShadowedDirectionalLight {
                visibleLightIndex = visibleLightIndex,
                slopeScaleBias    = light.shadowBias,
                nearPlaneOffset   = light.shadowNearPlane
            };

            return(new Vector4(light.shadowStrength, shadowSettings.directional.cascadeCount * shadowedDirectionalLightCount++, light.shadowNormalBias, maskChannel));
        }

        return(new Vector4(0f, 0f, 0f, -1f));
    }
Ejemplo n.º 7
0
    public void Apply()
    {
        lightingData.ApplyLightmapsTex();
        ApplyLightmapsRenderData();
        //下面代码不设置会没有烘焙的影子
        LightBakingOutput bakingOutput = new LightBakingOutput();

        bakingOutput.isBaked           = true;
        bakingOutput.lightmapBakeType  = LightmapBakeType.Mixed;
        bakingOutput.mixedLightingMode = MixedLightingMode.Shadowmask;
        dirLight.bakingOutput          = bakingOutput;
    }
Ejemplo n.º 8
0
    public Vector4 ReserveOtherShadows(Light light, int visibleLightIndex)
    {
        if (light.shadows != LightShadows.None && light.shadowStrength > 0f)
        {
            LightBakingOutput lightBaking = light.bakingOutput;
            if (lightBaking.lightmapBakeType == LightmapBakeType.Mixed && lightBaking.mixedLightingMode == MixedLightingMode.Shadowmask)
            {
                useShadowMask = true;

                return(new Vector4(light.shadowStrength, 0f, 0f, lightBaking.occlusionMaskChannel));
            }
        }

        return(new Vector4(0f, 0f, 0f, -1f));
    }
Ejemplo n.º 9
0
    public static int constructor(IntPtr l)
    {
        int result;

        try
        {
            LightBakingOutput lightBakingOutput = default(LightBakingOutput);
            LuaObject.pushValue(l, true);
            LuaObject.pushValue(l, lightBakingOutput);
            result = 2;
        }
        catch (Exception e)
        {
            result = LuaObject.error(l, e);
        }
        return(result);
    }
 void Update()
 {
     if (isBaked != bakeLight.bakingOutput.isBaked ||
         lightmapBakeType != bakeLight.bakingOutput.lightmapBakeType ||
         mixedLightingMode != bakeLight.bakingOutput.mixedLightingMode ||
         probeOcclusionLightIndex != bakeLight.bakingOutput.probeOcclusionLightIndex ||
         occlusionMaskChannel != bakeLight.bakingOutput.occlusionMaskChannel)
     {
         LightBakingOutput output = new LightBakingOutput();
         output.isBaked = isBaked;
         output.occlusionMaskChannel = occlusionMaskChannel;
         output.mixedLightingMode    = mixedLightingMode;
         output.occlusionMaskChannel = probeOcclusionLightIndex;
         output.lightmapBakeType     = lightmapBakeType;
         bakeLight.bakingOutput      = output;
     }
 }
Ejemplo n.º 11
0
    public Vector4 ReserveDirectioanlShadows(Light light, int visibleLightIndex)
    {
        if (ShadowedDirectionalLightCount < maxShadowedDirectionalLightCount &&
            light.shadows != LightShadows.None && light.shadowStrength > 0f //&&
            //cullingResults.GetShadowCasterBounds(visibleLightIndex, out Bounds b)
            )
        //the getshadowCasterBound will return false if the light does not effect any oject(can cast shadow) in shadow range
        {
            float maskChannel = -1;
            //we will decide wether to use the shadow mask depend on if the lights are using thi shadow mask
            LightBakingOutput lightBaking = light.bakingOutput;
            if (lightBaking.lightmapBakeType == LightmapBakeType.Mixed &&
                lightBaking.mixedLightingMode == MixedLightingMode.Shadowmask)
            {
                useShadowMask = true;
                maskChannel   = lightBaking.occlusionMaskChannel;
            }

            //Inform Shader the light does not affect anything, used for baked light attenuation
            if (!cullingResults.GetShadowCasterBounds(visibleLightIndex, out Bounds b))
            {
                return(new Vector4(-light.shadowStrength, 0f, maskChannel));
            }

            ShadowedDirectionalLights[ShadowedDirectionalLightCount] =
                new ShadowedDirectionalLight {
                visibleLightIndex = visibleLightIndex,
                slopScaleBias     = light.shadowBias,
                nearPlaneOffset   = light.shadowNearPlane
            };
            return(new Vector4(light.shadowStrength,
                               shadowSettings.directional.cascadeCount * ShadowedDirectionalLightCount++,
                               light.shadowNormalBias,
                               maskChannel));
        }
        else
        {
            return(new Vector4(0f, 0f, 0f, -1f));
        }
    }
        public Vector4 ReserveOtherShadows(Light light, int visibleLightIndex)
        {
            if (light.shadows == LightShadows.None || light.shadowStrength <= 0)
            {
                return(new Vector4(0f, 0f, 0f, -1f));
            }

            int occlusionMaskChannel            = -1;
            LightBakingOutput lightBakingOutput = light.bakingOutput;

            if (lightBakingOutput.lightmapBakeType == LightmapBakeType.Mixed && lightBakingOutput.mixedLightingMode == MixedLightingMode.Shadowmask)
            {
                useShadowMask        = true;
                occlusionMaskChannel = lightBakingOutput.occlusionMaskChannel;
            }

            bool isPoint       = light.type == LightType.Point;
            int  newLightCount = currentOtherShadowCount + (isPoint ? 6 : 1);

            if (newLightCount >= maxOtherShadaowCount || !cullingResults.GetShadowCasterBounds(visibleLightIndex, out Bounds bounds))
            {
                // the shadow strength of light is negative, see GetDirectionalShadowAttenuation in WindsmoonShadow.hlsl
                // if the stength is positive, the shader may be handle the shadow as realtime shadow
                return(new Vector4(-light.shadowStrength, 0f, 0f, occlusionMaskChannel));
            }

            otherShadows[currentOtherShadowCount] = new OtherShadow()
            {
                VisibleLightIndex = visibleLightIndex,
                SlopeScaleBias    = light.shadowBias,
                NoramlBias        = light.shadowNormalBias,
                IsPoint           = isPoint
            };

            Vector4 data = new Vector4(light.shadowStrength, currentOtherShadowCount, isPoint ? 1f : 0f, occlusionMaskChannel);

            currentOtherShadowCount = newLightCount;
            return(data);
        }
Ejemplo n.º 13
0
        public Vector3 ReserveDirectionalShadows(Light light, int visibleLightIndex)
        {
            // GetShadowCasterBounds  return true if the light affects at least one shadow casting object in the Scene
            if (currentDirectionalLightShadowCount >= maxDirectionalShadowCount || light.shadows == LightShadows.None || light.shadowStrength <= 0f ||
                cullingResults.GetShadowCasterBounds(visibleLightIndex, out Bounds bouds) == false)
            {
                return(Vector3.zero);
            }

            LightBakingOutput lightBakingOutput = light.bakingOutput;

            if (lightBakingOutput.lightmapBakeType == LightmapBakeType.Mixed && lightBakingOutput.mixedLightingMode == MixedLightingMode.Shadowmask)
            {
                useShadowMask = true;
            }

            directionalShadows[currentDirectionalLightShadowCount] = new DirectionalShadow()
            {
                visibleLightIndex = visibleLightIndex, slopeScaleBias = light.shadowBias, nearPlaneOffset = light.shadowNearPlane
            };
            return(new Vector3(light.shadowStrength, shadowSettings.DirectionalShadowSetting.CascadeCount * currentDirectionalLightShadowCount++, light.shadowNormalBias));
        }
 static void ApplyRendererInfo(RendererInfo[] infos, int lightmapOffsetIndex, LightInfo[] lightsInfo)
 {
     for (int i = 0; i < infos.Length; i++)
     {
         var info = infos[i];
         if (info.renderer != null)
         {
             info.renderer.lightmapIndex       = info.lightmapIndex + lightmapOffsetIndex;
             info.renderer.lightmapScaleOffset = info.lightmapOffsetScale;
         }
     }
     for (int i = 0; i < lightsInfo.Length; i++)
     {
         LightBakingOutput bakingOutput = new LightBakingOutput
         {
             isBaked           = true,
             lightmapBakeType  = (LightmapBakeType)lightsInfo[i].lightmapBaketype,
             mixedLightingMode = (MixedLightingMode)lightsInfo[i].mixedLightingMode
         };
         lightsInfo[i].light.bakingOutput = bakingOutput;
     }
 }
Ejemplo n.º 15
0
 public Vector4 ReserveOtherShadows(Light light, int visibleLightIndex)
 {
     if (light.shadows != LightShadows.None && light.shadowStrength > 0f)
     {
         LightBakingOutput lightBaking = light.bakingOutput;
         // But because their range is limited it is possible for multiple lights to use the same channel, as long as they don't overlap.
         //Thus the shadow mask can support an arbitrary amount of lights, but only up to four per texel. If multiple lights end up overlapping
         //while trying to claim the same channel then the least important lights will be forced to Baked mode until there is no longer a conflict.
         //如果灯光太多,会出现多个light取同一个channel,会将不重要的light强制变成baked,也就不会进行计算了
         if (
             lightBaking.lightmapBakeType == LightmapBakeType.Mixed &&
             lightBaking.mixedLightingMode == MixedLightingMode.Shadowmask
             )
         {
             useShadowMask = true;
             return(new Vector4(
                        light.shadowStrength, 0f, 0f,
                        lightBaking.occlusionMaskChannel
                        ));
         }
     }
     return(new Vector4(0f, 0f, 0f, -1f));
 }
Ejemplo n.º 16
0
    /// <summary>
    /// 配置灯光环境
    /// </summary>
    void ConfigureLights()
    {
        mainLightExists = false;
        bool shadowmaskExists    = false;
        bool subtractiveLighting = false;

        shadowTileCount = 0;
        for (int i = 0; i < cull.visibleLights.Count; i++)
        {
            if (i == maxVisibleLights)  //超过最大灯光数量跳出循环
            {
                break;
            }
            VisibleLight light = cull.visibleLights[i];
            //visibleLightColors[i] = light.finalColor;
            Vector4 attenuation = Vector4.zero;
            attenuation.w = 1;
            Vector4 shadow = Vector4.zero;

            LightBakingOutput baking = light.light.bakingOutput;
            //标识
            visibleLightOcclusionMasks[i] = occlusionMasks[baking.occlusionMaskChannel + 1];
            if (baking.lightmapBakeType == LightmapBakeType.Mixed)
            {
                shadowmaskExists |= baking.mixedLightingMode == MixedLightingMode.Shadowmask;
                //subtractiveLighting |= baking.mixedLightingMode == MixedLightingMode.Subtractive;
                if (baking.mixedLightingMode == MixedLightingMode.Subtractive)
                {
                    subtractiveLighting = true;
                    //设置的颜色设置进去
                    cameraBuffer.SetGlobalColor(subtractiveShadowColorId, RenderSettings.subtractiveShadowColor);
                }
            }
            if (light.lightType == LightType.Directional)
            {
                Vector4 v = light.localToWorld.GetColumn(2);
                v.x = -v.x;
                v.y = -v.y;
                v.z = -v.z;
                visibleLightDirectionsOrPositions[i] = v;
                shadow   = ConfigureShadows(i, light.light);
                shadow.z = 1f;  //标识处理方向光
                if (i == 0 && shadow.x > 0f && shadowCascades > 0)
                {
                    mainLightExists  = true;
                    shadowTileCount -= 1;
                }
            }
            else
            {
                visibleLightDirectionsOrPositions[i] = light.localToWorld.GetColumn(3);  //获取点光源位置
                attenuation.x = 1f / Mathf.Max(light.range * light.range, 0.00001f);

                if (light.lightType == LightType.Spot)
                {
                    Vector4 v = light.localToWorld.GetColumn(2);
                    v.x = -v.x;
                    v.y = -v.y;
                    v.z = -v.z;
                    visibleLightSpotDirections[i] = v;
                    float outerRad   = Mathf.Deg2Rad * 0.5f * light.spotAngle;
                    float outerCos   = Mathf.Cos(outerRad);
                    float outerTan   = Mathf.Tan(outerRad);
                    float innerCos   = Mathf.Cos(Mathf.Atan(((64f - 18f) / 64f) * outerTan));
                    float angleRange = Mathf.Max(innerCos - outerCos, 0.001f);
                    attenuation.z = 1f / angleRange;
                    attenuation.w = -outerCos * attenuation.z;

                    //阴影
                    //Light shadowLight = light.light;
                    //Bounds shadowBounds;
                    //if (shadowLight.shadows != LightShadows.None && cull.GetShadowCasterBounds(i, out shadowBounds))
                    //{
                    //    shadowTileCount += 1;
                    //    shadow.x = shadowLight.shadowStrength;  //x分量存阴影强度
                    //    shadow.y = shadowLight.shadows == LightShadows.Soft ? 1f : 0f;
                    //}
                    shadow = ConfigureShadows(i, light.light);
                }
                else
                {
                    visibleLightSpotDirections[i] = Vector4.one;
                }
            }
            visibleLightColors[i]       = light.finalColor;
            visibleLightAttenuations[i] = attenuation;
            shadowData[i] = shadow;
        }
        bool useDistanceShadowmask = QualitySettings.shadowmaskMode == ShadowmaskMode.DistanceShadowmask;

        //是否存在shadowMask
        CoreUtils.SetKeyword(cameraBuffer, shadowmaskKeyword, shadowmaskExists && !useDistanceShadowmask);
        CoreUtils.SetKeyword(cameraBuffer, subtractiveLightingKeyword, subtractiveLighting);
        CoreUtils.SetKeyword(cameraBuffer, distanceShadowmask, shadowmaskExists && useDistanceShadowmask);
        //for (; i < maxVisibleLights; i++)   //还原清除后面灯光颜色(0,0,0,0)
        //{
        //    visibleLightColors[i] = Color.clear;
        //}
        //告诉Unity 超出最大灯光数量的索引设置为-1使其不起作用
        if (mainLightExists || cull.visibleLights.Count > maxVisibleLights)
        {
            int[] lightIndices = cull.GetLightIndexMap();
            if (mainLightExists)
            {
                lightIndices[0] = -1;
            }
            for (int i = maxVisibleLights; i < cull.visibleLights.Count; i++)
            {
                lightIndices[i] = -1;
            }
            cull.SetLightIndexMap(lightIndices);
        }
    }
Ejemplo n.º 17
0
    void ConfigureLights()
    {
        mainLightExists = false;
        shadowTileCount = 0;
        bool shadowmaskExists = false;

        for (int i = 0; i < cull.visibleLights.Length; i++)
        {
            if (i == maxVisibleLights)
            {
                break;
            }

            VisibleLight light = cull.visibleLights[i];
            visibleLightColors[i] = light.finalColor;
            Vector4 attenuation = Vector4.zero;
            attenuation.w = 1f;
            Vector4 shadow = Vector4.zero;

            // shadowmask ?
            LightBakingOutput baking = light.light.bakingOutput;
            visibleLightOcclusionMasks[i] = occlusionMasks[baking.occlusionMaskChannel + 1];
            if (baking.lightmapBakeType == LightmapBakeType.Mixed)
            {
                shadowmaskExists |= baking.mixedLightingMode == MixedLightingMode.Shadowmask;
            }

            if (light.lightType == LightType.Directional)
            {
                Vector4 v = light.localToWorldMatrix.GetColumn(2);
                v.x = -v.x;
                v.y = -v.y;
                v.z = -v.z;
                visibleLightDirectionsOrPositions[i] = v;
                shadow   = ConfigureShadows(i, light.light);
                shadow.z = 1f;// flag
                if (i == 0 && shadow.x > 0f && shadowCascades > 0)
                {
                    mainLightExists  = true;
                    shadowTileCount -= 1;
                }
            }
            else
            {
                visibleLightDirectionsOrPositions[i] = light.localToWorldMatrix.GetColumn(3);
                attenuation.x = 1f / Mathf.Max(light.range * light.range, 0.00001f);
                if (light.lightType == LightType.Spot)
                {
                    Vector4 v = light.localToWorldMatrix.GetColumn(2);
                    v.x = -v.x;
                    v.y = -v.y;
                    v.z = -v.z;
                    visibleLightSpotDirections[i] = v;

                    float outerRad   = Mathf.Deg2Rad * 0.5f * light.spotAngle;
                    float outerCos   = Mathf.Cos(outerRad);
                    float outerTan   = Mathf.Tan(outerRad);
                    float innerCos   = Mathf.Cos(Mathf.Atan((46f / 64f) * outerTan));
                    float angleRange = Mathf.Max(innerCos - outerCos, 0.001f);
                    attenuation.z = 1f / angleRange;
                    attenuation.w = -outerCos * attenuation.z;
                    shadow        = ConfigureShadows(i, light.light);
                }
                else
                {
                    visibleLightSpotDirections[i] = Vector4.one;
                }
            }

            visibleLightAttenuations[i] = attenuation;
            shadowData[i] = shadow;
        }

        // shadowmask
        bool useDistanceShadowmask = QualitySettings.shadowmaskMode == ShadowmaskMode.DistanceShadowmask;

        CoreUtils.SetKeyword(cameraBuffer, shadowmaskKeyword, shadowmaskExists && !useDistanceShadowmask);
        CoreUtils.SetKeyword(cameraBuffer, distanceShadowmaskKeyword, shadowmaskExists && useDistanceShadowmask);

        if (mainLightExists || cull.visibleLights.Length > maxVisibleLights)
        {
            NativeArray <int> lightIndices = cull.GetLightIndexMap(Allocator.Temp);
            if (mainLightExists)
            {
                lightIndices[0] = -1;
            }
            for (int i = maxVisibleLights; i < cull.visibleLights.Length; i++)
            {
                lightIndices[i] = -1;
            }
            cull.SetLightIndexMap(lightIndices);
        }
    }
Ejemplo n.º 18
0
        private void ConfigureLights()
        {
            mainLightExists = false;
            bool shadowmaskExists    = false;
            bool subtractiveLighting = false;

            shadowTileCount = 0;
            for (int i = 0; i < cullingResults.visibleLights.Length; i++)
            {
                if (i == maxVisibleLights)
                {
                    break;
                }
                VisibleLight light = cullingResults.visibleLights[i];
                // finalColor字段存储了光源的颜色,该颜色数据是由光源的color属性和intensity属性相乘后的结果,并经过了颜色空间的校正。
                visibleLightColors[i] = light.finalColor;
                Vector4 attenuation = Vector4.zero;
                attenuation.w = 1f; // 为了保证不同类型的光照计算的一致性(用同样的shader代码),将w分量设置为1。
                Vector4 shadow = Vector4.zero;

                LightBakingOutput baking = light.light.bakingOutput;
                // 有四种可能的掩码,我们可以在静态数组(occlusionMasks)中预定义。
                // 但也有可能有些灯光不使用阴影遮罩。我们将通过将第一个遮罩组件设置为-1来指示这一点。
                // 如果灯光不使用阴影遮罩,则通道为-1,因此在检索预定义的 occlusionMasks 时+1。
                visibleLightOcclusionMasks[i] = occlusionMasks[baking.occlusionMaskChannel + 1];
                if (baking.lightmapBakeType == LightmapBakeType.Mixed)
                {
                    shadowmaskExists |= baking.mixedLightingMode == MixedLightingMode.Shadowmask; // 判读是否存在烘培阴影。
                    if (baking.mixedLightingMode == MixedLightingMode.Subtractive)
                    {
                        subtractiveLighting = true;
                        cameraBuffer.SetGlobalColor(subtractiveShadowColorId, UnityEngine.RenderSettings.subtractiveShadowColor.linear);
                    }
                }

                if (light.lightType == LightType.Directional)
                {
                    // 方向光的光源方向信息可以通过光源的旋转信息获得,光源的方向是它的z轴方向。
                    // 我们可以通过VisibleLight.localToWorldMatrix矩阵获取在世界坐标系中的该信息。这个矩阵的第三列定义了光源的本地Z轴方向。
                    Vector4 v = light.localToWorldMatrix.GetColumn(2);
                    // 在shader中我们使用从物体朝向光源的向量方向进行计算,所以将获得的光源方向进行取反操作。
                    v.x = -v.x;
                    v.y = -v.y;
                    v.z = -v.z;
                    visibleLightDirectionsOrPositions[i] = v;
                    // 设置阴影。
                    shadow   = ConfigureShadows(i, light.light);
                    shadow.z = 1f; // 用阴影数据的z分量来区分是方向光还是聚光灯。
                    if (i == 0 && shadow.x > 0f && ShadowCascades > 0)
                    {
                        mainLightExists = true;
                        // 我们会为主光源提供单独的渲染贴图,所以当我们拥有主光源时,让图块计数减1,
                        // 并且在RenderShadows函数中将其从常规阴影贴图渲染中排除。
                        shadowTileCount -= 1;
                    }
                }
                else if (light.lightType == LightType.Point || light.lightType == LightType.Spot)
                {
                    // 点光源不关心光的方向而关心光源的位置。这个矩阵的第四列定义了光源的世界位置。
                    visibleLightDirectionsOrPositions[i] = light.localToWorldMatrix.GetColumn(3);
                    attenuation.x = 1f / Mathf.Max(light.range * light.range, 0.00001f);
                    if (light.lightType == LightType.Spot)
                    {
                        // 聚光灯的光源方向。
                        Vector4 v = light.localToWorldMatrix.GetColumn(2);
                        v.x = -v.x;
                        v.y = -v.y;
                        v.z = -v.z;
                        visibleLightSpotDirections[i] = v;
                        // 聚光灯的衰减。
                        float outerRad   = Mathf.Deg2Rad * 0.5f * light.spotAngle;
                        float outerCos   = Mathf.Cos(outerRad);
                        float outerTan   = Mathf.Tan(outerRad);
                        float innerCos   = Mathf.Cos(Mathf.Atan(((46f / 64f) * outerTan)));
                        float angleRange = Mathf.Max(innerCos - outerCos, 0.001f);
                        attenuation.z = 1f / angleRange;
                        attenuation.w = -outerCos * attenuation.z;
                        // 设置阴影。
                        shadow = ConfigureShadows(i, light.light);
                    }
                    else
                    {
                        visibleLightSpotDirections[i] = Vector4.one;
                    }
                }
                // 填充点光源或聚光灯的光照范围。
                visibleLightAttenuations[i] = attenuation;
                shadowData[i] = shadow;
            }

            cameraBuffer.SetGlobalVectorArray(visibleLightColorsId, visibleLightColors);
            cameraBuffer.SetGlobalVectorArray(visibleLightDirectionsOrPositionsId, visibleLightDirectionsOrPositions);
            cameraBuffer.SetGlobalVectorArray(visibleLightAttenuationsId, visibleLightAttenuations);     // 点光源。
            cameraBuffer.SetGlobalVectorArray(visibleLightSpotDirectionsId, visibleLightSpotDirections); // 聚光灯。
            cameraBuffer.SetGlobalVectorArray(visibleLightOcclusionMasksId, visibleLightOcclusionMasks);

            // 尽管目前我们已经支持到场景中最多16个光源,但是依然无法避免有可能会存在更多光源的情况。
            // 当超出时,我们需要告诉Unity需要将一些光源舍弃以避免数组的越界。
            // 如果主光源存在,在渲染前将主光源移出可见光列表,以防止在shader中计算多次(会导致像素光数量上限变成5个)。
            if (mainLightExists || cullingResults.visibleLights.Length > maxVisibleLights)
            {
                var lightIndexs = cullingResults.GetLightIndexMap(Unity.Collections.Allocator.TempJob);
                if (mainLightExists)
                {
                    lightIndexs[0] = -1;
                }
                for (int i = maxVisibleLights; i < cullingResults.visibleLights.Length; i++)
                {
                    lightIndexs[i] = -1;
                }
                cullingResults.SetLightIndexMap(lightIndexs);
                lightIndexs.Dispose();
            }

            bool useDistanceShadowmask = QualitySettings.shadowmaskMode == ShadowmaskMode.DistanceShadowmask;

            CoreUtils.SetKeyword(cameraBuffer, shadowmaskKeyword, shadowmaskExists && !useDistanceShadowmask);
            CoreUtils.SetKeyword(cameraBuffer, distanceShadowmaskKeyword, shadowmaskExists && useDistanceShadowmask);
            CoreUtils.SetKeyword(cameraBuffer, subtractiveLightingKeyword, subtractiveLighting);
        }
Ejemplo n.º 19
0
    void ConfigureLights()
    {
        mainLightExists = false;
        bool shadowmaskExists    = false;
        bool subtractiveLighting = false;

        shadowTileCount = 0;
        for (int i = 0; i < cull.visibleLights.Count; i++)
        {
            if (i == maxVisibleLights)
            {
                break;
            }

            VisibleLight light = cull.visibleLights[i];
            visibleLightColors[i] = light.finalColor;

            Vector4 attenuation = Vector4.zero;
            attenuation.w = 1f;
            Vector4 shadow = Vector4.zero;

            LightBakingOutput baking = light.light.bakingOutput;
            visibleLightOcclusionMasks[i] = occlusionMasks[baking.occlusionMaskChannel + 1];
            if (baking.lightmapBakeType == LightmapBakeType.Mixed)
            {
                shadowmaskExists |=
                    baking.mixedLightingMode == MixedLightingMode.Shadowmask;
                //subtractiveLighting |=
                //    baking.mixedLightingMode == MixedLightingMode.Subtractive;

                if (baking.mixedLightingMode == MixedLightingMode.Subtractive)
                {
                    subtractiveLighting = true;
                    cameraBuffer.SetGlobalColor(
                        subtractiveShadowColorId,
                        RenderSettings.subtractiveShadowColor.linear
                        );
                }
            }

            if (light.lightType == LightType.Directional)
            {
                //因为要求出光源的朝向,相当于要知道光源transform.forward,矩阵第三列是光源z轴在世界坐标系下表示,也就是forward
                Vector4 v = light.localToWorld.GetColumn(2);
                v.x = -v.x;
                v.y = -v.y;
                v.z = -v.z;
                visibleLightDirectionsOrPositions[i] = v;
                shadow   = ConfigureShadows(i, light.light);
                shadow.z = 1f;

                if (i == 0 && shadow.x > 0f && shadowCascades > 0)
                {
                    mainLightExists  = true;
                    shadowTileCount -= 1;
                }
            }
            else
            {
                //第四列是光源原点在世界坐标系中的位置
                visibleLightDirectionsOrPositions[i] = light.localToWorld.GetColumn(3);
                attenuation.x = 1f / Mathf.Max(light.range * light.range, 0.00001f);

                if (light.lightType == LightType.Spot)
                {
                    Vector4 v = light.localToWorld.GetColumn(2);
                    v.x = -v.x;
                    v.y = -v.y;
                    v.z = -v.z;
                    //存储spot光源方向
                    visibleLightSpotDirections[i] = v;

                    float outerRad   = Mathf.Deg2Rad * 0.5f * light.spotAngle;
                    float outerCos   = Mathf.Cos(outerRad);
                    float outerTan   = Mathf.Tan(outerRad);
                    float innerCos   = Mathf.Cos(Mathf.Atan(((46f / 64f) * outerTan)));
                    float angleRange = Mathf.Max(innerCos - outerCos, 0.001f);
                    attenuation.z = 1f / angleRange;
                    attenuation.w = -outerCos * attenuation.z;

                    shadow = ConfigureShadows(i, light.light);

                    //Light shadowLight = light.light;
                    //Bounds shadowBounds;
                    //if (shadowLight.shadows != LightShadows.None && cull.GetShadowCasterBounds(i, out shadowBounds))
                    //{
                    //    shadowTileCount += 1;
                    //    shadow.x = shadowLight.shadowStrength;
                    //    shadow.y = shadowLight.shadows == LightShadows.Soft ? 1f : 0f;
                    //}
                }
                else
                {
                    visibleLightSpotDirections[i] = Vector4.one;
                }
            }
            visibleLightAttenuations[i] = attenuation;
            shadowData[i] = shadow;
        }

        bool useDistanceShadowmask =
            QualitySettings.shadowmaskMode == ShadowmaskMode.DistanceShadowmask;

        CoreUtils.SetKeyword(cameraBuffer, shadowmaskKeyword, shadowmaskExists && !useDistanceShadowmask);
        CoreUtils.SetKeyword(
            cameraBuffer, distanceShadowmaskKeyword,
            shadowmaskExists && useDistanceShadowmask
            );
        CoreUtils.SetKeyword(cameraBuffer, subtractiveLightingKeyword, subtractiveLighting);

        //如果超过maxVisibleLights数量的灯光,该脚本不会传输给Shader
        //但是Unity自身可能会对超出maxVisibleLights的灯光,进行unity_4LightIndices0赋值,下标会找不到,_VisibleLightColors越界
        if (mainLightExists || cull.visibleLights.Count > maxVisibleLights)
        {
            int[] lightIndices = cull.GetLightIndexMap();
            if (mainLightExists)
            {
                lightIndices[0] = -1;
            }
            for (int i = maxVisibleLights; i < cull.visibleLights.Count; i++)
            {
                lightIndices[i] = -1;
            }
            cull.SetLightIndexMap(lightIndices);
        }
    }
Ejemplo n.º 20
0
    public static void RefreshScene(Scene scene, ftLightmapsStorage storage = null, bool updateNonBaked = false)
    {
        var sceneCount = SceneManager.sceneCount;

        if (globalMapsAdditional == null)
        {
            globalMapsAdditional = new List <LightmapAdditionalData>();
        }

        var lmaps                   = new List <LightmapData>();
        var lmapsAdditional         = new List <LightmapAdditionalData>();
        var existingLmaps           = LightmapSettings.lightmaps;
        var existingLmapsAdditional = globalMapsAdditional;

        // Acquire storage
        if (storage == null)
        {
            if (!scene.isLoaded)
            {
                //Debug.LogError("dbg: Scene not loaded");
                return;
            }
            SceneManager.SetActiveScene(scene);

            var go = FindInScene("!ftraceLightmaps", scene);
            if (go == null)
            {
                //Debug.LogError("dbg: no storage");
                return;
            }

            storage = go.GetComponent <ftLightmapsStorage>();
            if (storage == null)
            {
                //Debug.LogError("dbg: no storage 2");
                return;
            }
        }
        if (storage.idremap == null || storage.idremap.Length != storage.maps.Count)
        {
            storage.idremap = new int[storage.maps.Count];
        }

        // Decide which global engine lightmapping mode to use
        // TODO: allow mixing different modes
        directionalMode = storage.dirMaps.Count != 0;
        bool patchedDirection = false;

        LightmapSettings.lightmapsMode = directionalMode ? LightmapsMode.CombinedDirectional : LightmapsMode.NonDirectional;


        // Set dummy directional tex for non-directional lightmaps in directional mode
        if (directionalMode)
        {
            for (int i = 0; i < existingLmaps.Length; i++)
            {
                if (directionalMode && existingLmaps[i].lightmapDir == null)
                {
                    var lm = existingLmaps[i];
                    lm.lightmapDir   = GetEmptyDirectionTex(storage);
                    existingLmaps[i] = lm;
                    patchedDirection = true;
                }
            }
        }

        // Detect if changes to lightmap array are necessary
        bool sameArray = false;

        if (existingLmaps.Length == storage.maps.Count)
        {
            sameArray = true;
            for (int i = 0; i < storage.maps.Count; i++)
            {
                if (existingLmaps[i].lightmapColor != storage.maps[i])
                {
                    sameArray = false;
                    break;
                }
                if (storage.rnmMaps0.Count > i && (existingLmapsAdditional.Count <= i || existingLmapsAdditional[i].rnm0 != storage.rnmMaps0[i]))
                {
                    sameArray = false;
                    break;
                }
            }
        }

        if (!sameArray) // create new lightmap array
        {
            if (sceneCount >= 1)
            {
                // first add old
                for (int i = 0; i < existingLmaps.Length; i++)
                {
                    // skip empty lightmaps (can be created by 5.6 ldata asset or vertex color)
                    // ... unless there are valid lightmaps around them
                    bool lightmapIsEmpty      = existingLmaps[i] == null || (existingLmaps[i].lightmapColor == null && existingLmaps[i].shadowMask == null);
                    bool lightmapCanBeSkipped = lightmapIsEmpty && (i == 0 || i == existingLmaps.Length - 1);
                    if (!lightmapCanBeSkipped)
                    {
                        lmaps.Add(existingLmaps[i]);
                        if (existingLmapsAdditional.Count > i)
                        {
                            lmapsAdditional.Add(existingLmapsAdditional[i]);
                        }
                    }
                }
            }

            for (int i = 0; i < storage.maps.Count; i++)
            {
                var       texlm   = storage.maps[i];
                Texture2D texmask = null;
                Texture2D texdir  = null;
                Texture2D texrnm0 = null;
                Texture2D texrnm1 = null;
                Texture2D texrnm2 = null;
                int       mapMode = 0;
                if (storage.masks.Count > i)
                {
                    texmask = storage.masks[i];
                }
                if (storage.dirMaps.Count > i)
                {
                    texdir = storage.dirMaps[i];
                }
                if (storage.rnmMaps0.Count > i)
                {
                    texrnm0 = storage.rnmMaps0[i];
                    texrnm1 = storage.rnmMaps1[i];
                    texrnm2 = storage.rnmMaps2[i];
                    mapMode = storage.mapsMode[i];
                }

                bool found      = false;
                int  firstEmpty = -1;
                for (int j = 0; j < lmaps.Count; j++)
                {
                    if (lmaps[j].lightmapColor == texlm && lmaps[j].shadowMask == texmask)
                    {
                        // lightmap already added - reuse
                        storage.idremap[i] = j;
                        found = true;

                        //Debug.LogError("reused "+j);

                        // additional maps array could be flushed due to script recompilation - recover
                        if (texrnm0 != null && (lmapsAdditional.Count <= j || lmapsAdditional[j].rnm0 == null))
                        {
                            while (lmapsAdditional.Count <= j)
                            {
                                lmapsAdditional.Add(new LightmapAdditionalData());
                            }
                            var l = new LightmapAdditionalData();
                            l.rnm0             = texrnm0;
                            l.rnm1             = texrnm1;
                            l.rnm2             = texrnm2;
                            l.mode             = mapMode;
                            lmapsAdditional[j] = l;
                        }

                        break;
                    }
                    else if (firstEmpty < 0 && lmaps[j].lightmapColor == null && lmaps[j].shadowMask == null)
                    {
                        // free (deleted) entry in existing lightmap list - possibly reuse
                        storage.idremap[i] = j;
                        firstEmpty         = j;
                    }
                }

                if (!found)
                {
                    LightmapData lm;
                    if (firstEmpty >= 0)
                    {
                        lm = lmaps[firstEmpty];
                    }
                    else
                    {
                        lm = new LightmapData();
                    }

                    lm.lightmapColor = texlm;
                    if (storage.masks.Count > i)
                    {
                        lm.shadowMask = texmask;
                    }
                    if (storage.dirMaps.Count > i && texdir != null)
                    {
                        lm.lightmapDir = texdir;
                    }
                    else if (directionalMode)
                    {
                        lm.lightmapDir = GetEmptyDirectionTex(storage);
                    }

                    if (firstEmpty < 0)
                    {
                        lmaps.Add(lm);
                        storage.idremap[i] = lmaps.Count - 1;
                    }
                    else
                    {
                        lmaps[firstEmpty] = lm;
                    }

                    if (storage.rnmMaps0.Count > i)
                    {
                        var l = new LightmapAdditionalData();
                        l.rnm0 = texrnm0;
                        l.rnm1 = texrnm1;
                        l.rnm2 = texrnm2;
                        l.mode = mapMode;

                        if (firstEmpty < 0)
                        {
                            //Debug.LogError("added "+(lmaps.Count-1));
                            while (lmapsAdditional.Count < lmaps.Count - 1)
                            {
                                lmapsAdditional.Add(new LightmapAdditionalData());
                            }
                            lmapsAdditional.Add(l);
                        }
                        else
                        {
                            //Debug.LogError("set " + firstEmpty);
                            while (lmapsAdditional.Count < firstEmpty + 1)
                            {
                                lmapsAdditional.Add(new LightmapAdditionalData());
                            }
                            lmapsAdditional[firstEmpty] = l;
                        }
                    }
                }
            }
        }
        else // reuse existing lightmap array, only remap IDs
        {
            for (int i = 0; i < storage.maps.Count; i++)
            {
                storage.idremap[i] = i;

                //Debug.LogError("full reuse");

                /*if (storage.rnmMaps0.Count > i)
                 * {
                 *  var l = new LightmapAdditionalData();
                 *  l.rnm0 = storage.rnmMaps0[i];
                 *  l.rnm1 = storage.rnmMaps1[i];
                 *  l.rnm2 = storage.rnmMaps2[i];
                 *  l.mode = storage.mapsMode[i];
                 *  lmapsAdditional.Add(l);
                 * }*/
            }
        }

#if UNITY_EDITOR
        // Set editor lighting mode
        Lightmapping.giWorkflowMode = Lightmapping.GIWorkflowMode.OnDemand;
        Lightmapping.realtimeGI     = storage.usesRealtimeGI;
        Lightmapping.bakedGI        = true;
#endif

        // Replace the lightmap array if needed
        if (sameArray && patchedDirection)
        {
            LightmapSettings.lightmaps = existingLmaps;
        }
        if (!sameArray)
        {
            LightmapSettings.lightmaps = lmaps.ToArray();
            globalMapsAdditional       = lmapsAdditional;
        }

        /*
         * // Debug
         * var lms = LightmapSettings.lightmaps;
         * for(int i=0; i<lms.Length; i++)
         * {
         *  var name1 = ((lms[i]==null || lms[i].lightmapColor==null) ? "-" : lms[i].lightmapColor.name);
         *  var name2 = (globalMapsAdditional.Count > i ?(globalMapsAdditional[i].rnm0==null?"x":globalMapsAdditional[i].rnm0.name) : "-");
         *  Debug.LogError(i+" "+name1+" "+name2);
         * }
         */

        // Attempt to update skybox probe
        if (RenderSettings.ambientMode == UnityEngine.Rendering.AmbientMode.Skybox)// && Lightmapping.lightingDataAsset == null)
        {
            var probe   = RenderSettings.ambientProbe;
            int isEmpty = -1;
            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 9; j++)
                {
                    // default bugged probes are [almost] black or 1302?
                    float a = Mathf.Abs(probe[i, j]);
                    if (a > 1000.0f || a < 0.000001f)
                    {
                        isEmpty = 1;
                        break;
                    }
                    if (probe[i, j] != 0)
                    {
                        isEmpty = 0;
                        break;
                    }
                }
                if (isEmpty >= 0)
                {
                    break;
                }
            }
            if (isEmpty != 0)
            {
                DynamicGI.UpdateEnvironment();
            }
        }

        // Set lightmap data on mesh renderers
        var emptyVec4 = new Vector4(1, 1, 0, 0);
        for (int i = 0; i < storage.bakedRenderers.Count; i++)
        {
            var r = storage.bakedRenderers[i];
            if (r == null)
            {
                continue;
            }
            //if (r.isPartOfStaticBatch) continue;
            var  id    = storage.bakedIDs[i];
            Mesh vmesh = null;
            if (i < storage.bakedVertexColorMesh.Count)
            {
                vmesh = storage.bakedVertexColorMesh[i];
            }

            if (vmesh != null)
            {
                r.additionalVertexStreams = vmesh;
                r.lightmapIndex           = 0xFFFF;
                var prop = new MaterialPropertyBlock();
                prop.SetFloat("bakeryLightmapMode", 1);
                r.SetPropertyBlock(prop);
                continue;
            }

            int globalID = (id < 0 || id >= storage.idremap.Length) ? id : storage.idremap[id];
            r.lightmapIndex = globalID;

            if (!r.isPartOfStaticBatch)
            {
                // scaleOffset is baked on static batches already
                var scaleOffset = id < 0 ? emptyVec4 : storage.bakedScaleOffset[i];
                r.lightmapScaleOffset = scaleOffset;
            }

            if (r.lightmapIndex >= 0 && globalID < globalMapsAdditional.Count)
            {
                var lmap = globalMapsAdditional[globalID];
                if (lmap.rnm0 != null)
                {
                    var prop = new MaterialPropertyBlock();
                    prop.SetTexture("_RNM0", lmap.rnm0);
                    prop.SetTexture("_RNM1", lmap.rnm1);
                    prop.SetTexture("_RNM2", lmap.rnm2);
                    prop.SetFloat("bakeryLightmapMode", lmap.mode);
                    r.SetPropertyBlock(prop);
                }
            }
        }

        // Set lightmap data on definitely-not-baked mesh renderers (can be possibly avoided)
        if (updateNonBaked)
        {
            for (int i = 0; i < storage.nonBakedRenderers.Count; i++)
            {
                var r = storage.nonBakedRenderers[i];
                if (r == null)
                {
                    continue;
                }
                if (r.isPartOfStaticBatch)
                {
                    continue;
                }
                r.lightmapIndex = 0xFFFE;
            }
        }

        // Set lightmap data on terrains
        for (int i = 0; i < storage.bakedRenderersTerrain.Count; i++)
        {
            var r = storage.bakedRenderersTerrain[i];
            if (r == null)
            {
                continue;
            }
            var id = storage.bakedIDsTerrain[i];
            r.lightmapIndex = (id < 0 || id >= storage.idremap.Length) ? id : storage.idremap[id];

            var scaleOffset = id < 0 ? emptyVec4 : storage.bakedScaleOffsetTerrain[i];
            r.lightmapScaleOffset = scaleOffset;
        }

        // Set shadowmask parameters on lights
        for (int i = 0; i < storage.bakedLights.Count; i++)
        {
#if UNITY_2017_3_OR_NEWER
            var output = new LightBakingOutput();
            output.isBaked                      = true;
            output.lightmapBakeType             = LightmapBakeType.Mixed;
            output.mixedLightingMode            = MixedLightingMode.Shadowmask;
            output.occlusionMaskChannel         = storage.bakedLightChannels[i];
            output.probeOcclusionLightIndex     = storage.bakedLights[i].bakingOutput.probeOcclusionLightIndex;
            storage.bakedLights[i].bakingOutput = output;
            //#else
            //var light = storage.bakedLights[i];
#endif
        }

        // Increment lightmap refcounts
        if (lightmapRefCount == null)
        {
            lightmapRefCount = new List <int>();
        }
        for (int i = 0; i < storage.idremap.Length; i++)
        {
            int currentID = storage.idremap[i];
            while (lightmapRefCount.Count <= currentID)
            {
                lightmapRefCount.Add(0);
            }
            if (lightmapRefCount[currentID] < 0)
            {
                lightmapRefCount[currentID] = 0;
            }
            lightmapRefCount[currentID]++;
        }
        //if (loadedStorages == null) loadedStorages = new List<ftLightmapsStorage>();
        //if (loadedStorages.Contains(storage)) loadedStorages.Add(storage);

        //return appendOffset;
    }
Ejemplo n.º 21
0
    void ConfigureLights()
    {
        mainLightExist = false;
        bool shadowmaskExists    = false;
        bool subtractiveLighting = false;

        shadowTileCount = 0;
        for (int i = 0; i < cull.visibleLights.Count; i++)
        {
            if (i == maxVisibleLights)
            {
                break;
            }
            VisibleLight light = cull.visibleLights[i];
            visibleLightColors[i] = light.finalColor;
            Vector4 attenuation = Vector4.zero;
            attenuation.w = 1f;
            Vector4 shadow = Vector4.zero;

            LightBakingOutput baking = light.light.bakingOutput;
            visibleLightOcclusionMasks[i] = occlusionMasks[baking.occlusionMaskChannel + 1];
            if (baking.lightmapBakeType == LightmapBakeType.Mixed)
            {
                shadowmaskExists |= baking.mixedLightingMode == MixedLightingMode.Shadowmask;
                if (baking.mixedLightingMode == MixedLightingMode.Subtractive)
                {
                    subtractiveLighting = true;
                    cameraBuffer.SetGlobalColor(subtractiveShadowColorID, RenderSettings.subtractiveShadowColor.linear);
                }
            }

            if (light.lightType == LightType.Directional)
            {
                Vector4 v = light.localToWorld.GetColumn(2);
                v.x = -v.x;
                v.y = -v.y;
                v.z = -v.z;
                visibleLightDirectionsOrPositions[i] = v;
                shadow   = ConfigureShadows(i, light.light);
                shadow.z = 1f;
                if (i == 0 && shadow.x > 0f && shadowCascades > 0)
                {
                    mainLightExist   = true;
                    shadowTileCount -= 1;
                }
            }
            else
            {
                visibleLightDirectionsOrPositions[i] = light.localToWorld.GetColumn(3);
                attenuation.x = 1f / Mathf.Max(light.range * light.range, 0.00001f);

                if (light.lightType == LightType.Spot)
                {
                    Vector4 v = light.localToWorld.GetColumn(2);
                    v.x = -v.x;
                    v.y = -v.y;
                    v.z = -v.z;
                    visibleLightSpotDirections[i] = v;

                    float outerAngle = Mathf.Deg2Rad * light.spotAngle;
                    float outerCos   = Mathf.Cos(outerAngle * 0.5f);
                    float innerAngle = 2.0f * Mathf.Atan(Mathf.Tan(outerAngle * 0.5f) * (64.0f - 18.0f) / 64.0f);
                    float innerCos   = Mathf.Cos(innerAngle * 0.5f);
                    float angleRange = Mathf.Max(0.001f, innerCos - outerCos);
                    attenuation.z = 1.0f / angleRange;
                    attenuation.w = -outerCos * attenuation.z;

                    Light shadowLight = light.light;
                    shadow = ConfigureShadows(i, shadowLight);
                }
                else
                {
                    visibleLightSpotDirections[i] = Vector4.one;
                }
            }
            visibleLightAttenuations[i] = attenuation;
            shadowData[i] = shadow;
        }

        bool useDistanceShadowmask = QualitySettings.shadowmaskMode == ShadowmaskMode.DistanceShadowmask;

        CoreUtils.SetKeyword(cameraBuffer, shadowmaskKeyword, shadowmaskExists && !useDistanceShadowmask);
        CoreUtils.SetKeyword(cameraBuffer, distanceShadowmaskKeyword, shadowmaskExists && useDistanceShadowmask);
        CoreUtils.SetKeyword(cameraBuffer, subtractiveLightingKeyword, subtractiveLighting);

        if (mainLightExist || cull.visibleLights.Count > maxVisibleLights)
        {
            int[] lightIndices = cull.GetLightIndexMap();
            if (mainLightExist)
            {
                lightIndices[0] = -1;
            }
            for (int i = maxVisibleLights; i < cull.visibleLights.Count; i++)
            {
                lightIndices[i] = -1;
            }
            cull.SetLightIndexMap(lightIndices);
        }
    }
    private void ConfigureLights()
    {
        mainLightExists = false;
        bool shadowmaskExists    = false;
        bool subtractiveLighting = false;

        shadowTileCount = 0;
        for (int i = 0; i < cull.visibleLights.Count && i < maxVisibleLights; i++)
        {
            VisibleLight light = cull.visibleLights[i];
            visibleLightColors[i] = light.finalColor;

            Vector4 attenuation = Vector4.zero;
            attenuation.w = 1f;
            Vector4 shadow = Vector4.zero;

            LightBakingOutput baking = light.light.bakingOutput;
            visibleLightOcclusionMasks[i] = occlusionMasks[baking.occlusionMaskChannel + 1];
            if (baking.lightmapBakeType == LightmapBakeType.Mixed)
            {
                shadowmaskExists |= baking.mixedLightingMode == MixedLightingMode.Shadowmask;
                if (baking.mixedLightingMode == MixedLightingMode.Subtractive)
                {
                    subtractiveLighting = true;
                    cameraBuffer.SetGlobalColor(subtractiveShadowColorID, RenderSettings.subtractiveShadowColor.linear);
                }
            }

            if (light.lightType == LightType.Directional)
            {
                //光线按照局部Z轴照射  第三列是Z轴旋转
                Vector4 v = light.localToWorld.GetColumn(2);
                //在shader中 我们需要的光的方向是 从表面到光的  所以要求反
                //第四个分量总是零 只用对 x y z 求反
                v.x = -v.x;
                v.y = -v.y;
                v.z = -v.z;
                visibleLightDirectionsOrPositions[i] = v;
                shadow = ConfigureShadows(i, light.light);
                //z=1 是方向光
                shadow.z = 1f;
                if (i == 0 && shadow.x > 0f && shadowCascades > 0)
                {
                    mainLightExists  = true;
                    shadowTileCount -= 1;
                }
            }
            else
            {
                //第三个储存的是位置 w是1
                visibleLightDirectionsOrPositions[i]
                    = light.localToWorld.GetColumn(3);

                attenuation.x = 1f / Mathf.Max(light.range * light.range, 0.000001f);

                if (light.lightType == LightType.Spot)
                {
                    //聚光灯需要 方向 拿Z轴  即矩阵第三行
                    Vector4 v = light.localToWorld.GetColumn(2);

                    v.x = -v.x;
                    v.y = -v.y;
                    v.z = -v.z;
                    visibleLightSpotDirections[i] = v;

                    float outerRad = Mathf.Deg2Rad * 0.5f * light.spotAngle;
                    //灯光角的一半   外面不显示
                    float outerCos = Mathf.Cos(outerRad);
                    //内圈 不衰减
                    float outerTan = Mathf.Tan(outerRad);
                    //外圈衰减
                    float innerCos =
                        Mathf.Cos(Mathf.Atan(((64f - 18f) / 64f) * outerTan));
                    float angleRange = Mathf.Max(innerCos - outerCos, 0.0001f);
                    attenuation.z = 1f / angleRange;
                    attenuation.w = -outerCos * attenuation.z;

                    shadow = ConfigureShadows(i, light.light);
                }
                else
                {
                    visibleLightSpotDirections[i] = Vector4.one;
                }
            }

            visibleLightAttenuations[i] = attenuation;
            shadowData[i] = shadow;
        }

        bool useDistanceShadowmask = QualitySettings.shadowmaskMode == ShadowmaskMode.DistanceShadowmask;

        CoreUtils.SetKeyword(cameraBuffer, shadowmaskKeyword, shadowmaskExists && !useDistanceShadowmask);
        CoreUtils.SetKeyword(cameraBuffer, distanceShadowmaskKeyword, shadowmaskExists && useDistanceShadowmask);
        CoreUtils.SetKeyword(cameraBuffer, subtractiveLightingKeyword, subtractiveLighting);


        //剔除额外的光 和 主光源
        if (mainLightExists || cull.visibleLights.Count > maxVisibleLights)
        {
            int[] lightIndices = cull.GetLightIndexMap();

            if (mainLightExists)
            {
                lightIndices[0] = -1;
            }

            for (int i = maxVisibleLights; i < cull.visibleLights.Count; i++)
            {
                lightIndices[i] = -1;
            }

            cull.SetLightIndexMap(lightIndices);
        }
    }
Ejemplo n.º 23
0
    /// <summary>
    /// 初始化光照相关信息
    /// </summary>
    void ConfigureLights()
    {
        mainLightExists = false;
        bool shadowmaskExists    = false;
        bool subtractiveLighting = false;

        shadowTileCount = 0;
        for (int i = 0; i < cull.visibleLights.Count; i++)
        {
            if (i == maxVisiableLights)   //最多光源数量,超过的忽略不再处理
            {
                break;
            }

            var light = cull.visibleLights[i];
            visiableLightColors[i] = light.finalColor;
            Vector4 attenuation = Vector4.zero;
            attenuation.w = 1f;  //不影响其他光源类型
            Vector4 shadow = Vector4.zero;

            LightBakingOutput baking = light.light.bakingOutput;
            visibleLightOcclusionMasks[i] = occlusionMasks[baking.occlusionMaskChannel + 1];
            if (baking.lightmapBakeType == LightmapBakeType.Mixed)
            {
                shadowmaskExists |= baking.mixedLightingMode == MixedLightingMode.Shadowmask;
                //subtractiveLighting |= baking.mixedLightingMode == MixedLightingMode.Subtractive;
                if (baking.mixedLightingMode == MixedLightingMode.Subtractive)
                {
                    subtractiveLighting = true;
                    cameraBuffer.SetGlobalColor(subtractiveShadowColorId,
                                                RenderSettings.subtractiveShadowColor.linear);
                }
            }

            if (light.lightType == LightType.Directional)
            {
                Vector4 v = light.localToWorld.GetColumn(2);
                v.x = -v.x;
                v.y = -v.y;
                v.z = -v.z;
                visiableLightDirectionsOrPositions[i] = v;
                shadow   = ConfigureShadows(i, light.light);
                shadow.z = 1f;
                if (i == 0 && shadow.x > 0f && shadowCascades > 0)
                {
                    mainLightExists  = true;
                    shadowTileCount -= 1;
                }
            }
            else
            {
                //光源的位置
                visiableLightDirectionsOrPositions[i] = light.localToWorld.GetColumn(3);
                attenuation.x = 1f / Mathf.Max(light.range * light.range, 0.00001f);

                if (light.lightType == LightType.Spot)
                {
                    Vector4 v = light.localToWorld.GetColumn(2);
                    v.x = -v.x;
                    v.y = -v.y;
                    v.z = -v.z;
                    visiableLightSpotDirections[i] = v;

                    float outerRad   = Mathf.Deg2Rad * 0.5f * light.spotAngle;
                    float outerCos   = Mathf.Cos(outerRad);
                    float outerTan   = Mathf.Tan(outerRad);
                    float innerCos   = Mathf.Cos(Mathf.Atan((46f / 64f) * outerTan));
                    float angleRange = Mathf.Max(innerCos - outerCos, 0.0001f);
                    attenuation.z = 1f / angleRange;
                    attenuation.w = -outerCos * attenuation.z;

                    shadow = ConfigureShadows(i, light.light);
                }
                else
                {
                    //Point Light
                    visiableLightSpotDirections[i] = Vector4.one;
                }
            }
            visiableLightAttenuations[i] = attenuation;
            shadowData[i] = shadow;
        }

        bool useDistanceShadowmaks = QualitySettings.shadowmaskMode == ShadowmaskMode.DistanceShadowmask;

        CoreUtils.SetKeyword(cameraBuffer, shadowmaskKeyword, shadowmaskExists && !useDistanceShadowmaks);
        CoreUtils.SetKeyword(cameraBuffer, distanceShadowMaskKeyword, shadowmaskExists && useDistanceShadowmaks);
        CoreUtils.SetKeyword(cameraBuffer, subtractiveLightingKeyword, subtractiveLighting);

        //超过最大光源个数限制时,设置为-1的灯(不存在的灯)
        if (mainLightExists || cull.visibleLights.Count > maxVisiableLights)
        {
            int[] lightIndices = cull.GetLightIndexMap();
            if (mainLightExists)
            {
                lightIndices[0] = -1;
            }
            for (int i = maxVisiableLights; i < cull.visibleLights.Count; i++)
            {
                lightIndices[i] = -1;
            }
            cull.SetLightIndexMap(lightIndices);
        }
    }
Ejemplo n.º 24
0
    void ConfigureLights()
    {
        mainLightExists = false;
        bool shadowmaskExists    = false;
        bool subtractiveLighting = false;

        shadowTileCount = 0;

        for (int i = 0; i < cull.visibleLights.Count; i++)
        {
            if (i == maxVisibleLights)
            {
                break;
            }
            VisibleLight light = cull.visibleLights[i];
            visibleLightColors[i] = light.finalColor;

            Vector4 attenuation = Vector4.zero;
            attenuation.w = 1f;   //if no spot light, factor =1

            Vector4 shadow = Vector4.zero;

            //shadowmask settings
            LightBakingOutput baking = light.light.bakingOutput;
            visibleLightOcclusionMasks[i] =
                occlusionMasks[baking.occlusionMaskChannel + 1];
            if (baking.lightmapBakeType == LightmapBakeType.Mixed)
            {
                shadowmaskExists |=
                    baking.mixedLightingMode == MixedLightingMode.Shadowmask;

                if (baking.mixedLightingMode == MixedLightingMode.Subtractive)
                {
                    subtractiveLighting = true;
                    cameraBuffer.SetGlobalColor(
                        subtractiveShadowColorId,
                        RenderSettings.subtractiveShadowColor.linear
                        );
                }
            }


            //light settings
            if (light.lightType == LightType.Directional)
            {
                Vector4 v = light.localToWorld.GetColumn(2);
                v.x = -v.x;
                v.y = -v.y;
                v.z = -v.z;  //change to vector surfaceToLight
                visibleLightDirectionsOrPositions[i] = v;

                shadow   = ConfigureShadows(i, light.light);
                shadow.z = 1f;

                //directional light index =0, cast shadow, use cascades
                if (i == 0 && shadow.x > 0f && shadowCascades > 0)
                {
                    mainLightExists  = true;
                    shadowTileCount -= 1;   //cascaded shadow map is not included in tiled shadow map
                }
            }
            else
            {
                visibleLightDirectionsOrPositions[i] = light.localToWorld.GetColumn(3);
                attenuation.x = 1f /
                                Mathf.Max(light.range * light.range, 0.00001f);

                if (light.lightType == LightType.Spot)
                {
                    Vector4 v = light.localToWorld.GetColumn(2);
                    v.x = -v.x;
                    v.y = -v.y;
                    v.z = -v.z;
                    visibleLightSpotDirections[i] = v;

                    float outerRad = Mathf.Deg2Rad * 0.5f * light.spotAngle;
                    float outerCos = Mathf.Cos(outerRad);
                    float outerTan = Mathf.Tan(outerRad);
                    float innerCos =
                        Mathf.Cos(Mathf.Atan(((46f / 64f) * outerTan)));
                    float angleRange = Mathf.Max(innerCos - outerCos, 0.001f);
                    attenuation.z = 1f / angleRange;
                    attenuation.w = -outerCos * attenuation.z;

                    //buffer shadowData
                    shadow = ConfigureShadows(i, light.light);
                }
                else
                {
                    //indicator of pointlight
                    visibleLightSpotDirections[i] = Vector4.one;
                }
            }

            visibleLightAttenuations[i] = attenuation;
            shadowData[i] = shadow;
        }

        //number of lights exceeds upper limit
        if (mainLightExists || cull.visibleLights.Count > maxVisibleLights)
        {
            int[] lightIndices = cull.GetLightIndexMap();
            if (mainLightExists)
            {
                //remove main light from diffuseLight render, avoid a second render
                lightIndices[0] = -1;
            }
            for (int i = maxVisibleLights; i < cull.visibleLights.Count; i++)
            {
                lightIndices[i] = -1;
            }
            cull.SetLightIndexMap(lightIndices);
        }

        bool useDistanceShadowmask =
            QualitySettings.shadowmaskMode == ShadowmaskMode.DistanceShadowmask;

        //enable shadowmask keyword
        CoreUtils.SetKeyword(cameraBuffer, shadowmaskKeyword,
                             shadowmaskExists && !useDistanceShadowmask); //if use shadowmask mode
        CoreUtils.SetKeyword(cameraBuffer, distanceShadowmaskKeyword,
                             shadowmaskExists && useDistanceShadowmask);  //if use distance shadowmask
        CoreUtils.SetKeyword(cameraBuffer, subtractiveLightingKeyword,
                             subtractiveLighting);
    }
Ejemplo n.º 25
0
        /// <summary>
        /// Read the data into the specified value.
        /// </summary>
        /// <param name="value">Value.</param>
        /// <param name="reader">Reader.</param>
        public override void ReadInto(object value, ISaveGameReader reader)
        {
            UnityEngine.Light light = (UnityEngine.Light)value;
            foreach (string property in reader.Properties)
            {
                switch (property)
                {
                case "type":
                    light.type = reader.ReadProperty <UnityEngine.LightType> ();
                    break;

                case "color":
                    light.color = reader.ReadProperty <UnityEngine.Color> ();
                    break;

                case "colorTemperature":
                    light.colorTemperature = reader.ReadProperty <System.Single> ();
                    break;

                case "intensity":
                    light.intensity = reader.ReadProperty <System.Single> ();
                    break;

                case "bounceIntensity":
                    light.bounceIntensity = reader.ReadProperty <System.Single> ();
                    break;

                case "shadows":
                    light.shadows = reader.ReadProperty <UnityEngine.LightShadows> ();
                    break;

                case "shadowStrength":
                    light.shadowStrength = reader.ReadProperty <System.Single> ();
                    break;

                case "shadowResolution":
                    light.shadowResolution = reader.ReadProperty <UnityEngine.Rendering.LightShadowResolution> ();
                    break;

                case "shadowCustomResolution":
                    light.shadowCustomResolution = reader.ReadProperty <System.Int32> ();
                    break;

                case "shadowBias":
                    light.shadowBias = reader.ReadProperty <System.Single> ();
                    break;

                case "shadowNormalBias":
                    light.shadowNormalBias = reader.ReadProperty <System.Single> ();
                    break;

                case "shadowNearPlane":
                    light.shadowNearPlane = reader.ReadProperty <System.Single> ();
                    break;

                case "range":
                    light.range = reader.ReadProperty <System.Single> ();
                    break;

                case "spotAngle":
                    light.spotAngle = reader.ReadProperty <System.Single> ();
                    break;

                case "cookieSize":
                    light.cookieSize = reader.ReadProperty <System.Single> ();
                    break;

                case "cookie":
                    if (light.cookie == null)
                    {
                        light.cookie = reader.ReadProperty <UnityEngine.Texture> ();
                    }
                    else
                    {
                        reader.ReadIntoProperty <UnityEngine.Texture> (light.cookie);
                    }
                    break;

                case "flare":
                    if (light.flare == null)
                    {
                        light.flare = reader.ReadProperty <UnityEngine.Flare> ();
                    }
                    else
                    {
                        reader.ReadIntoProperty <UnityEngine.Flare> (light.flare);
                    }
                    break;

                case "renderMode":
                    light.renderMode = reader.ReadProperty <UnityEngine.LightRenderMode> ();
                    break;

                case "alreadyLightmapped":
                                                #if UNITY_2017_3_OR_NEWER
                    LightBakingOutput bakingOutput = light.bakingOutput;
                    bakingOutput.isBaked = reader.ReadProperty <System.Boolean> ();
                    light.bakingOutput   = bakingOutput;
                                                #else
                    light.alreadyLightmapped = reader.ReadProperty <System.Boolean> ();
                                                #endif
                    break;

                case "cullingMask":
                    light.cullingMask = reader.ReadProperty <System.Int32> ();
                    break;

                case "enabled":
                    light.enabled = reader.ReadProperty <System.Boolean> ();
                    break;

                case "tag":
                    light.tag = reader.ReadProperty <System.String> ();
                    break;

                case "name":
                    light.name = reader.ReadProperty <System.String> ();
                    break;

                case "hideFlags":
                    light.hideFlags = reader.ReadProperty <UnityEngine.HideFlags> ();
                    break;
                }
            }
        }