// Copyright (c) Wojciech Figat. All rights reserved. #pragma once #if COMPILE_WITH_TEXTURE_TOOL #include "Engine/Render2D/SpriteAtlas.h" #include "Engine/Graphics/Textures/Types.h" #include "Engine/Graphics/Textures/GPUTexture.h" #include "Engine/Core/ISerializable.h" class JsonWriter; /// /// Textures importing, processing and exporting utilities. /// API_CLASS(Namespace="FlaxEngine.Tools", Static) class FLAXENGINE_API TextureTool { DECLARE_SCRIPTING_TYPE_MINIMAL(TextureTool); /// /// Texture import options. /// API_STRUCT(Attributes="HideInEditor") struct FLAXENGINE_API Options : public ISerializable { DECLARE_SCRIPTING_TYPE_MINIMAL(Options); // Texture format type. API_FIELD(Attributes="EditorOrder(0)") TextureFormatType Type = TextureFormatType::ColorRGB; // True if texture should be imported as a texture atlas (with sprites). API_FIELD(Attributes="EditorOrder(10)") bool IsAtlas = false; // True if disable dynamic texture streaming. API_FIELD(Attributes="EditorOrder(20)") bool NeverStream = false; // True if disable dynamic texture streaming. API_FIELD(Attributes="EditorOrder(30)") bool Compress = true; // True if texture channels have independent data (for compression methods). API_FIELD(Attributes="EditorOrder(40)") bool IndependentChannels = false; // If checked, indicates that input file should be loaded as an sRGB image. Common for color maps and diffuse/albedo textures. API_FIELD(Attributes="EditorOrder(50), EditorDisplay(null, \"sRGB\")") bool sRGB = false; // True if generate mip maps chain for the texture. API_FIELD(Attributes="EditorOrder(60)") bool GenerateMipMaps = true; // True if flip Y coordinate of the texture (Flips over X axis). API_FIELD(Attributes="EditorOrder(70)") bool FlipY = false; // True if flip X coordinate of the texture (Flips over Y axis). API_FIELD(Attributes="EditorOrder(71)") bool FlipX = false; // Invert the red channel. API_FIELD(Attributes="EditorOrder(72), EditorDisplay(\"Invert Channels\")") bool InvertRedChannel = false; // Invert the green channel. Good for OpenGL to DirectX conversion. API_FIELD(Attributes="EditorOrder(73), EditorDisplay(\"Invert Channels\")") bool InvertGreenChannel = false; // Invert the blue channel. API_FIELD(Attributes="EditorOrder(74), EditorDisplay(\"Invert Channels\")") bool InvertBlueChannel = false; // Invert the alpha channel. API_FIELD(Attributes="EditorOrder(75), EditorDisplay(\"Invert Channels\")") bool InvertAlphaChannel = false; // Rebuild Z (blue) channel assuming X/Y are normals. API_FIELD(Attributes="EditorOrder(76)") bool ReconstructZChannel = false; // Texture size scale. Allows increasing or decreasing the imported texture resolution. Default is 1. API_FIELD(Attributes="EditorOrder(80), Limit(0.0001f, 1000.0f, 0.01f)") float Scale = 1.0f; // Maximum size of the texture (for both width and height). Higher resolution textures will be resized during importing process. Used to clip textures that are too big. API_FIELD(Attributes="HideInEditor") int32 MaxSize = 8192; // True if resize texture on import. Use SizeX/SizeY properties to define texture width and height. Texture scale property will be ignored. API_FIELD(Attributes="EditorOrder(100)") bool Resize = false; // Keeps the aspect ratio when resizing. API_FIELD(Attributes="EditorOrder(101), VisibleIf(nameof(Resize))") bool KeepAspectRatio = false; // The width of the imported texture. If Resize property is set to true then texture will be resized during the import to this value during the import, otherwise it will be ignored. API_FIELD(Attributes="HideInEditor") int32 SizeX = 1024; // The height of the imported texture. If Resize property is set to true then texture will be resized during the import to this value during the import, otherwise it will be ignored. API_FIELD(Attributes="HideInEditor") int32 SizeY = 1024; // Check to preserve alpha coverage in generated mips for alpha test reference. Scales mipmap alpha values to preserve alpha coverage based on an alpha test reference value. API_FIELD(Attributes="EditorOrder(200)") bool PreserveAlphaCoverage = false; // The reference value for the alpha coverage preserving. API_FIELD(Attributes="EditorOrder(210), VisibleIf(\"PreserveAlphaCoverage\")") float PreserveAlphaCoverageReference = 0.5f; // The texture group for streaming (negative if unused). See Streaming Settings. API_FIELD(Attributes="EditorOrder(300), CustomEditorAlias(\"FlaxEditor.CustomEditors.Dedicated.TextureGroupEditor\")") int32 TextureGroup = -1; // The sprites for the sprite sheet import mode. API_FIELD(Attributes="HideInEditor") Array Sprites; // The custom format to use. Can be used to override default format from texture Type. API_FIELD(Attributes="HideInEditor") PixelFormat InternalFormat = PixelFormat::Unknown; // Function used for fast importing textures used by internal parts of the engine Function InternalLoad; public: String ToString() const; // [ISerializable] void Serialize(SerializeStream& stream, const void* otherObj) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override; }; public: #if USE_EDITOR /// /// Checks whenever the given texture file contains alpha channel data with values different from solid fill of 1 (non fully opaque). /// /// The file path. /// True if has alpha channel, otherwise false. static bool HasAlpha(const StringView& path); #endif /// /// Imports the texture. /// /// The file path. /// The output data. /// True if fails, otherwise false. static bool ImportTexture(const StringView& path, TextureData& textureData); /// /// Imports the texture. /// /// The file path. /// The output data. /// The import options. /// The error message container. /// True if fails, otherwise false. static bool ImportTexture(const StringView& path, TextureData& textureData, Options options, String& errorMsg); /// /// Exports the texture. /// /// The output file path. /// The output data. /// True if fails, otherwise false. static bool ExportTexture(const StringView& path, const TextureData& textureData); /// /// Converts the specified source texture data into another format. /// /// The destination data. /// The source data. /// The destination data format. Must be other than source data type. /// True if fails, otherwise false. static bool Convert(TextureData& dst, const TextureData& src, const PixelFormat dstFormat); /// /// Resizes the specified source texture data into another dimensions. /// /// The destination data. /// The source data. /// The destination data width. /// The destination data height. /// True if fails, otherwise false. static bool Resize(TextureData& dst, const TextureData& src, int32 dstWidth, int32 dstHeight); /// /// Updates the texture data. Supports transcoding source data (eg. Basis). /// /// The GPU context. /// The destination GPU texture. It has to be allocated. /// The destination surface index in the texture array. /// The absolute index of the mip map to update. /// The buffer with texture the data. /// The row pitch (in bytes) of the input data. /// The slice pitch (in bytes) of the input data. /// The format of the data. If different then GPU texture format then runtime conversion might happen. static bool UpdateTexture(GPUContext* context, GPUTexture* texture, int32 arrayIndex, int32 mipIndex, Span data, uint32 rowPitch, uint32 slicePitch, PixelFormat dataFormat); /// /// Calculates the runtime format for the texture pixels based on the texture type and input texture data (format and size). Checks the current GPUDevice formats support. /// /// Type fo the texture that hints it's usage. /// The existing texture data format (ideally to preserve to avoid conversions). /// Width of the texture (in pixels). /// Height of the texture (in pixels). /// Indicates that texture data is stored in sRGB color space. /// Resolved pixel format for the GPU Texture. static PixelFormat GetTextureFormat(TextureFormatType textureType, PixelFormat dataFormat, int32 width, int32 height, bool sRGB); public: static PixelFormat ToPixelFormat(TextureFormatType format, int32 width, int32 height, bool canCompress = true); #if USE_EDITOR static bool WriteTextureData(BytesContainer& result, const TextureData& textureData, int32 mipIndex); #endif private: enum class ImageType { DDS, TGA, PNG, BMP, GIF, TIFF, JPEG, HDR, RAW, EXR, Internal, }; static bool GetImageType(const StringView& path, ImageType& type); static bool Transform(TextureData& texture, const Function& transformation); #if COMPILE_WITH_DIRECTXTEX static bool ExportTextureDirectXTex(ImageType type, const StringView& path, const TextureData& textureData); static bool ImportTextureDirectXTex(ImageType type, const StringView& path, TextureData& textureData, bool& hasAlpha); static bool ImportTextureDirectXTex(ImageType type, const StringView& path, TextureData& textureData, const Options& options, String& errorMsg, bool& hasAlpha); static bool ConvertDirectXTex(TextureData& dst, const TextureData& src, const PixelFormat dstFormat); static bool ResizeDirectXTex(TextureData& dst, const TextureData& src, int32 dstWidth, int32 dstHeight); #endif #if COMPILE_WITH_STB static bool ExportTextureStb(ImageType type, const StringView& path, const TextureData& textureData); static bool ImportTextureStb(ImageType type, const StringView& path, TextureData& textureData, bool& hasAlpha); static bool ImportTextureStb(ImageType type, const StringView& path, TextureData& textureData, const Options& options, String& errorMsg, bool& hasAlpha); static bool ConvertStb(TextureData& dst, const TextureData& src, const PixelFormat dstFormat); static bool ResizeStb(PixelFormat format, TextureMipData& dstMip, const TextureMipData& srcMip, int32 dstMipWidth, int32 dstMipHeight); static bool ResizeStb(TextureData& dst, const TextureData& src, int32 dstWidth, int32 dstHeight); #endif #if COMPILE_WITH_ASTC static bool ConvertAstc(TextureData& dst, const TextureData& src, PixelFormat dstFormat); #endif #if COMPILE_WITH_BASISU static bool ConvertBasisUniversal(TextureData& dst, const TextureData& src); static bool UpdateTextureBasisUniversal(GPUContext* context, GPUTexture* texture, int32 arrayIndex, int32 mipIndex, Span data, uint32 rowPitch, uint32 slicePitch, PixelFormat dataFormat); #endif }; #endif