diff --git a/src/AbstractTexture.cpp b/src/AbstractTexture.cpp index 89d5eeef6..57ee1c9bc 100644 --- a/src/AbstractTexture.cpp +++ b/src/AbstractTexture.cpp @@ -80,4 +80,42 @@ void AbstractTexture::generateMipmap() { glGenerateMipmap(target); } +AbstractTexture::InternalFormat::InternalFormat(AbstractTexture::Components components, AbstractTexture::ComponentType type) { + #define internalFormatSwitch(c) switch(type) { \ + case ComponentType::UnsignedByte: \ + internalFormat = GL_##c##8UI; break; \ + case ComponentType::Byte: \ + internalFormat = GL_##c##8I; break; \ + case ComponentType::UnsignedShort: \ + internalFormat = GL_##c##16UI; break; \ + case ComponentType::Short: \ + internalFormat = GL_##c##16I; break; \ + case ComponentType::UnsignedInt: \ + internalFormat = GL_##c##32UI; break; \ + case ComponentType::Int: \ + internalFormat = GL_##c##32I; break; \ + case ComponentType::Half: \ + internalFormat = GL_##c##16F; break; \ + case ComponentType::Float: \ + internalFormat = GL_##c##32F; break; \ + case ComponentType::NormalizedUnsignedByte: \ + internalFormat = GL_##c##8; break; \ + case ComponentType::NormalizedByte: \ + internalFormat = GL_##c##8_SNORM; break; \ + case ComponentType::NormalizedUnsignedShort: \ + internalFormat = GL_##c##16; break; \ + case ComponentType::NormalizedShort: \ + internalFormat = GL_##c##16_SNORM; break; \ + } + if(components == Components::Red) + internalFormatSwitch(R) + else if(components == Components::RedGreen) + internalFormatSwitch(RG) + else if(components == Components::RGB) + internalFormatSwitch(RGB) + else if(components == Components::RGBA) + internalFormatSwitch(RGBA) + #undef internalFormatSwitch +} + } diff --git a/src/AbstractTexture.h b/src/AbstractTexture.h index b184693e8..76657184f 100644 --- a/src/AbstractTexture.h +++ b/src/AbstractTexture.h @@ -93,28 +93,229 @@ class MAGNUM_EXPORT AbstractTexture { ClampToBorder = GL_CLAMP_TO_BORDER }; - /** @brief Internal format */ - enum class InternalFormat: GLint { - Red = GL_RED, /**< One-component (red channel) */ - RedGreen = GL_RG, /**< Two-component (red and green channel) */ - RGB = GL_RGB, /**< Three-component (RGB) */ - RGBA = GL_RGBA, /**< Four-component (RGBA) */ - BGR = GL_BGR, /**< Three-component (BGR) */ - BGRA = GL_BGRA, /**< Four-component (BGRA) */ + /** @{ @name Internal texture formats */ + + /** @brief Number of components for each value */ + enum class Components { + /** + * Red component only. Green and blue are set to `0`, alpha is set + * to `1`. + */ + Red, + + /** + * Red and green component. Blue is set to `0`, alpha is set to + * `1`. + */ + RedGreen, + + RGB, /**< Red, green and blue component. Alpha is set to `1`. */ + RGBA /**< Red, green, blue component and alpha. */ + }; + + /** @brief Type of data per each component */ + enum class ComponentType { + UnsignedByte, /**< Unsigned byte (char) */ + Byte, /**< Byte (char) */ + UnsignedShort, /**< Unsigned short */ + Short, /**< Short */ + UnsignedInt, /**< Unsigned integer */ + Int, /**< Integer */ + Half, /**< Half float (16 bit) */ + Float, /**< Float (32 bit) */ + + /** + * Normalized unsigned byte, i.e. values from range + * @f$ [0; 255] @f$ are converted to range @f$ [0.0; 1.0] @f$. + */ + NormalizedUnsignedByte, + + /** + * Normalized byte, i.e. values from range + * @f$ [-128; 127] @f$ are converted to range @f$ [0.0; 1.0] @f$. + */ + NormalizedByte, + + /** + * Normalized unsigned short, i.e. values from range + * @f$ [0; 65536] @f$ are converted to range @f$ [0.0; 1.0] @f$. + */ + NormalizedUnsignedShort, + + /** + * Normalized short, i.e. values from range + * @f$ [-32768; 32767] @f$ are converted to range @f$ [0.0; 1.0] @f$. + */ + NormalizedShort + }; + + /** + * @brief Internal format + * + * For more information about default values for unused components and + * normalization see enums Components and ComponentType. + */ + enum class Format: GLenum { + /** + * One-component (red channel), unsigned normalized, probably + * 8bit. + */ + Red = GL_RED, + + /** + * Two-component (red and green channel), unsigned normalized, + * each component probably 8bit, 16bit total. + */ + RedGreen = GL_RG, + + /** + * Three-component RGB, unsigned normalized, each component + * probably 8bit, 24bit total. + */ + RGB = GL_RGB, + + /** + * Four-component RGBA, unsigned normalized, each component + * probably 8bit, 24bit total. + */ + RGBA = GL_RGBA, + + /** + * Three-component BGR, unsigned normalized, each component + * probably 8bit, 24bit total. + */ + BGR = GL_BGR, + + /** + * Four-component BGRA, unsigned normalized, each component + * probably 8bit, 24bit total. + */ + BGRA = GL_BGRA, + + /** + * Four-component sRGBA, unsigned normalized, each component + * 8bit, 32bit total. + */ + SRGBA8 = GL_SRGB8_ALPHA8, + + /** + * Three-component sRGB, unsigned normalized, each component + * 8bit, 24bit total. + */ + SRGB8 = GL_SRGB8, + + /** + * Four-component RGBA, unsigned normalized, each RGB component + * 10bit, alpha 2bit, 32bit total. + */ + RGB10Alpha2 = GL_RGB10_A2, + + /** + * Four-component RGBA, unsigned integers, each RGB component + * 10bit, alpha channel 2bit, 32bit total. + */ + RGB10Alpha2Unsigned = GL_RGB10_A2UI, + + /** + * Four-component RGBA, unsigned normalized, each RGB component + * 5bit, alpha 1bit, 16bit total. + */ + RGB5Alpha1 = GL_RGB5_A1, + + /** + * Four-component RGBA, unsigned normalized, each component 4bit, + * 16bit total. + */ + RGBA4 = GL_RGBA4, + + /** + * Three-component RGB, float, red and green 11bit, blue 10bit, + * 32bit total. + */ + RG11B10Float = GL_R11F_G11F_B10F, - /** Compressed red channel */ + #if defined(GL_RGB565) || defined(DOXYGEN_GENERATING_OUTPUT) + /** + * Three-component RGB, unsigned normalized, red and blue 5bit, + * green 6bit, 16bit total. + */ + RGB565 = GL_RGB565, + #endif + + /** + * Three-component RGB, unsigned integers with exponent, each + * component 9bit, exponent 5bit, 32bit total. + */ + RGB9Exponent5 = GL_RGB9_E5, + + /** + * Compressed red channel, unsigned normalized. + */ CompressedRed = GL_COMPRESSED_RED, - /** Compressed red and green channel */ + /** + * Compressed red and green channel, unsigned normalized. + */ CompressedRedGreen = GL_COMPRESSED_RG, - /** Compressed RGB */ + /** Compressed RGB, unsigned normalized. */ CompressedRGB = GL_COMPRESSED_RGB, - /** Compressed RGBA */ - CompressedRGBA = GL_COMPRESSED_RGBA + /** Compressed RGBA, unsigned normalized. */ + CompressedRGBA = GL_COMPRESSED_RGBA, + + /** RTGC compressed red channel, unsigned normalized. */ + CompressedRtgcRed = GL_COMPRESSED_RED_RGTC1, + + /** RTGC compressed red channel, signed normalized. */ + CompressedRtgcSignedRed = GL_COMPRESSED_SIGNED_RED_RGTC1, + + /** RTGC compressed red and green channel, unsigned normalized. */ + CompressedRtgcRedGreen = GL_COMPRESSED_RG_RGTC2, + + /** RTGC compressed red and green channel, signed normalized. */ + CompressedRtgcSignedRedGreen = GL_COMPRESSED_SIGNED_RG_RGTC2, + + #if defined(GL_RGB565) || defined(DOXYGEN_GENERATING_OUTPUT) + /** BTPC compressed RGBA, unsigned normalized. */ + CompressedBtpcRGBA = GL_COMPRESSED_RGBA_BPTC_UNORM, + + /** BTPC compressed sRGBA, unsigned normalized. */ + CompressedBtpcSRGBA = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM, + + /** BTPC compressed RGB, signed float. */ + CompressedBtpcRGBSignedFloat = GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT, + + /** BTPC compressed RGB, unsigned float. */ + CompressedBtpcRGBUnsignedFloat = GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT, + #endif + + /** Depth component. */ + Depth = GL_DEPTH_COMPONENT, + + /** Depth and stencil component. */ + DepthStencil = GL_DEPTH_STENCIL, + + /** 16bit depth component. */ + Depth16 = GL_DEPTH_COMPONENT16, + + /** 24bit depth component. */ + Depth24 = GL_DEPTH_COMPONENT24, + + /** 32bit float depth component. */ + Depth32Float = GL_DEPTH_COMPONENT32F, + + /** 24bit depth and 8bit stencil component. */ + Depth24Stencil8 = GL_DEPTH24_STENCIL8, + + /** 32bit float depth component and 8bit stencil component. */ + Depth32FloatStencil8 = GL_DEPTH32F_STENCIL8 }; + class InternalFormat; + + /*@}*/ + /** @brief Color format */ enum class ColorFormat: GLenum { Red = GL_RED, /**< One-component (red channel) */ @@ -328,6 +529,46 @@ class MAGNUM_EXPORT AbstractTexture { GLuint texture; }; +/** +@brief Internal format + +When specifying internal format, you can either specify as binary OR of +component count (using Component enum) and data type per component (value from +ComponentType enum), or using one of named internal formats from Format enum, +e.g.: +@code +InternalFormat fmt1 = Format::RGBA; +InternalFormat fmt2 = Components::RGBA|ComponentType::NormalizedUnsignedByte; +@endcode +You can also use the constructor directly instead of binary OR: +@code +InternalFormat fmt2(Components::RGBA, ComponentType::NormalizedUnsignedByte); +@endcode +*/ +class AbstractTexture::InternalFormat { + public: + /** @brief Constructor from component count and data type per component */ + InternalFormat(Components components, ComponentType type); + + /** @brief Constructor from named internal format */ + inline constexpr InternalFormat(Format format): internalFormat(static_cast(format)) {} + + /** @brief OpenGL internal format ID */ + inline constexpr operator GLint() const { return internalFormat; } + + private: + GLint internalFormat; +}; + +/** @brief Convertor of component count and data type to InternalFormat */ +inline AbstractTexture::InternalFormat operator|(AbstractTexture::Components components, AbstractTexture::ComponentType type) { + return AbstractTexture::InternalFormat(components, type); +} +/** @brief Convertor of component count and data type to InternalFormat */ +inline AbstractTexture::InternalFormat operator|(AbstractTexture::ComponentType type, AbstractTexture::Components components) { + return AbstractTexture::InternalFormat(components, type); +} + #ifndef DOXYGEN_GENERATING_OUTPUT template<> struct AbstractTexture::DataHelper<1> { enum class Target: GLenum { @@ -341,7 +582,7 @@ template<> struct AbstractTexture::DataHelper<1> { } inline static void set(Target target, GLint mipLevel, InternalFormat internalFormat, const Math::Vector& dimensions, ColorFormat colorFormat, Type type, const void* data) { - glTexImage1D(static_cast(target), mipLevel, static_cast(internalFormat), dimensions.at(0), 0, static_cast(colorFormat), static_cast(type), data); + glTexImage1D(static_cast(target), mipLevel, internalFormat, dimensions.at(0), 0, static_cast(colorFormat), static_cast(type), data); } template inline static void set(Target target, GLint mipLevel, InternalFormat internalFormat, T* image) { @@ -378,7 +619,7 @@ template<> struct AbstractTexture::DataHelper<2> { } inline static void set(Target target, GLint mipLevel, InternalFormat internalFormat, const Math::Vector& dimensions, ColorFormat colorFormat, Type type, const void* data) { - glTexImage2D(static_cast(target), mipLevel, static_cast(internalFormat), dimensions.at(0), dimensions.at(1), 0, static_cast(colorFormat), static_cast(type), data); + glTexImage2D(static_cast(target), mipLevel, internalFormat, dimensions.at(0), dimensions.at(1), 0, static_cast(colorFormat), static_cast(type), data); } template inline static void set(Target target, GLint mipLevel, InternalFormat internalFormat, T* image) { @@ -408,7 +649,7 @@ template<> struct AbstractTexture::DataHelper<3> { } inline static void set(Target target, GLint mipLevel, InternalFormat internalFormat, const Math::Vector& dimensions, ColorFormat colorFormat, Type type, const void* data) { - glTexImage3D(static_cast(target), mipLevel, static_cast(internalFormat), dimensions.at(0), dimensions.at(1), dimensions.at(2), 0, static_cast(colorFormat), static_cast(type), data); + glTexImage3D(static_cast(target), mipLevel, internalFormat, dimensions.at(0), dimensions.at(1), dimensions.at(2), 0, static_cast(colorFormat), static_cast(type), data); } template inline static void set(Target target, GLint mipLevel, InternalFormat internalFormat, T* image) {