/// <summary> /// Gets terrain albedo texture array containing each terrain tile in a seperate array slice. /// </summary> /// <param name="archive">Archive index.</param> /// <param name="stayReadable">Texture should stay readable.</param> /// <param name="nonAlphaFormat">Non-alpha TextureFormat.</param> /// <returns>Texture2DArray or null</returns> public Texture2DArray GetTerrainAlbedoTextureArray( int archive, bool stayReadable = false, SupportedNonAlphaTextureFormats nonAlphaFormat = SupportedNonAlphaTextureFormats.RGB24) { // Load texture file and check count matches terrain tiles TextureFile textureFile = new TextureFile(Path.Combine(Arena2Path, TextureFile.IndexToFileName(archive)), FileUsage.UseMemory, true); int numSlices = 0; if (textureFile.RecordCount == 56) { numSlices = textureFile.RecordCount; } else { return(null); } Texture2DArray textureArray; if (TextureReplacement.CustomTextureExist(archive, 0, 0)) { Texture2D albedoMap = TextureReplacement.LoadCustomTexture(archive, 0, 0); textureArray = new Texture2DArray(albedoMap.width, albedoMap.height, numSlices, ParseTextureFormat(nonAlphaFormat), MipMaps); } else { textureArray = new Texture2DArray(textureFile.GetWidth(0), textureFile.GetWidth(1), numSlices, ParseTextureFormat(nonAlphaFormat), MipMaps); } // Rollout tiles into texture array for (int record = 0; record < textureFile.RecordCount; record++) { Color32[] albedo; if (TextureReplacement.CustomTextureExist(archive, record, 0)) { // Import custom texture Texture2D albedoMap = TextureReplacement.LoadCustomTexture(archive, record, 0); albedo = albedoMap.GetPixels32(); } else { // Create base image with gutter DFSize sz; albedo = textureFile.GetColor32(record, 0, -1, 0, out sz); } // Insert into texture array textureArray.SetPixels32(albedo, record, 0); } textureArray.Apply(true, !stayReadable); // Change settings for these textures textureArray.wrapMode = TextureWrapMode.Clamp; textureArray.anisoLevel = 8; return(textureArray); }
///// <summary> ///// TEMP: Creates super-atlas populated with all archives in array. ///// Currently does not support animated textures, normal map, or emission map. ///// TODO: Integrate this feature fully with material system. ///// </summary> ///// <param name="archives">Archive array.</param> ///// <param name="borderSize">Number of pixels border to add around image.</param> ///// <param name="dilate">Blend texture into surrounding empty pixels. Requires border.</param> ///// <param name="maxAtlasSize">Maximum atlas size.</param> ///// <param name="alphaTextureFormat">Alpha TextureFormat.</param> ///// <param name="nonAlphaFormat">Non-alpha TextureFormat.</param> ///// <returns>TextureAtlasBuilder.</returns> //public TextureAtlasBuilder CreateTextureAtlasBuilder( // int[] archives, // int borderSize = 0, // bool dilate = false, // int maxAtlasSize = 2048, // SupportedAlphaTextureFormats alphaTextureFormat = SupportedAlphaTextureFormats.RGBA32, // SupportedNonAlphaTextureFormats nonAlphaFormat = SupportedNonAlphaTextureFormats.RGB24) //{ // // Iterate archives // TextureFile textureFile = new TextureFile(); // TextureAtlasBuilder builder = new TextureAtlasBuilder(); // GetTextureSettings settings = TextureReader.CreateTextureSettings(0, 0, 0, 0, borderSize, dilate, maxAtlasSize); // settings.stayReadable = true; // for (int i = 0; i < archives.Length; i++) // { // // Load texture file // settings.archive = archives[i]; // textureFile.Load(Path.Combine(Arena2Path, TextureFile.IndexToFileName(settings.archive)), FileUsage.UseMemory, true); // // Add all records for this archive - single frame only // for (int record = 0; record < textureFile.RecordCount; record++) // { // settings.record = record; // GetTextureResults results = GetTexture2D(settings, alphaTextureFormat, nonAlphaFormat); // DFSize size = textureFile.GetSize(record); // DFSize scale = textureFile.GetScale(record); // builder.AddTextureItem( // results.albedoMap, // settings.archive, // settings.record, // 0, 1, // new Vector2(size.Width, size.Height), // new Vector2(scale.Width, scale.Height)); // } // } // // Apply the builder // builder.Rebuild(borderSize); // return builder; //} /// <summary> /// Gets specially packed tileset atlas for terrains. /// This needs to be improved to create each mip level manually to further reduce artifacts. /// </summary> /// <param name="archive">Archive index.</param> /// <param name="stayReadable">Texture should stay readable.</param> /// <param name="nonAlphaFormat">Non-alpha TextureFormat.</param> /// <returns></returns> public GetTextureResults GetTerrainTilesetTexture( int archive, bool stayReadable = false, SupportedNonAlphaTextureFormats nonAlphaFormat = SupportedNonAlphaTextureFormats.RGB24) { const int atlasDim = 2048; const int gutterSize = 32; GetTextureResults results = new GetTextureResults(); // Load texture file and check count matches terrain tiles TextureFile textureFile = new TextureFile(Path.Combine(Arena2Path, TextureFile.IndexToFileName(archive)), FileUsage.UseMemory, true); if (textureFile.RecordCount != 56) { return(results); } // Rollout tiles into atlas. // This is somewhat inefficient, but fortunately atlases only // need to be generated once and can be prepared offline where // startup time is critical. int x = 0, y = 0; Color32[] atlasColors = new Color32[atlasDim * atlasDim]; for (int record = 0; record < textureFile.RecordCount; record++) { // Create base image with gutter DFSize sz; Color32[] albedo = textureFile.GetColor32(record, 0, -1, gutterSize, out sz); // Wrap and clamp textures based on tile switch (record) { // Textures that do not tile in any direction case 5: case 7: case 10: case 12: case 15: case 17: case 20: case 22: case 25: case 27: case 30: case 32: case 34: case 35: case 36: case 37: case 38: case 39: case 40: case 41: case 42: case 43: case 44: case 45: case 47: case 48: case 49: case 50: case 51: case 52: case 53: case 55: ImageProcessing.ClampBorder(ref albedo, sz, gutterSize); break; // Textures that clamp horizontally and tile vertically case 6: case 11: case 16: case 21: case 26: case 31: ImageProcessing.WrapBorder(ref albedo, sz, gutterSize, false); ImageProcessing.ClampBorder(ref albedo, sz, gutterSize, true, false); break; // Textures that tile in all directions default: ImageProcessing.WrapBorder(ref albedo, sz, gutterSize); break; } // Create variants Color32[] rotate = ImageProcessing.RotateColors(ref albedo, sz.Width, sz.Height); Color32[] flip = ImageProcessing.FlipColors(ref albedo, sz.Width, sz.Height); Color32[] rotateFlip = ImageProcessing.RotateColors(ref flip, sz.Width, sz.Height); // Insert into atlas ImageProcessing.InsertColors(ref albedo, ref atlasColors, x, y, sz.Width, sz.Height, atlasDim, atlasDim); ImageProcessing.InsertColors(ref rotate, ref atlasColors, x + sz.Width, y, sz.Width, sz.Height, atlasDim, atlasDim); ImageProcessing.InsertColors(ref flip, ref atlasColors, x + sz.Width * 2, y, sz.Width, sz.Height, atlasDim, atlasDim); ImageProcessing.InsertColors(ref rotateFlip, ref atlasColors, x + sz.Width * 3, y, sz.Width, sz.Height, atlasDim, atlasDim); // Increment position x += sz.Width * 4; if (x >= atlasDim) { y += sz.Height; x = 0; } } // Create Texture2D Texture2D albedoAtlas = new Texture2D(atlasDim, atlasDim, ParseTextureFormat(nonAlphaFormat), MipMaps); albedoAtlas.SetPixels32(atlasColors); albedoAtlas.Apply(true, !stayReadable); // Change settings for these textures albedoAtlas.wrapMode = TextureWrapMode.Clamp; albedoAtlas.anisoLevel = 8; // Store results results.albedoMap = albedoAtlas; return(results); }