internal static void CreateTemporaryTexturesForAtlas(List <MaterialPropTexturesSet> distinctMaterialTextures, TextureCombineHandler combiner, int propIdx, TexturePipelineData data) { for (int texSetIdx = 0; texSetIdx < data.distinctMaterialTextures.Count; texSetIdx++) { MaterialPropTexturesSet txs = data.distinctMaterialTextures[texSetIdx]; MaterialPropTexture matTex = txs.ts[propIdx]; if (matTex.isNull) { //create a small 16 x 16 texture to use in the atlas Color col = data.nonTexturePropertyBlender.GetColorForTemporaryTexture(txs.matsAndGOs.mats[0].mat, data.texPropertyNames[propIdx]); txs.CreateColoredTexToReplaceNull(data.texPropertyNames[propIdx].name, propIdx, data._fixOutOfBoundsUVs, combiner, col); } } }
public abstract IEnumerator CreateAtlases(ProgressUpdateDelegate progressInfo, TexturePipelineData data, TextureCombineHandler combiner, AtlasPackingResult packedAtlasRects, Texture2D[] atlases, EditorMethodsInterface textureEditorMethods);
/// <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; }
/// <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(); } }
public void CreateColoredTexToReplaceNull(string propName, int propIdx, bool considerMeshUVs, TextureCombineHandler combiner, Color col) { MaterialPropTexture matTex = ts[propIdx]; matTex.t = combiner._createTemporaryTexture(propName, 16, 16, TextureFormat.ARGB32, true); MeshBakerUtility.setSolidColor(matTex.GetTexture2D(), col); }
public IEnumerator CreateAtlases(ProgressUpdateDelegate progressInfo, TexturePipelineData data, TextureCombineHandler combiner, AtlasPackingResult packedAtlasRects, Texture2D[] atlases, EditorMethodsInterface textureEditorMethods) { Debug.Assert(!data.IsOnlyOneTextureInAtlasReuseTextures()); Rect[] uvRects = packedAtlasRects.rects; int atlasSizeX = packedAtlasRects.atlasX; int atlasSizeY = packedAtlasRects.atlasY; Debug.Log("Generated atlas will be " + atlasSizeX + "x" + atlasSizeY); //create a game object GameObject renderAtlasesGO = null; try { renderAtlasesGO = new GameObject("MBrenderAtlasesGO"); AtlasPackerRenderTexture atlasRenderTexture = renderAtlasesGO.AddComponent <AtlasPackerRenderTexture>(); renderAtlasesGO.AddComponent <Camera>(); if (data._considerNonTextureProperties) { Debug.LogWarning("Blend Non-Texture Properties has limited functionality when used with Mesh Baker Texture Packer Fast."); } for (int propIdx = 0; propIdx < data.numAtlases; propIdx++) { Texture2D atlas = null; if (!TextureCombinerPipeline._ShouldWeCreateAtlasForThisProperty(propIdx, data._considerNonTextureProperties, data.allTexturesAreNullAndSameColor)) { atlas = null; Debug.Log("Not creating atlas for " + data.texPropertyNames[propIdx].name + " because textures are null and default value parameters are the same."); } else { GC.Collect(); TextureCombinerPackerBase.CreateTemporaryTexturesForAtlas(data.distinctMaterialTextures, combiner, propIdx, data); if (progressInfo != null) { progressInfo("Creating Atlas '" + data.texPropertyNames[propIdx].name + "'", .01f); } // =========== // configure it Debug.Log("About to render " + data.texPropertyNames[propIdx].name + " isNormal=" + data.texPropertyNames[propIdx].isNormalMap); atlasRenderTexture.width = atlasSizeX; atlasRenderTexture.height = atlasSizeY; atlasRenderTexture.padding = data._atlasPadding; atlasRenderTexture.rects = uvRects; atlasRenderTexture.textureSets = data.distinctMaterialTextures; atlasRenderTexture.indexOfTexSetToRender = propIdx; atlasRenderTexture.texPropertyName = data.texPropertyNames[propIdx]; atlasRenderTexture.isNormalMap = data.texPropertyNames[propIdx].isNormalMap; atlasRenderTexture.fixOutOfBoundsUVs = data._fixOutOfBoundsUVs; atlasRenderTexture.considerNonTextureProperties = data._considerNonTextureProperties; atlasRenderTexture.resultMaterialTextureBlender = data.nonTexturePropertyBlender; // call render on it atlas = atlasRenderTexture.OnRenderAtlas(combiner); // destroy it // ============= Debug.Log("Saving atlas " + data.texPropertyNames[propIdx].name + " w=" + atlas.width + " h=" + atlas.height + " id=" + atlas.GetInstanceID()); } atlases[propIdx] = atlas; if (progressInfo != null) { progressInfo("Saving atlas: '" + data.texPropertyNames[propIdx].name + "'", .04f); } 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); // need to save atlases before doing this } } catch (Exception ex) { //Debug.LogError(ex); Debug.LogException(ex); } finally { if (renderAtlasesGO != null) { MeshBakerUtility.Destroy(renderAtlasesGO); } } yield break; }