//检查是否为所在树的贴图集 bool CheckInCurrLittleOctree(LODVolume lodVolume, TextureAtlasData rootData) { LODVolume[] parents = lodVolume.GetComponentsInParent <LODVolume>(); foreach (LODVolume p in parents) { if (p.gameObject == rootData.m_Root)//找到我是该大贴图的孩子 { return(true); } } return(false); }
/*导出单独一个TextureAtlas*/ public static void ExportOnlyOneTextureAtlasData(TextureAtlasData data, string atlasPath, string materialPath, string name) { string paths = AssetDatabase.GetAssetPath(data.m_Atlases); if (paths != "") { return; } data.m_Atlases.textureAtlas = SaveUniqueAtlasAsset <Texture2D>(data.m_Atlases.textureAtlas, atlasPath, name); if (data.m_Atlases.textureAtlas_N)//有法线贴图就保存 { data.m_Atlases.textureAtlas_N = SaveUniqueAtlasAsset <Texture2D>(data.m_Atlases.textureAtlas_N, atlasPath, name + "_N"); } data.m_Material.mainTexture = data.m_Atlases.textureAtlas; SaveMaterialsAsset(data.m_Material, materialPath, name); SaveUniqueAtlasAsset(data.m_Atlases, atlasPath, name); }
/*删除单独一个TextureAtlas*/ public static void DeleteOnlyOneTextureAtlasData(TextureAtlasData data) { string paths = AssetDatabase.GetAssetPath(data.m_Atlases.textureAtlas); if (paths != "") { AssetDatabase.DeleteAsset(paths); } paths = AssetDatabase.GetAssetPath(data.m_Atlases.textureAtlas_N); if (paths != "") { AssetDatabase.DeleteAsset(paths); } paths = AssetDatabase.GetAssetPath(data.m_Atlases); if (paths != "") { AssetDatabase.DeleteAsset(paths); } paths = AssetDatabase.GetAssetPath(data.m_Material); if (paths != "") { AssetDatabase.DeleteAsset(paths); } }
/*更新合批贴图、材质球*/ void UpdataCombineMatsAndTexs(HLODGenerate hlodGenerate) { Dictionary <HLODGenerate, List <TextureAtlasData> > m_AllAtlases = TextureAtlasModule.instance.AllAtlases; List <TextureAtlasData> data = null; if (m_AllAtlases.TryGetValue(hlodGenerate, out data)) { List <TextureAtlasData> remove = m_RemovedTextureAtlasData; List <TextureAtlasData> add = m_AddedTextureAtlasData; remove.Clear(); add.Clear(); //标记delete的就删除并删除资源,标记add就添加或更新 for (int i = 0; i < data.Count; i++) { TextureAtlasData taData = data[i]; switch (taData.m_State) { case TextureAtlasData.State.Delete: remove.Add(taData); break; case TextureAtlasData.State.Add: taData.m_MeshRenderers.RemoveAll(r => r == null); if (taData.m_MeshRenderers.Count > 0) { add.Add(taData); } else { taData.m_State = TextureAtlasData.State.Delete; remove.Add(taData); } //删除空renderer break; } } data.RemoveAll(r => r.m_State == TextureAtlasData.State.Delete); if (hlodGenerate.m_IsExportMatTex) { if (hlodGenerate.m_TextureAssetPath == "") { EditorUtility.DisplayDialog("警告", "没有选择textures路径,请先选择路径", "是"); hlodGenerate.m_IsExportMatTex = false; return; } if (hlodGenerate.m_MaterialAssetPath == "") { EditorUtility.DisplayDialog("警告", "没有选择materials路径,请先选择路径", "是"); hlodGenerate.m_IsExportMatTex = false; return; } int progressCount = 1; foreach (TextureAtlasData r in remove) { EditorUtility.DisplayProgressBar("删除图集", r.m_Root.name, (float)progressCount++ / remove.Count); TextureAtlasModule.DeleteOnlyOneTextureAtlasData(r); } progressCount = 1; foreach (TextureAtlasData a in add) { EditorUtility.DisplayProgressBar("保存图集", a.m_Root.name, (float)progressCount++ / add.Count); TextureAtlasModule.ExportOnlyOneTextureAtlasData(a, hlodGenerate.m_TextureAssetPath, hlodGenerate.m_MaterialAssetPath, a.m_MeshRenderers[0].name); foreach (MeshRenderer mr in a.m_MeshRenderers) { mr.sharedMaterial = a.m_Material; } a.m_State = TextureAtlasData.State.None; } } remove.Clear(); add.Clear(); EditorUtility.ClearProgressBar(); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } }
public IEnumerator Batch(HLODGenerate hg, LODVolume lodVolume) { GameObject go = lodVolume.combined._hlodRoot; var renderers = go.GetComponentsInChildren <Renderer>(); var materials = new HashSet <Material>(renderers.SelectMany(r => r.sharedMaterials)); List <Texture2D> textures = new List <Texture2D>(); List <Texture2D> normals = new List <Texture2D>(); textures = new HashSet <Texture2D>(materials.Select(m => { if (m) { return(m.mainTexture as Texture2D); } return(null); }).Where(t => t != null)).ToList(); textures.Add(whiteTexture); /* * foreach(var t2d in textures) * { * foreach(var rd in renderers) * { * if(rd.sharedMaterial.mainTexture == t2d) * { * Texture2D t = rd.sharedMaterial.GetTexture("_BumpMap") as Texture2D; * if (t == null) * { * var texture = new Texture2D(rd.sharedMaterial.mainTexture.width, rd.sharedMaterial.mainTexture.height, TextureFormat.RGB24, false, PlayerSettings.colorSpace == ColorSpace.Linear); * * t = texture; * //texture.Apply(); * } * else if(t.width != rd.sharedMaterial.mainTexture.width || t.height != rd.sharedMaterial.mainTexture.height) * { * int width = rd.sharedMaterial.mainTexture.width; * int height = rd.sharedMaterial.mainTexture.height; * var texture = new Texture2D(rd.sharedMaterial.mainTexture.width, rd.sharedMaterial.mainTexture.height, t.format, false, PlayerSettings.colorSpace == ColorSpace.Linear); * * * for(int i = 0; i < height; i++) * { * for(int j = 0; j <width; j++) * { * //EditorUtility.DisplayProgressBar("fsdfasd", (height * width).ToString(), (float)(i * j) / (height * width)); * // Color newColor = t.GetPixelBilinear(j / width, i / height); * texture.SetPixel(j, i, Color.white); * } * } * //EditorUtility.ClearProgressBar(); * texture.Apply(); * t = texture; * } * normals.Add(t); * break; * } * } * } * normals.Add(whiteTexture); */ TextureAtlasData atlasData = null; yield return(TextureAtlasModule.instance.GetTextureAtlas(hg, lodVolume, textures.ToArray(), normals.ToArray(), a => atlasData = a)); var mainAtlasLookup = new Dictionary <Texture2D, Rect>(); //var normalAtlasLookup = new Dictionary<Texture2D, Rect>(); var atlasTextures = atlasData.m_Atlases.textures; for (int i = 0; i < atlasTextures.Length; i++) { mainAtlasLookup[atlasTextures[i]] = atlasData.m_Atlases.uvs[i]; } MeshFilter[] meshFilters = go.GetComponentsInChildren <MeshFilter>(); var combine = new List <CombineInstance>(); for (int i = 0; i < meshFilters.Length; i++) { var mf = meshFilters[i]; var sharedMesh = mf.sharedMesh; if (!sharedMesh) { continue; } if (!sharedMesh.isReadable) { var assetPath = AssetDatabase.GetAssetPath(sharedMesh); if (!string.IsNullOrEmpty(assetPath)) { var importer = AssetImporter.GetAtPath(assetPath) as ModelImporter; if (importer) { importer.isReadable = true; importer.SaveAndReimport(); } } } var ci = new CombineInstance(); var mesh = UnityEngine.Object.Instantiate(sharedMesh); var mr = mf.GetComponent <MeshRenderer>(); var sharedMaterials = mr.sharedMaterials; var uv = mesh.uv; if (uv == null) { uv = mesh.uv2; } var colors = mesh.colors; if (colors == null || colors.Length == 0) { colors = new Color[uv.Length]; } var updated = new bool[uv.Length]; var triangles = new List <int>(); // Some meshes have submeshes that either aren't expected to render or are missing a material, so go ahead and skip var subMeshCount = Mathf.Min(mesh.subMeshCount, sharedMaterials.Length); for (int j = 0; j < subMeshCount; j++) { var sharedMaterial = sharedMaterials[Mathf.Min(j, sharedMaterials.Length - 1)]; var mainTexture = whiteTexture; var materialColor = Color.white; if (sharedMaterial) { var texture = sharedMaterial.mainTexture as Texture2D; //sharedMaterial.texture if (texture) { mainTexture = texture; } if (sharedMaterial.HasProperty("_Color")) { materialColor = sharedMaterial.color; } } if (mesh.GetTopology(j) != MeshTopology.Triangles) { Debug.LogWarning("Mesh must have triangles", mf); continue; } triangles.Clear(); mesh.GetTriangles(triangles, j); var uvOffset = mainAtlasLookup[mainTexture]; foreach (var t in triangles) { if (!updated[t]) { var uvCoord = uv[t]; if (mainTexture == whiteTexture) { // Sample at center of white texture to avoid sampling edge colors incorrectly uvCoord.x = 0.5f; uvCoord.y = 0.5f; } while (uvCoord.x < 0) { uvCoord.x += 1; } while (uvCoord.y < 0) { uvCoord.y += 1; } while (uvCoord.x > 1) { uvCoord.x -= 1; } while (uvCoord.y > 1) { uvCoord.y -= 1; } uvCoord.x = Mathf.Lerp(uvOffset.xMin, uvOffset.xMax, uvCoord.x); uvCoord.y = Mathf.Lerp(uvOffset.yMin, uvOffset.yMax, uvCoord.y); uv[t] = uvCoord; if (mainTexture == whiteTexture) { colors[t] = materialColor; } else { colors[t] = Color.white; } updated[t] = true; } } yield return(null); } mesh.uv = uv; mesh.uv2 = null; mesh.colors = colors; ci.mesh = mesh; ci.transform = mf.transform.localToWorldMatrix; combine.Add(ci); mf.gameObject.SetActive(false); yield return(null); } var combinedMesh = new Mesh(); #if UNITY_2017_3_OR_NEWER combinedMesh.indexFormat = IndexFormat.UInt32; #endif combinedMesh.CombineMeshes(combine.ToArray(), true, true); combinedMesh.RecalculateBounds(); var meshFilter = go.AddComponent <MeshFilter>(); meshFilter.sharedMesh = combinedMesh; for (int i = 0; i < meshFilters.Length; i++) { UnityEngine.Object.DestroyImmediate(meshFilters[i].gameObject); } var meshRenderer = go.AddComponent <MeshRenderer>(); meshRenderer.sharedMaterial = atlasData.m_Material; atlasData.m_MeshRenderers.Add(meshRenderer); }
public IEnumerator GetTextureAtlas(HLODGenerate hg, LODVolume lodVolume, Texture2D[] textures, Texture2D[] normals, Action <TextureAtlasData> callback) { TextureAtlasData atlasData = null; List <TextureAtlasData> atlasesData = null; GetTextureAtlasList(hg, out atlasesData); yield return(null); foreach (var a in atlasesData) { if (a.m_State == TextureAtlasData.State.Delete) { continue; } //检查是否为所在树的贴图集 if (!CheckInCurrLittleOctree(lodVolume, a)) { continue; } //是否重新生成 if (IsReGenerate(lodVolume, textures, a.m_Atlases)) { a.m_State = TextureAtlasData.State.Delete; break; } // At a minimum the atlas should have all of the textures requested, but can be a superset if (!textures.Except(a.m_Atlases.textures).Any()) { atlasData = a; break; } yield return(null); } //m_Atlases.Remove(deleteAtlas); if (atlasData == null)//没有找到图集就创建一个 { atlasData = new TextureAtlasData(null, TextureAtlasData.State.Add); atlasData.m_Material = new Material(Shader.Find("Standard")); /*先序遍历,所有根节点就是第一个创建的对象,子节点会找到这个图集而不会继续创建*/ atlasData.m_Root = lodVolume.gameObject; } if (!atlasData.m_Atlases) { atlasData.m_Atlases = ScriptableObject.CreateInstance <TextureAtlas>(); TextureReadableSetting(textures); //TextureReadableSetting(normals); CombineTexture(textures, atlasData.m_Atlases, false, callback); //CombineTexture(normals, atlasData.m_Atlases, true, callback); atlasData.m_Material.mainTexture = atlasData.m_Atlases.textureAtlas; //material.SetTexture("_NormalMap", atlasData.m_Atlases.textureAtlas_N); atlasesData.Add(atlasData); yield return(null); } if (callback != null) { callback(atlasData); } }