예제 #1
0
        //float _maxTimePerFrameForCoroutine;
        public IEnumerator CombineTexturesIntoAtlasesCoroutine(ProgressUpdateDelegate progressInfo,
                                                               AtlasesAndRects resultAtlasesAndRects,
                                                               Material resultMaterial,
                                                               List <GameObject> objsToMesh,
                                                               List <Material> allowedMaterialsFilter,
                                                               EditorMethodsInterface textureEditorMethods = null,
                                                               CombineTexturesIntoAtlasesCoroutineResult coroutineResult = null,
                                                               float maxTimePerFrame = .01f,
                                                               List <AtlasPackingResult> packingResults = null,
                                                               bool onlyPackRects = false,
                                                               bool splitAtlasWhenPackingIfTooBig = false)
        {
            coroutineResult.success    = true;
            coroutineResult.isFinished = false;
            if (maxTimePerFrame <= 0f)
            {
                Debug.LogError("maxTimePerFrame must be a value greater than zero");
                coroutineResult.isFinished = true;
                yield break;
            }
            //_maxTimePerFrameForCoroutine = maxTimePerFrame;
            yield return(_CombineTexturesIntoAtlases(progressInfo,
                                                     coroutineResult,
                                                     resultAtlasesAndRects,
                                                     resultMaterial,
                                                     objsToMesh,
                                                     allowedMaterialsFilter,
                                                     textureEditorMethods,
                                                     packingResults,
                                                     onlyPackRects,
                                                     splitAtlasWhenPackingIfTooBig));

            coroutineResult.isFinished = true;
            yield break;
        }
예제 #2
0
        /// <summary>
        /// 合并贴图形成纹理图集
        /// </summary>
        public bool CombineTexturesIntoAtlases(ProgressUpdateDelegate progressInfo,
                                               AtlasesAndRects resultAtlasesAndRects,
                                               Material resultMaterial,
                                               List <GameObject> objsToMesh,
                                               List <Material> allowedMaterialsFilter,
                                               EditorMethodsInterface textureEditorMethods = null,
                                               List <AtlasPackingResult> packingResults    = null,
                                               bool onlyPackRects = false,
                                               bool splitAtlasWhenPackingIfTooBig = false)
        {
            CombineTexturesIntoAtlasesCoroutineResult result = new CombineTexturesIntoAtlasesCoroutineResult();

            RunCorutineWithoutPause(
                _CombineTexturesIntoAtlases(
                    progressInfo,
                    result,
                    resultAtlasesAndRects,
                    resultMaterial,
                    objsToMesh,
                    allowedMaterialsFilter,
                    textureEditorMethods,
                    packingResults,
                    onlyPackRects,
                    splitAtlasWhenPackingIfTooBig
                    ),
                0);
            if (result.success == false)
            {
                Debug.LogError("Failed to generate atlases.");
            }
            return(result.success);
        }
예제 #3
0
        // texPropertyNames 是 resultMaterial中纹理属性的列表
        // allowedMaterialsFilter 是材料列表。 没有这些材料的物体将被忽略。这由多种材质过滤器使用
        // textureEditorMethods 仅封装编辑器功能,例如保存资产和跟踪纹理资产谁的格式已更改。 如果在运行时使用,则为null。
        IEnumerator __CombineTexturesIntoAtlases(ProgressUpdateDelegate progressInfo,
                                                 CombineTexturesIntoAtlasesCoroutineResult result,
                                                 AtlasesAndRects resultAtlasesAndRects,
                                                 TexturePipelineData data,
                                                 bool splitAtlasWhenPackingIfTooBig,
                                                 EditorMethodsInterface textureEditorMethods)
        {
            if (progressInfo != null)
            {
                progressInfo("Collecting textures ", .01f);
            }

            // --- 1、记录各合并物体的源材质的 Prop Texture 信息写入 Data.distinctMaterialTextures
            //每个图集(主图,凹凸等)都将有的 MaterialTextures.Count 个图像。
            //每个 distinctMaterialTextures 对应一个游戏物体的某个材质,记录一组纹理,分别材质的在每个Prop图集一个。
            List <GameObject> usedObjsToMesh = new List <GameObject>();

            yield return(TextureCombinerPipeline.__Step1_CollectDistinctMatTexturesAndUsedObjects(progressInfo, result, data, textureEditorMethods, usedObjsToMesh));

            if (!result.success)
            {
                yield break;
            }

            // --- 2、计算使每个材质属性中的多个材质的合理尺寸
            yield return(TextureCombinerPipeline._Step2_CalculateIdealSizesForTexturesInAtlasAndPadding(progressInfo, result, data, textureEditorMethods));

            if (!result.success)
            {
                yield break;
            }

            // --- 3、创建特定打包方式的打包器
            ITextureCombinerPacker texturePaker = TextureCombinerPipeline.CreatePacker(data.IsOnlyOneTextureInAtlasReuseTextures(), data._packingAlgorithm);

            yield return(texturePaker.ConvertTexturesToReadableFormats(progressInfo, result, data, this, textureEditorMethods));

            if (!result.success)
            {
                yield break;
            }

            // --- 4、计算各源材质在合并材质 Atlas 的排布
            AtlasPackingResult[] uvRects = texturePaker.CalculateAtlasRectangles(data, splitAtlasWhenPackingIfTooBig);

            // --- 5、创建 Atlas 并保存
            yield return(TextureCombinerPipeline.__Step3_BuildAndSaveAtlasesAndStoreResults(progressInfo,
                                                                                            result,
                                                                                            data,
                                                                                            this,
                                                                                            texturePaker,
                                                                                            uvRects[0],
                                                                                            textureEditorMethods,
                                                                                            resultAtlasesAndRects));
        }
