public override bool Equals(object obj)
        {
            if (!(obj is MaterialAndUVRect))
            {
                return(false);
            }
            MaterialAndUVRect b = (MaterialAndUVRect)obj;

            return(material == b.material &&
                   allPropsUseSameTiling_samplingEncapsulatinRect == b.allPropsUseSameTiling_samplingEncapsulatinRect &&
                   allPropsUseSameTiling_sourceMaterialTiling == b.allPropsUseSameTiling_sourceMaterialTiling &&
                   allPropsUseSameTiling == b.allPropsUseSameTiling &&
                   propsUseDifferntTiling_srcUVsamplingRect == b.propsUseDifferntTiling_srcUVsamplingRect);
        }
        /// <summary>
        /// A material can appear more than once in an atlas if using fixOutOfBoundsUVs.
        /// in this case you need to use the UV rect of the mesh to find the correct rectangle.
        /// If the all properties on the mat use the same tiling then
        /// encapsulatingRect can be larger and will include baked UV and material tiling
        /// If mat uses different tiling for different maps then encapsulatingRect is the uvs of
        /// source mesh used to bake atlas and sourceMaterialTilingOut is 0,0,1,1. This works because
        /// material tiling was baked into the atlas.
        /// 尝试获取源物体材质在合并材质中的映射信息
        /// 如果使用fixOutOfBoundsUVs,一个材质可以在图集中出现多次。在这种情况下,您需要使用网格的UV矩形来找到正确的矩形。
        /// 如果材质上的所有属性都使用相同的拼贴,则 encapsulatingRect 可以更大,并将包含烘焙的UV和材质平铺
        /// 如果mat 对不同映射使用不同的tiling,则 encapsulatingRect 是用于烘焙图集的 uvs 且 sourceMaterialTilingOut 为0,0,1,1。
        /// 材质 tiling 烘焙到 atlas 中。
        /// </summary>
        public bool TryGetMaterialToUVRectMap(Material sourceMat,
                                              Mesh sourceMesh,
                                              int submeshIdx,
                                              int idxInResultMats,
                                              MeshChannelsCache meshChannelCache,
                                              Dictionary <int, MeshAnalysisResult[]> meshAnalysisCache,
                                              out TextureTilingTreatment tilingTreatment,
                                              out Rect rectInAtlas,
                                              out Rect encapsulatingRectOut,
                                              out Rect sourceMaterialTilingOut,
                                              ref string errorMsg)
        {
            for (int i = 0; i < resultAsset.materialsAndUVRects.Length; i++)
            {
                resultAsset.materialsAndUVRects[i].allPropsUseSameTiling = true;
            }

            tilingTreatment = TextureTilingTreatment.unknown;
            if (resultAsset.materialsAndUVRects.Length == 0)
            {
                errorMsg                = "Texture Bake Result 资源中的 材质UVRect 映射信息为空,需重新合并";
                rectInAtlas             = new Rect();
                encapsulatingRectOut    = new Rect();
                sourceMaterialTilingOut = new Rect();
                return(false);
            }
            if (sourceMat == null)
            {
                rectInAtlas             = new Rect();
                encapsulatingRectOut    = new Rect();
                sourceMaterialTilingOut = new Rect();
                errorMsg = string.Format("网格 {0} 的子网格 {1} 缺少材质,无法获取映射关系", sourceMesh.name, submeshIdx);
                return(false);
            }
            if (submeshIdx >= sourceMesh.subMeshCount)
            {
                errorMsg                = "参数错误 :Submesh index 大于子网格数量";
                rectInAtlas             = new Rect();
                encapsulatingRectOut    = new Rect();
                sourceMaterialTilingOut = new Rect();
                return(false);
            }

            //源材质在 matsAndSrcUVRect 的 ID
            int idx = -1;

            for (int i = 0; i < matsAndSrcUVRect.Length; i++)
            {
                if (sourceMat == matsAndSrcUVRect[i].material)
                {
                    idx = i;
                    break;
                }
            }
            if (idx == -1)
            {
                rectInAtlas             = new Rect();
                encapsulatingRectOut    = new Rect();
                sourceMaterialTilingOut = new Rect();
                errorMsg = string.Format("Material {0} 在 Texture Bake Result 中无法找到", sourceMat.name);
                return(false);
            }

            //不处理网格 UVs
            if (!resultAsset.resultMaterials[idxInResultMats].considerMeshUVs)
            {
                if (numTimesMatAppearsInAtlas[idx] != 1)
                {
                    Debug.LogError("TextureBakeResults 资源错误,FixOutOfBoundsUVs is false and a material appears more than once.");
                }
                MaterialAndUVRect mr = matsAndSrcUVRect[idx];
                rectInAtlas             = mr.atlasRect;
                tilingTreatment         = mr.tilingTreatment;
                encapsulatingRectOut    = mr.GetEncapsulatingRect();
                sourceMaterialTilingOut = mr.GetMaterialTilingRect();
                return(true);
            }
            else
            {
                //todo what if no UVs
                //Find UV rect in source mesh
                //源网格分析,并缓存
                MeshAnalysisResult[] meshAnalysisInfo;
                if (!meshAnalysisCache.TryGetValue(sourceMesh.GetInstanceID(), out meshAnalysisInfo))
                {
                    meshAnalysisInfo = new MeshAnalysisResult[sourceMesh.subMeshCount];
                    for (int j = 0; j < sourceMesh.subMeshCount; j++)
                    {
                        Vector2[] uvss = meshChannelCache.GetUv0Raw(sourceMesh);
                        MeshBakerUtility.hasOutOfBoundsUVs(uvss, sourceMesh, ref meshAnalysisInfo[j], j);
                    }
                    meshAnalysisCache.Add(sourceMesh.GetInstanceID(), meshAnalysisInfo);
                }

                //this could be a mesh that was not used in the texture baking that has huge UV tiling too big for the rect that was baked
                //find a record that has an atlas uvRect capable of containing this
                //这可能是未在纹理烘焙中使用的网格,该网格的UV贴图对于烘焙的rect而言太大
                //找到一条记录,该记录具有能够包含此图集的uvRect
                bool found                = false;
                Rect encapsulatingRect    = new Rect(0, 0, 0, 0);
                Rect sourceMaterialTiling = new Rect(0, 0, 0, 0);

                //Debug.Log(string.Format("尝试在图集中查找能够使用材质{1}保持网格{0}的平铺采样rect的矩形",
                //    m, sourceMat, meshAnalysisInfo[submeshIdx].uvRect.ToString("f5")));

                for (int i = idx; i < matsAndSrcUVRect.Length; i++)
                {
                    MaterialAndUVRect matAndUVrect = matsAndSrcUVRect[i];
                    if (matAndUVrect.material == sourceMat)
                    {
                        if (matAndUVrect.allPropsUseSameTiling)
                        {
                            encapsulatingRect    = matAndUVrect.allPropsUseSameTiling_samplingEncapsulatinRect;
                            sourceMaterialTiling = matAndUVrect.allPropsUseSameTiling_sourceMaterialTiling;
                        }
                        else
                        {
                            encapsulatingRect    = matAndUVrect.propsUseDifferntTiling_srcUVsamplingRect;
                            sourceMaterialTiling = new Rect(0, 0, 1, 1);
                        }

                        if (UVRectUtility.IsMeshAndMaterialRectEnclosedByAtlasRect(
                                matAndUVrect.tilingTreatment,
                                meshAnalysisInfo[submeshIdx].uvRect,
                                sourceMaterialTiling,
                                encapsulatingRect))
                        {
                            Debug.Log("在图集中找到" + "ID 为 " + i + "包含" + sourceMesh + "  的 tiled sampling 的 Rect");
                            idx   = i;
                            found = true;
                            break;
                        }
                    }
                }
                if (found)
                {
                    MaterialAndUVRect mr = matsAndSrcUVRect[idx];
                    rectInAtlas             = mr.atlasRect;
                    tilingTreatment         = mr.tilingTreatment;
                    encapsulatingRectOut    = mr.GetEncapsulatingRect();
                    sourceMaterialTilingOut = mr.GetMaterialTilingRect();
                    return(true);
                }
                else
                {
                    rectInAtlas             = new Rect();
                    encapsulatingRectOut    = new Rect();
                    sourceMaterialTilingOut = new Rect();
                    errorMsg = string.Format("Could not find a tiled rectangle in the atlas capable of containing the uv and material tiling on mesh {0} for material {1}. " +
                                             "Was this mesh included when atlases were baked?", sourceMesh.name, sourceMat);
                    return(false);
                }
            }
        }
        /// <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;
        }
