#pragma once #include "BsCorePrerequisites.h" #include "BsPixelData.h" namespace BansheeEngine { /** * @brief Types of texture compression quality. */ enum class CompressionQuality { Fastest, Normal, Production, Highest }; /** * @brief Mode of the alpha channel in a texture. */ enum class AlphaMode { None, /*< Texture has no alpha values. */ Transparency, /*< Alpha is in the separate transparency channel. */ Premultiplied /*< Alpha values have been pre-multiplied with the color values. */ }; /** * @brief Wrap mode to use when generating mip maps. */ enum class MipMapWrapMode { Mirror, Repeat, Clamp }; /** * @brief Filter to use when generating mip maps. */ enum class MipMapFilter { Box, Triangle, Kaiser }; /** * @brief Options used to control texture compression. */ struct CompressionOptions { PixelFormat format = PF_BC1; /*< Format to compress to. Must be a format containing compressed data. */ AlphaMode alphaMode = AlphaMode::None; /*< Controls how to (and if) to compress the alpha channel. */ bool isNormalMap = false; /*< Determines does the input data represent a normal map. */ bool isSRGB = false; /*< Determines has the input data been gamma corrected. */ CompressionQuality quality = CompressionQuality::Normal; /*< Compressed image quality. Better compression might take longer to execute but will generate better results. */ }; /** * @brief Options used to control texture mip map generation. */ struct MipMapGenOptions { MipMapFilter filter = MipMapFilter::Box; /*< Filter to use when downsamping input data. */ MipMapWrapMode wrapMode = MipMapWrapMode::Mirror; /*< Determines how to downsample pixels on borders. */ bool isNormalMap = false; /*< Determines does the input data represent a normal map. */ bool normalizeMipmaps = false; /*< Should the downsampled values be re-normalized. Only relevant for mip-maps representing normal maps. */ }; /** * @brief Utility methods for converting and managing pixel data and formats. */ class BS_CORE_EXPORT PixelUtil { public: /** * @brief Filtering types to use when scaling images. */ enum Filter { FILTER_NEAREST, /*< No filtering is performed and nearest existing value is used. */ FILTER_LINEAR /*< Box filter is applied, averaging nearby pixels. */ }; /** * @brief Returns the size of a single pixel of the provided pixel format, * in bytes. */ static UINT32 getNumElemBytes(PixelFormat format); /** * @brief Returns the size of a single pixel of the provided pixel format, * in bits. */ static UINT32 getNumElemBits( PixelFormat format ); /** * @brief Returns the size of the memory region required to hold pixels of the provided size ana format. */ static UINT32 getMemorySize(UINT32 width, UINT32 height, UINT32 depth, PixelFormat format); /** * @brief Calculates the size of a mip level of a texture with the provided size. */ static void getSizeForMipLevel(UINT32 width, UINT32 height, UINT32 depth, UINT32 mipLevel, UINT32& mipWidth, UINT32& mipHeight, UINT32& mipDepth); /** * @brief Returns property flags for this pixel format. * * @see PixelFormatFlags */ static UINT32 getFlags(PixelFormat format); /** * @brief Checks if the provided pixel format has an alpha channel. */ static bool hasAlpha(PixelFormat format); /** * @brief Checks is the provided pixel format a floating point format. */ static bool isFloatingPoint(PixelFormat format); /** * @brief Checks is the provided pixel format compressed. */ static bool isCompressed(PixelFormat format); /** * @brief Checks is the provided pixel format a depth/stencil buffer format. */ static bool isDepth(PixelFormat format); /** * @brief Checks is the provided format in native endian format. */ static bool isNativeEndian(PixelFormat format); /** * @brief Checks are the provided dimensions valid for the specified pixel format. * Some formats (like DXT) require width/height to be multiples of four and some * formats dont allow depth larger than 1. */ static bool isValidExtent(UINT32 width, UINT32 height, UINT32 depth, PixelFormat format); /** * @brief Returns the number of bits per each element in the provided pixel format. * This will return all zero for compressed and depth/stencil formats. */ static void getBitDepths(PixelFormat format, int rgba[4]); /** * @brief Returns bit masks that determine in what bit range is each channel stored. * * @note e.g. if your color is stored in an UINT32 and you want to extract the red channel * you should AND the color UINT32 with the bit-mask for the red channel and then * right shift it by the red channel bit shift amount. */ static void getBitMasks(PixelFormat format, UINT32 rgba[4]); /** * @brief Returns number of bits you need to shift a pixel element in order * to move it to the start of the data type. * * @note e.g. if your color is stored in an UINT32 and you want to extract the red channel * you should AND the color UINT32 with the bit-mask for the red channel and then * right shift it by the red channel bit shift amount. */ static void getBitShifts(PixelFormat format, UINT8 rgba[4]); /** * @brief Returns the name of the pixel format. */ static String getFormatName(PixelFormat srcformat); /** * @brief Returns true if the pixel data in the format can be directly accessed and read. * This is generally not true for compressed formats. */ static bool isAccessible(PixelFormat srcformat); /** * @brief Returns the type of an individual pixel element in the provided format. */ static PixelComponentType getElementType(PixelFormat format); /** * @brief Returns the number of pixel elements in the provided format. */ static UINT32 getNumElements(PixelFormat format); /** * @brief Returns the maximum number of mip maps that can be generated until we reach * the minimum size possible. This does not count the base level. */ static UINT32 getMaxMipmaps(UINT32 width, UINT32 height, UINT32 depth, PixelFormat format); /** * @brief Writes the color to the provided memory location. */ static void packColor(const Color& color, PixelFormat format, void* dest); /** * @brief Writes the color to the provided memory location. If the destination * format is floating point, the byte values will be converted into [0.0, 1.0] range. */ static void packColor(UINT8 r, UINT8 g, UINT8 b, UINT8 a, PixelFormat format, void* dest); /** * @brief Writes the color to the provided memory location. If the destination format * in non-floating point, the float values will be assumed to be in [0.0, 1.0] which * will be converted to integer range. ([0, 255] in the case of bytes) */ static void packColor(float r, float g, float b, float a, const PixelFormat format, void* dest); /** * @brief Reads the color from the provided memory location and stores it * into the provided color object. */ static void unpackColor(Color* color, PixelFormat format, const void* src); /** * @brief Reads the color from the provided memory location and stores it * into the provided color elements, as bytes clamped to [0, 255] range. */ static void unpackColor(UINT8* r, UINT8* g, UINT8* b, UINT8* a, PixelFormat format, const void* src); /** * @brief Reads the color from the provided memory location and stores it * into the provided color elements. If the format is not natively floating * point a conversion is done in such a way that returned values range [0.0, 1.0]. */ static void unpackColor(float* r, float* g, float* b, float* a, PixelFormat format, const void* src); /** * @brief Converts pixels from one format to another. Provided pixel data objects * must have previously allocated buffers of adequate size and their sizes must match. */ static void bulkPixelConversion(const PixelData& src, PixelData& dst); /** * @brief Compresses the provided data using the specified compression options. */ static void compress(const PixelData& src, PixelData& dst, const CompressionOptions& options); /** * @brief Generates mip-maps from the provided source data using the specified compression options. * Returned list includes the base level. * * @returns A list of calculated mip-map data. First entry is the largest mip and other follow in * order from largest to smallest. */ static Vector genMipmaps(const PixelData& src, const MipMapGenOptions& options); /** * @brief Scales pixel data in the source buffer and stores the scaled data in the destination buffer. * Provided pixel data objects must have previously allocated buffers of adequate size. You may * also provided a filtering method to use when scaling. */ static void scale(const PixelData& src, PixelData& dst, Filter filter = FILTER_LINEAR); /** * @brief Applies gamma correction to the pixels in the provided buffer. * * @param buffer Pointer to the buffer containing the pixels. * @param gamma Gamma value to apply. * @param size Size of the buffer in bytes. * @param bpp Number of bits per pixel of the pixels in the buffer. */ static void applyGamma(UINT8* buffer, float gamma, UINT32 size, UINT8 bpp); }; }