using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor; using System.Linq; using System.IO; public class CubemapTextureBuilder : EditorWindow { [MenuItem("Tools/Cubemap Builder")] public static void OpenWindow() { GetWindow(); } Texture2D[] textures = new Texture2D[6]; string[] labels = new string[] { "Right", "Left", "Top", "Bottom", "Front", "Back" }; TextureFormat[] HDRFormats = new TextureFormat[] { TextureFormat.ASTC_HDR_10x10 , TextureFormat.ASTC_HDR_12x12 , TextureFormat.ASTC_HDR_4x4 , TextureFormat.ASTC_HDR_5x5 , TextureFormat.ASTC_HDR_6x6 , TextureFormat.ASTC_HDR_8x8 , TextureFormat.BC6H , TextureFormat.RGBAFloat , TextureFormat.RGBAHalf }; Vector2Int[] placementRects = new Vector2Int[] { new Vector2Int(2, 1), new Vector2Int(0, 1), new Vector2Int(1, 2), new Vector2Int(1, 0), new Vector2Int(1, 1), new Vector2Int(3, 1), }; private void OnGUI() { for (int i = 0; i < 6; i++) { textures[i] = EditorGUILayout.ObjectField(labels[i], textures[i], typeof(Texture2D), false) as Texture2D; } if (GUILayout.Button("Build Cubemap")) { // Missing Texture if (textures.Any(t => t == null)) { EditorUtility.DisplayDialog("Cubemap Builder Error", "One or more texture is missing.", "Ok"); return; } // Get size var size = textures[0].width; // Not all of the same size or square if (textures.Any(t => (t.width != size) || (t.height != size))) { EditorUtility.DisplayDialog("Cubemap Builder Error", "All the textures need to be the same size and square.", "Ok"); return; } var isHDR = HDRFormats.Any(f => f == textures[0].format); var texturePaths = textures.Select(t => AssetDatabase.GetAssetPath(t)).ToArray(); // Should be ok, ask for the file path. var path = EditorUtility.SaveFilePanel("Save Cubemap", Path.GetDirectoryName(texturePaths[0]), "Cubemap", isHDR ? "exr" : "png"); if (string.IsNullOrEmpty(path)) return; // Save the readable flag to restore it afterwards var readableFlags = textures.Select(t => t.isReadable).ToArray(); // Get the importer and mark the textures as readable var importers = texturePaths.Select(p => TextureImporter.GetAtPath(p) as TextureImporter).ToArray(); foreach (var importer in importers) { importer.isReadable = true; } AssetDatabase.Refresh(); foreach (var p in texturePaths) { AssetDatabase.ImportAsset(p); } // Build the cubemap texture var cubeTexture = new Texture2D(size * 4, size * 3, isHDR ? TextureFormat.RGBAFloat : TextureFormat.RGBA32, false); for (int i = 0; i < 6; i++) { cubeTexture.SetPixels(placementRects[i].x * size, placementRects[i].y * size, size, size, textures[i].GetPixels(0)); } cubeTexture.Apply(false); // Save the texture to the specified path, and destroy the temporary object var bytes = isHDR ? cubeTexture.EncodeToEXR() : cubeTexture.EncodeToPNG(); File.WriteAllBytes(path, bytes); DestroyImmediate(cubeTexture); // Reset the read flags, and reimport everything for (var i = 0; i < 6; i++) { importers[i].isReadable = readableFlags[i]; } path = path.Remove(0, Application.dataPath.Length - 6); AssetDatabase.ImportAsset(path); var cubeImporter = AssetImporter.GetAtPath(path) as TextureImporter; cubeImporter.textureShape = TextureImporterShape.TextureCube; cubeImporter.sRGBTexture = false; cubeImporter.generateCubemap = TextureImporterGenerateCubemap.FullCubemap; foreach (var p in texturePaths) { AssetDatabase.ImportAsset(p); } AssetDatabase.ImportAsset(path); AssetDatabase.Refresh(); } } }