/// <summary> /// Texture 合并管线第 3 步,创建 Atlas 并保存资源 /// </summary> /// <returns></returns> internal static void Step3_BuildAndSaveAtlasesAndStoreResults( TextureCombinePipelineData data, TextureCombineHandler combiner, ITextureCombineAtlasPacker 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); //创建图集 packer.CreateAtlases(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); } 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; combiner._destroyAllTemporaryTextures(); }
public void RunTestHarness() { if (packerType == PackerType.regular) { texturePacker = new MB2_TexturePackerRegular(); } else if (packerType == PackerType.horizontal) { MB2_TexturePackerHorizontalVert tp = new MB2_TexturePackerHorizontalVert(); tp.packingOrientation = MB2_TexturePackerHorizontalVert.TexturePackingOrientation.horizontal; texturePacker = tp; } else if (packerType == PackerType.vertical) { MB2_TexturePackerHorizontalVert tp = new MB2_TexturePackerHorizontalVert(); tp.packingOrientation = MB2_TexturePackerHorizontalVert.TexturePackingOrientation.vertical; texturePacker = tp; } texturePacker.atlasMustBePowerOfTwo = atlasMustBePowerOfTwo; texturePacker.LOG_LEVEL = logLevel; rs = texturePacker.GetRects(imgsToAdd, maxDim, padding, doMultiAtlas); if (rs != null) { Debug.Log("NumAtlas= " + rs.Length); for (int i = 0; i < rs.Length; i++) { Debug.Log("AtlasSize " + rs[i].atlasX + " mxY= " + rs[i].atlasY); for (int j = 0; j < rs[i].rects.Length; j++) { Rect r = rs[i].rects[j]; r.x *= rs[i].atlasX; r.y *= rs[i].atlasY; r.width *= rs[i].atlasX; r.height *= rs[i].atlasY; Debug.Log(r.ToString("f5")); } Vector2 offset = new Vector2((i * 1.5f) * maxDim, 0); AtlasPackingResult apr = rs[i]; Vector2 center = new Vector2(offset.x + apr.atlasX / 2, offset.y + apr.atlasY / 2); Vector2 sz = new Vector2(apr.atlasX, apr.atlasY); Debug.Log("==============="); } if (rs.Length > 0) { res = "mxX= " + rs[0].atlasX + " mxY= " + rs[0].atlasY; } } else { res = "ERROR: PACKING FAILED"; } }
private void OnDrawGizmos() { if (rs != null) { for (int i = 0; i < rs.Length; i++) { Vector2 offset = new Vector2((i * 1.5f) * maxDim, 0); AtlasPackingResult apr = rs[i]; Vector2 center = new Vector2(offset.x + apr.atlasX / 2, offset.y + apr.atlasY / 2); Vector2 sz = new Vector2(apr.atlasX, apr.atlasY); Gizmos.DrawWireCube(center, sz); for (int j = 0; j < rs[i].rects.Length; j++) { Rect r = rs[i].rects[j]; Gizmos.color = new Color(Random.value, Random.value, Random.value); center = new Vector2(offset.x + (r.x + r.width / 2f) * rs[i].atlasX, offset.y + (r.y + r.height / 2f) * rs[i].atlasY); Vector2 szz = new Vector2(r.width * rs[i].atlasX, r.height * rs[i].atlasY); Gizmos.DrawCube(center, szz); } } } }
public override void CreateAtlases( TextureCombinePipelineData data, TextureCombineHandler combiner, AtlasPackingResult packedAtlasRects, Texture2D[] atlases, EditorMethodsInterface textureEditorMethods) { Rect[] uvRects = packedAtlasRects.rects; int atlasSizeX = packedAtlasRects.atlasX; int atlasSizeY = packedAtlasRects.atlasY; Debug.Log("Generated atlas will be " + atlasSizeX + "x" + atlasSizeY); for (int propIdx = 0; propIdx < data.numAtlases; propIdx++) { Texture2D atlas = null; ShaderTextureProperty property = data.texPropertyNames[propIdx]; if (!TextureCombinePipeline.ShouldWeCreateAtlasForThisProperty(propIdx, data.considerNonTextureProperties, data.allTexturesAreNullAndSameColor)) { atlas = null; Debug.Log("=== Not creating atlas for " + property.name + " because textures are null and default value parameters are the same."); } else { Debug.Log("=== Creating atlas for " + property.name); GC.Collect(); CreateTemporaryTexturesForAtlas(data.distinctMaterialTextures, combiner, propIdx, data); //use a jagged array because it is much more efficient in memory Color[][] atlasPixels = new Color[atlasSizeY][]; for (int j = 0; j < atlasPixels.Length; j++) { atlasPixels[j] = new Color[atlasSizeX]; } bool isNormalMap = false; if (property.isNormalMap) { isNormalMap = true; } for (int texSetIdx = 0; texSetIdx < data.distinctMaterialTextures.Count; texSetIdx++) { MaterialPropTexturesSet texSet = data.distinctMaterialTextures[texSetIdx]; MaterialPropTexture matTex = texSet.ts[propIdx]; string s = "Creating Atlas '" + property.name + "' texture " + matTex.GetTexName(); Debug.Log(string.Format("Adding texture {0} to atlas {1} for texSet {2} srcMat {3}", matTex.GetTexName(), property.name, texSetIdx, texSet.matsAndGOs.mats[0].GetMaterialName())); Rect r = uvRects[texSetIdx]; Texture2D t = texSet.ts[propIdx].GetTexture2D(); int x = Mathf.RoundToInt(r.x * atlasSizeX); int y = Mathf.RoundToInt(r.y * atlasSizeY); int ww = Mathf.RoundToInt(r.width * atlasSizeX); int hh = Mathf.RoundToInt(r.height * atlasSizeY); if (ww == 0 || hh == 0) { Debug.LogError("Image in atlas has no height or width " + r); } if (textureEditorMethods != null) { textureEditorMethods.SetReadWriteFlag(t, true, true); } DRect samplingRect = texSet.ts[propIdx].GetEncapsulatingSamplingRect(); CopyScaledAndTiledToAtlas(texSet.ts[propIdx], texSet, property, samplingRect, x, y, ww, hh, packedAtlasRects.padding[texSetIdx], atlasPixels, isNormalMap, data, combiner); } atlas = new Texture2D(atlasSizeX, atlasSizeY, TextureFormat.ARGB32, true); for (int j = 0; j < atlasPixels.Length; j++) { atlas.SetPixels(0, j, atlasSizeX, 1, atlasPixels[j]); } atlas.Apply(); Debug.Log("Saving atlas " + property.name + " w=" + atlas.width + " h=" + atlas.height); } atlases[propIdx] = atlas; if (data.saveAtlasesAsAssets && textureEditorMethods != null) { textureEditorMethods.SaveAtlasToAssetDatabase(atlases[propIdx], data.texPropertyNames[propIdx], propIdx, data.ResultMaterial); } else { data.ResultMaterial.SetTexture(data.texPropertyNames[propIdx].name, atlases[propIdx]); } data.ResultMaterial.SetTextureOffset(data.texPropertyNames[propIdx].name, Vector2.zero); data.ResultMaterial.SetTextureScale(data.texPropertyNames[propIdx].name, Vector2.one); combiner._destroyTemporaryTextures(data.texPropertyNames[propIdx].name); } }
public abstract void CreateAtlases(TextureCombinePipelineData data, TextureCombineHandler combiner, AtlasPackingResult packedAtlasRects, Texture2D[] atlases, EditorMethodsInterface textureEditorMethods);