Пример #4
0
        /// <summary>
        /// Creates for materials on renderer.
        /// 生成 TextureBakeResult,如果要合并的所有游戏物体都使用相同的材质,则可以使用该 TextureBakeResult。
        /// 将游戏物体的渲染器所使用的所有材质映射到 Atlas 中的矩形0,0..1,1 中。
        /// 用于创建临时 TextureCombineResult,Mesh 合并时,TextureCombineResult 为空时调用
        /// </summary>
        public static TextureBakeResults CreateForMaterialsOnRenderer(GameObject[] gos, List <Material> matsOnTargetRenderer)
        {
            HashSet <Material> fullMaterialList = new HashSet <Material>(matsOnTargetRenderer);

            for (int i = 0; i < gos.Length; i++)
            {
                if (gos[i] == null)
                {
                    Debug.LogError(string.Format("列表中第 {0} 个游戏物体为空", i));
                    return(null);
                }
                Material[] oMats = MeshBakerUtility.GetGOMaterials(gos[i]);
                if (oMats.Length == 0)
                {
                    Debug.LogError(string.Format("列表中第 {0} 个游戏物体没有 renderer 组件", i));
                    return(null);
                }
                for (int j = 0; j < oMats.Length; j++)
                {
                    if (!fullMaterialList.Contains(oMats[j]))
                    {
                        fullMaterialList.Add(oMats[j]);
                    }
                }
            }
            //所有游戏位图的源材质
            Material[] rms = new Material[fullMaterialList.Count];
            fullMaterialList.CopyTo(rms);

            TextureBakeResults       textureCombineResult = (TextureBakeResults)CreateInstance(typeof(TextureBakeResults));
            List <MaterialAndUVRect> sourceMatUVRects     = new List <MaterialAndUVRect>();

            for (int i = 0; i < rms.Length; i++)
            {
                if (rms[i] != null)
                {
                    MaterialAndUVRect matAndUVRect = new MaterialAndUVRect(rms[i],
                                                                           new Rect(0f, 0f, 1f, 1f),
                                                                           true,
                                                                           new Rect(0f, 0f, 1f, 1f),
                                                                           new Rect(0f, 0f, 1f, 1f),
                                                                           new Rect(0, 0, 0, 0),
                                                                           TextureTilingTreatment.none,
                                                                           "");
                    if (!sourceMatUVRects.Contains(matAndUVRect))
                    {
                        sourceMatUVRects.Add(matAndUVRect);
                    }
                }
            }

            textureCombineResult.resultMaterials = new MultiMaterial[sourceMatUVRects.Count];
            for (int i = 0; i < sourceMatUVRects.Count; i++)
            {
                textureCombineResult.resultMaterials[i] = new MultiMaterial();
                List <Material> sourceMats = new List <Material>();
                sourceMats.Add(sourceMatUVRects[i].material);
                textureCombineResult.resultMaterials[i].sourceMaterials  = sourceMats;
                textureCombineResult.resultMaterials[i].combinedMaterial = sourceMatUVRects[i].material;
                textureCombineResult.resultMaterials[i].considerMeshUVs  = false;
            }
            if (rms.Length == 1)
            {
                textureCombineResult.doMultiMaterial = false;
            }
            else
            {
                textureCombineResult.doMultiMaterial = true;
            }

            textureCombineResult.materialsAndUVRects = sourceMatUVRects.ToArray();
            return(textureCombineResult);
        }