예제 #4
0
        /// <summary>
        /// Creates the atlases.创建图集
        /// saveAtlasesAsAssets 创建图集并保存至项目资源目录,或者内存中
        /// editorMethods 贴图格式编辑器方法
        /// </summary>
        public AtlasesAndRects[] CreateAtlases(ProgressUpdateDelegate progressInfo,
                                               bool saveAtlasesAsAssets             = false,
                                               EditorMethodsInterface editorMethods = null)
        {
            AtlasesAndRects[] resultAtlasesAndRects = null;
            try
            {
                _coroutineResult = new CreateAtlasesCoroutineResult();

                TextureCombineHandler.RunCorutineWithoutPause(
                    CreateAtlasesCoroutine(progressInfo, _coroutineResult, saveAtlasesAsAssets, editorMethods, 1000f), 0);
                if (_coroutineResult.success && textureBakeResults != null)
                {
                    resultAtlasesAndRects = this.OnCombinedTexturesCoroutineAtlasesAndRects;
                }
            }
            catch (Exception e)
            {
                Debug.LogError(e);
            }
            finally
            {
                if (saveAtlasesAsAssets)
                { //Atlases were saved to project so we don't need these ones
                    if (resultAtlasesAndRects != null)
                    {
                        for (int j = 0; j < resultAtlasesAndRects.Length; j++)
                        {
                            AtlasesAndRects mAndA = resultAtlasesAndRects[j];
                            if (mAndA != null && mAndA.atlases != null)
                            {
                                for (int i = 0; i < mAndA.atlases.Length; i++)
                                {
                                    if (mAndA.atlases[i] != null)
                                    {
                                        if (editorMethods != null)
                                        {
                                            editorMethods.Destroy(mAndA.atlases[i]);
                                        }
                                        else
                                        {
                                            MeshBakerUtility.Destroy(mAndA.atlases[i]);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return(resultAtlasesAndRects);
        }
예제 #5
0
        void unpackMat2RectMap(TextureBakeResults tbr)
        {
            List <Material>          ms  = new List <Material>();
            List <MaterialAndUVRect> mss = new List <MaterialAndUVRect>();
            List <Rect> rs = new List <Rect>();

            for (int i = 0; i < OnCombinedTexturesCoroutineAtlasesAndRects.Length; i++)
            {
                AtlasesAndRects          newMesh = OnCombinedTexturesCoroutineAtlasesAndRects[i];
                List <MaterialAndUVRect> map     = newMesh.originMatToRect_map;
                if (map != null)
                {
                    for (int j = 0; j < map.Count; j++)
                    {
                        mss.Add(map[j]);
                        ms.Add(map[j].material);
                        rs.Add(map[j].atlasRect);
                    }
                }
            }
            //tbr.version = MB2_TextureBakeResults.VERSION;
            tbr.materialsAndUVRects = mss.ToArray();
        }
예제 #6
0
        IEnumerator _CombineTexturesIntoAtlases(ProgressUpdateDelegate progressInfo,
                                                CombineTexturesIntoAtlasesCoroutineResult result,
                                                AtlasesAndRects resultAtlasesAndRects,
                                                Material resultMaterial,
                                                List <GameObject> objsToMesh,
                                                List <Material> allowedMaterialsFilter,
                                                EditorMethodsInterface textureEditorMethods,
                                                List <AtlasPackingResult> atlasPackingResult,
                                                bool onlyPackRects,
                                                bool splitAtlasWhenPackingIfTooBig)
        {
            try
            {
                _temporaryTextures.Clear();
                MaterialPropTexture.readyToBuildAtlases = false;

                // ---- 0.合并材质前回调
                if (textureEditorMethods != null)
                {
                    textureEditorMethods.Clear();
                    textureEditorMethods.OnPreTextureBake();
                }

                // ---- 1.合并材质参数校验
                if (objsToMesh == null || objsToMesh.Count == 0)
                {
                    Debug.LogError("没有游戏物体参与合并");
                    result.success = false;
                    yield break;
                }

                if (_atlasPadding < 0)
                {
                    Debug.LogError("Atlas padding 必须大于等于零");
                    result.success = false;
                    yield break;
                }

                if (_maxTilingBakeSize < 2 || _maxTilingBakeSize > 4096)
                {
                    Debug.LogError("无效Tilling尺寸的值Invalid value for max tiling bake size.");
                    result.success = false;
                    yield break;
                }

                for (int i = 0; i < objsToMesh.Count; i++)
                {
                    Material[] ms = MeshBakerUtility.GetGOMaterials(objsToMesh[i]);
                    for (int j = 0; j < ms.Length; j++)
                    {
                        Material m = ms[j];
                        if (m == null)
                        {
                            Debug.LogError("游戏物体" + objsToMesh[i] + " 材质为空 ");
                            result.success = false;
                            yield break;
                        }
                    }
                }

                if (_fixOutOfBoundsUVs && (_packingAlgorithm == PackingAlgorithmEnum.MeshBakerTexturePacker_Horizontal ||
                                           _packingAlgorithm == PackingAlgorithmEnum.MeshBakerTexturePacker_Vertical))
                {
                    Debug.LogWarning("合并算法为 MeshBakerTexturePacker_Horizontal 或 MeshBakerTexturePacker_Vertical,建议不打开 Consider Mesh UVs 选项");
                }

                if (progressInfo != null)
                {
                    progressInfo("Collecting textures for " + objsToMesh.Count + " meshes.", .01f);
                }

                // ---- 2.创建材质合并管线数据
                TexturePipelineData data = CreatePipelineData(resultMaterial,
                                                              new List <ShaderTextureProperty>(),
                                                              objsToMesh,
                                                              allowedMaterialsFilter,
                                                              new List <MaterialPropTexturesSet>());

                // ---- 3.将材质的 shader 各参数信息写入管线数据中
                if (!TextureCombinerPipeline._CollectPropertyNames(data))
                {
                    result.success = false;
                    yield break;
                }

                // ---- 4.加载 Texture 混合器
                data.nonTexturePropertyBlender.LoadTextureBlendersIfNeeded(data.resultMaterial);

                // ---- 5.选择本地合并,或运行时合并
                if (onlyPackRects)
                {
                    yield return(__RunTexturePackerOnly(result, data, splitAtlasWhenPackingIfTooBig, textureEditorMethods, atlasPackingResult));
                }
                else
                {
                    yield return(__CombineTexturesIntoAtlases(progressInfo, result, resultAtlasesAndRects, data, splitAtlasWhenPackingIfTooBig, textureEditorMethods));
                }
            }
            finally
            {
                // ---- 6.删除缓存,合并材质完成回调
                _destroyAllTemporaryTextures();
                if (textureEditorMethods != null)
                {
                    textureEditorMethods.RestoreReadFlagsAndFormats(progressInfo);
                    textureEditorMethods.OnPostTextureBake();
                }
            }
        }
        /// <summary>
        ///  Texture 合并管线第 3 步,创建 Atlas 并保存资源
        /// </summary>
        /// <returns></returns>
        internal static IEnumerator __Step3_BuildAndSaveAtlasesAndStoreResults(ProgressUpdateDelegate progressInfo,
                                                                               CombineTexturesIntoAtlasesCoroutineResult result,
                                                                               TexturePipelineData data,
                                                                               TextureCombineHandler combiner,
                                                                               ITextureCombinerPacker packer,
                                                                               AtlasPackingResult atlasPackingResult,
                                                                               EditorMethodsInterface textureEditorMethods,
                                                                               AtlasesAndRects resultAtlasesAndRects)
        {
            //run the garbage collector to free up as much memory as possible before bake to reduce MissingReferenceException problems
            GC.Collect();
            Texture2D[] atlases = new Texture2D[data.numAtlases];
            //StringBuilder report = GenerateReport(data);

            //创建图集
            yield return(packer.CreateAtlases(progressInfo, data, combiner, atlasPackingResult, atlases, textureEditorMethods));

            data.nonTexturePropertyBlender.AdjustNonTextureProperties(data.resultMaterial, data.texPropertyNames, data.distinctMaterialTextures, textureEditorMethods);

            if (data.distinctMaterialTextures.Count > 0)
            {
                data.distinctMaterialTextures[0].AdjustResultMaterialNonTextureProperties(data.resultMaterial, data.texPropertyNames);
            }

            //结果报告
            //if (progressInfo != null)
            //    progressInfo("Building Report", .7f);
            ////report on atlases created
            //StringBuilder atlasMessage = new StringBuilder();
            //atlasMessage.AppendLine("---- Atlases ------");
            //for (int i = 0; i < data.numAtlases; i++)
            //{
            //    if (atlases[i] != null)
            //    {
            //        atlasMessage.AppendLine("Created Atlas For: " + data.texPropertyNames[i].name + " h=" + atlases[i].height + " w=" + atlases[i].width);
            //    }
            //    else if (!_ShouldWeCreateAtlasForThisProperty(i, data._considerNonTextureProperties, data.allTexturesAreNullAndSameColor))
            //    {
            //        atlasMessage.AppendLine("Did not create atlas for " + data.texPropertyNames[i].name + " because all source textures were null.");
            //    }
            //}
            //report.Append(atlasMessage.ToString());

            List <MaterialAndUVRect> mat2rect_map = new List <MaterialAndUVRect>();

            for (int i = 0; i < data.distinctMaterialTextures.Count; i++)
            {
                MaterialPropTexturesSet        texSet = data.distinctMaterialTextures[i];
                List <MatAndTransformToMerged> mats   = texSet.matsAndGOs.mats;
                Rect allPropsUseSameTiling_encapsulatingSamplingRect;
                Rect propsUseDifferntTiling_obUVRect;
                texSet.GetRectsForTextureBakeResults(out allPropsUseSameTiling_encapsulatingSamplingRect, out propsUseDifferntTiling_obUVRect);
                for (int j = 0; j < mats.Count; j++)
                {
                    Rect allPropsUseSameTiling_sourceMaterialTiling = texSet.GetMaterialTilingRectForTextureBakerResults(j);
                    MaterialAndUVRect key = new MaterialAndUVRect(
                        mats[j].mat,
                        atlasPackingResult.rects[i],
                        texSet.allTexturesUseSameMatTiling,
                        allPropsUseSameTiling_sourceMaterialTiling,
                        allPropsUseSameTiling_encapsulatingSamplingRect,
                        propsUseDifferntTiling_obUVRect,
                        texSet.tilingTreatment,
                        mats[j].objName);
                    if (!mat2rect_map.Contains(key))
                    {
                        mat2rect_map.Add(key);
                    }
                }
            }

            resultAtlasesAndRects.atlases             = atlases;                                               // one per texture on result shader
            resultAtlasesAndRects.texPropertyNames    = ShaderTextureProperty.GetNames(data.texPropertyNames); // one per texture on source shader
            resultAtlasesAndRects.originMatToRect_map = mat2rect_map;

            if (progressInfo != null)
            {
                progressInfo("Restoring Texture Formats & Read Flags", .8f);
            }
            combiner._destroyAllTemporaryTextures();
            if (textureEditorMethods != null)
            {
                textureEditorMethods.RestoreReadFlagsAndFormats(progressInfo);
            }

            //if (report != null)
            //    Debug.Log(report.ToString());

            yield break;
        }
예제 #8
0
        /// <summary>
        /// 创建贴图 Atlas 协程
        /// </summary>
        /// <returns></returns>
        public IEnumerator CreateAtlasesCoroutine(ProgressUpdateDelegate progressInfo,
                                                  CreateAtlasesCoroutineResult coroutineResult,
                                                  bool saveAtlasesAsAssets             = false,
                                                  EditorMethodsInterface editorMethods = null,
                                                  float maxTimePerFrame = .01f)
        {
            OnCombinedTexturesCoroutineAtlasesAndRects = null;

            //--- 1、合并前检测
            if (maxTimePerFrame <= 0f)
            {
                Debug.LogError("maxTimePerFrame must be a value greater than zero");
                coroutineResult.isFinished = true;
                yield break;
            }

            //验证等级
            ValidationLevel vl = Application.isPlaying ? ValidationLevel.quick : ValidationLevel.robust;

            //验证
            if (!DoCombinedValidate(this, ObjsToCombineTypes.dontCare, null, vl))
            {
                coroutineResult.isFinished = true;
                yield break;
            }

            //合并为多材质验证
            if (_doMultiMaterial && !_ValidateResultMaterials())
            {
                coroutineResult.isFinished = true;
                yield break;
            }
            else if (!_doMultiMaterial)
            {
                //合并为单独材质
                if (_resultMaterial == null)
                {
                    Debug.LogError("Combined Material is null please create and assign a result material.");
                    coroutineResult.isFinished = true;
                    yield break;
                }
                Shader targShader = _resultMaterial.shader;
                for (int i = 0; i < objsToMesh.Count; i++)
                {
                    Material[] ms = MeshBakerUtility.GetGOMaterials(objsToMesh[i]);
                    for (int j = 0; j < ms.Length; j++)
                    {
                        Material m = ms[j];
                        if (m != null && m.shader != targShader)
                        {
                            Debug.LogWarning("游戏物体" + objsToMesh[i] + " 没有使用 shader " + targShader +
                                             " it may not have the required textures. " +
                                             "If not small solid color textures will be generated.");
                        }
                    }
                }
            }

            TextureCombineHandler combiner = CreateAndConfigureTextureCombiner();

            combiner.saveAtlasesAsAssets = saveAtlasesAsAssets;

            ////--- 2、初始化存储合并结果的数据结构
            int numResults = 1;

            if (_doMultiMaterial)
            {
                numResults = resultMaterials.Length;
            }

            OnCombinedTexturesCoroutineAtlasesAndRects = new AtlasesAndRects[numResults];
            for (int i = 0; i < OnCombinedTexturesCoroutineAtlasesAndRects.Length; i++)
            {
                OnCombinedTexturesCoroutineAtlasesAndRects[i] = new AtlasesAndRects();
            }

            //--- 3、开始合并材质(单个,多个)
            for (int i = 0; i < OnCombinedTexturesCoroutineAtlasesAndRects.Length; i++)
            {
                Material        resMatToPass;
                List <Material> sourceMats;
                if (_doMultiMaterial)
                {
                    sourceMats   = resultMaterials[i].sourceMaterials;
                    resMatToPass = resultMaterials[i].combinedMaterial;
                    combiner.fixOutOfBoundsUVs = resultMaterials[i].considerMeshUVs;
                }
                else
                {
                    resMatToPass = _resultMaterial;
                    sourceMats   = null;
                }

                //TextureHandler 材质合并协程结果
                CombineTexturesIntoAtlasesCoroutineResult coroutineResult2 = new CombineTexturesIntoAtlasesCoroutineResult();
                yield return(combiner.CombineTexturesIntoAtlasesCoroutine(progressInfo,
                                                                          OnCombinedTexturesCoroutineAtlasesAndRects[i],
                                                                          resMatToPass,
                                                                          objsToMesh,
                                                                          sourceMats,
                                                                          editorMethods,
                                                                          coroutineResult2,
                                                                          maxTimePerFrame));

                coroutineResult.success = coroutineResult2.success;
                if (!coroutineResult.success)
                {
                    coroutineResult.isFinished = true;
                    yield break;
                }
            }

            //--- 4、TextureBakeResults 保存合并结果
            unpackMat2RectMap(textureBakeResults);
            textureBakeResults.doMultiMaterial = _doMultiMaterial;
            if (_doMultiMaterial)
            {
                textureBakeResults.resultMaterials = resultMaterials;
            }
            else
            {
                MultiMaterial[] resMats = new MultiMaterial[1];
                resMats[0] = new MultiMaterial();
                resMats[0].combinedMaterial = _resultMaterial;
                resMats[0].considerMeshUVs  = _fixOutOfBoundsUVs;
                resMats[0].sourceMaterials  = new List <Material>();
                for (int i = 0; i < textureBakeResults.materialsAndUVRects.Length; i++)
                {
                    resMats[0].sourceMaterials.Add(textureBakeResults.materialsAndUVRects[i].material);
                }
                textureBakeResults.resultMaterials = resMats;
            }

            //--- 5、传递合并结果到 MeshCombiner
            MeshBakerCommon[] mb = GetComponentsInChildren <MeshBakerCommon>();
            for (int i = 0; i < mb.Length; i++)
            {
                mb[i].textureBakeResults = textureBakeResults;
            }
            coroutineResult.isFinished = true;

            //--- 6、合并材质结束回调
            if (coroutineResult.success && onBuiltAtlasesSuccess != null)
            {
                onBuiltAtlasesSuccess();
            }
            if (!coroutineResult.success && onBuiltAtlasesFail != null)
            {
                onBuiltAtlasesFail();
            }
        }