/// <summary> /// 运行时图片打包 /// </summary> /// <param name="result"></param> /// <param name="data"></param> /// <param name="splitAtlasWhenPackingIfTooBig"></param> /// <param name="textureEditorMethods"></param> /// <param name="packingResult"></param> /// <returns></returns> IEnumerator __RunTexturePackerOnly(CombineTexturesIntoAtlasesCoroutineResult result, TexturePipelineData data, bool splitAtlasWhenPackingIfTooBig, EditorMethodsInterface textureEditorMethods, List <AtlasPackingResult> packingResult) { Debug.Log("__RunTexturePacker texture properties in shader:" + data.texPropertyNames.Count + " objsToMesh:" + data.allObjsToMesh.Count + " _fixOutOfBoundsUVs:" + data._fixOutOfBoundsUVs); List <GameObject> usedObjsToMesh = new List <GameObject>(); yield return(TextureCombinerPipeline.__Step1_CollectDistinctMatTexturesAndUsedObjects(null, result, data, textureEditorMethods, usedObjsToMesh)); if (!result.success) { yield break; } data.allTexturesAreNullAndSameColor = new TextureCombinerPipeline.CreateAtlasForProperty[data.texPropertyNames.Count]; yield return(TextureCombinerPipeline._Step2_CalculateIdealSizesForTexturesInAtlasAndPadding(null, result, data, textureEditorMethods)); if (!result.success) { yield break; } ITextureCombinerPacker texturePaker = TextureCombinerPipeline.CreatePacker(data.IsOnlyOneTextureInAtlasReuseTextures(), data._packingAlgorithm); // run the texture packer only AtlasPackingResult[] aprs = TextureCombinerPipeline.RunTexturePackerOnly(data, splitAtlasWhenPackingIfTooBig, texturePaker); for (int i = 0; i < aprs.Length; i++) { packingResult.Add(aprs[i]); } }
// 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)); }
internal static AtlasPackingResult[] RunTexturePackerOnly(TexturePipelineData data, bool doSplitIntoMultiAtlasIfTooBig, ITextureCombinerPacker texturePacker) { AtlasPackingResult[] apr = texturePacker.CalculateAtlasRectangles(data, doSplitIntoMultiAtlasIfTooBig); //copy materials PackingResults for (int i = 0; i < apr.Length; i++) { List <MatsAndGOs> matsList = new List <MatsAndGOs>(); apr[i].data = matsList; for (int j = 0; j < apr[i].srcImgIdxs.Length; j++) { MaterialPropTexturesSet ts = data.distinctMaterialTextures[apr[i].srcImgIdxs[j]]; matsList.Add(ts.matsAndGOs); } } return(apr); }
/// <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; }