// SPDX-FileCopyrightText: 2023 Unity Technologies and the glTFast authors // SPDX-License-Identifier: Apache-2.0 using System; using UnityEngine; using UnityEngine.Assertions; #if UNITY_2022_1_OR_NEWER using UnityEngine.Experimental.Rendering; #endif using Object = UnityEngine.Object; namespace GLTFast.Export { /// /// Wrapper to export a glTF image from one or more Unity textures /// public abstract class ImageExportBase { /// /// Exported texture's file name /// public abstract string FileName { get; } /// /// Exported texture's mime type /// public abstract string MimeType { get; } /// /// Source texture's filter mode /// public abstract FilterMode FilterMode { get; } /// /// Source texture's wrap mode (U direction) /// public abstract TextureWrapMode WrapModeU { get; } /// /// Source texture's wrap mode (V direction) /// public abstract TextureWrapMode WrapModeV { get; } /// /// Writes image file /// /// Destination file path /// If true, existing files will be overwritten /// True if writing succeeded, false otherwise public abstract bool Write(string filePath, bool overwrite); /// /// Returns the exported and encoded texture data /// /// Encoded texture data. public abstract byte[] GetData(); /// /// [1-100] quality for JPG images /// public int JpgQuality { get; set; } = 60; /// /// Encodes the export texture /// /// Main texture to encode /// Image format /// [1-100] quality for JPG images /// True if the texture has an alpha channel /// Custom blit material /// Encoded texture data protected static byte[] EncodeTexture( Texture2D texture, ImageFormat format, int jpgQuality, bool hasAlpha = true, Material blitMaterial = null) { #if UNITY_IMAGECONVERSION Assert.IsNotNull(texture); Texture2D exportTexture; var tmpTexture = false; if (texture.isReadable && blitMaterial==null) { exportTexture = texture; } else { var destRenderTexture = RenderTexture.GetTemporary( texture.width, texture.height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear, 1, RenderTextureMemoryless.Depth ); if (blitMaterial == null) { Graphics.Blit(texture, destRenderTexture); } else { Graphics.Blit(texture, destRenderTexture, blitMaterial); } exportTexture = new Texture2D( texture.width, texture.height, #if UNITY_2023_2_OR_NEWER // ~20 times faster texture construction !hasAlpha && SystemInfo.IsFormatSupported(GraphicsFormat.R8G8B8_UNorm, GraphicsFormatUsage.Sample) ? GraphicsFormat.R8G8B8_UNorm : GraphicsFormat.R8G8B8A8_UNorm, TextureCreationFlags.DontInitializePixels | TextureCreationFlags.DontUploadUponCreate #elif UNITY_2022_1_OR_NEWER // ~20 times faster texture construction !hasAlpha && SystemInfo.IsFormatSupported(GraphicsFormat.R8G8B8_UNorm, FormatUsage.Sample) ? GraphicsFormat.R8G8B8_UNorm : GraphicsFormat.R8G8B8A8_UNorm, TextureCreationFlags.DontInitializePixels | TextureCreationFlags.DontUploadUponCreate #else hasAlpha ? TextureFormat.ARGB32 : TextureFormat.RGB24, false, true #endif ); exportTexture.ReadPixels(new Rect(0, 0, destRenderTexture.width, destRenderTexture.height), 0, 0); RenderTexture.ReleaseTemporary(destRenderTexture); exportTexture.Apply(); tmpTexture = true; } var imageData = format == ImageFormat.Png ? exportTexture.EncodeToPNG() : exportTexture.EncodeToJPG(jpgQuality); if (tmpTexture) { // Release temporary texture #if UNITY_EDITOR Object.DestroyImmediate(exportTexture); #else Object.Destroy(exportTexture); #endif } return imageData; #else return null; #endif } } }