예제 #1
0
    public static void UnloadScene(ftLightmapsStorage storage)
    {
        if (lightmapRefCount == null)
        {
            return;
        }
        if (storage.idremap == null)
        {
            return;
        }

        //int idx = loadedStorages.IndexOf(storage);
        //if (idx >= 0) loadedStorages.RemoveAt(idx);

        LightmapData[] existingLmaps = null;
        List <LightmapAdditionalData> existingLmapsAdditional = null;

        //bool rebuild = false;
        for (int i = 0; i < storage.idremap.Length; i++)
        {
            int currentID = storage.idremap[i];

            // just never unload the 1st lightmap to prevent Unity from losing LM encoding settings
            // remapping all IDs at runtime would introduce a perf hiccup
            if (currentID == 0)
            {
                continue;
            }

            if (lightmapRefCount.Count <= currentID)
            {
                continue;
            }
            lightmapRefCount[currentID]--;
            //Debug.LogError("rem: "+currentID+" "+lightmapRefCount[currentID]);
            if (lightmapRefCount[currentID] == 0)
            {
                if (existingLmaps == null)
                {
                    existingLmaps = LightmapSettings.lightmaps;
                }

                if (existingLmaps.Length > currentID)
                {
                    existingLmaps[currentID].lightmapColor = null;
                    existingLmaps[currentID].lightmapDir   = null;
                    existingLmaps[currentID].shadowMask    = null;

                    if (existingLmapsAdditional == null)
                    {
                        existingLmapsAdditional = globalMapsAdditional;
                    }
                    if (existingLmapsAdditional != null && existingLmapsAdditional.Count > currentID)
                    {
                        var emptyEntry = new LightmapAdditionalData();
                        existingLmapsAdditional[currentID] = emptyEntry;
                    }
                }
                //if (currentID == 0) rebuild = true;
            }
        }

        /*
         * // If the first lightmap was unloaded, we need to rebuild the lightmap array
         * // because Unity uses 1st lightmap to determine encoding
         * if (rebuild)
         * {
         *  int newLength = 0;
         *  for(int i=0; i<existingLmaps.Length; i++)
         *  {
         *      if (existingLmaps[i].lightmapColor != null) newLength++;
         *  }
         *  var existingLmaps2 = new LightmapData[newLength];
         *  int ctr = 0;
         *  for(int i=0; i<existingLmaps.Length; i++)
         *  {
         *      if (existingLmaps[i].lightmapColor != null)
         *      {
         *          existingLmaps2[ctr] = existingLmaps[i];
         *          ctr++;
         *      }
         *  }
         *  existingLmaps = existingLmaps2;
         *
         *  for(int i=0; i<)
         * }
         */

        if (existingLmaps != null)
        {
            LightmapSettings.lightmaps = existingLmaps;
        }
    }
예제 #2
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;
    }