diff --git a/src/Texture.cpp b/src/Texture.cpp index 3a10b53f1..2b63207a4 100644 --- a/src/Texture.cpp +++ b/src/Texture.cpp @@ -30,20 +30,43 @@ static_assert(((Texture1D::NearestNeighborFilter|Texture1D::BaseMipLevel) == GL_ template void Texture::setWrapping(const Math::Vector& wrapping) { bind(); - for(int i = 0; i != dimensions; ++i) switch(i) { - case 0: - glTexParameteri(target, GL_TEXTURE_WRAP_S, wrapping.at(i)); - break; - case 1: - glTexParameteri(target, GL_TEXTURE_WRAP_T, wrapping.at(i)); - break; - case 2: - glTexParameteri(target, GL_TEXTURE_WRAP_R, wrapping.at(i)); - break; + for(int i = 0; i != dimensions; ++i) { + /* Repeat wrap modes are not available on rectangle textures. */ + if(target == GL_TEXTURE_RECTANGLE && (wrapping.at(i) == Repeat || wrapping.at(i) == MirroredRepeat)) + continue; + + switch(i) { + case 0: + glTexParameteri(target, GL_TEXTURE_WRAP_S, wrapping.at(i)); + break; + case 1: + glTexParameteri(target, GL_TEXTURE_WRAP_T, wrapping.at(i)); + break; + case 2: + glTexParameteri(target, GL_TEXTURE_WRAP_R, wrapping.at(i)); + break; + } } unbind(); } +template void Texture::setMinificationFilter(Filter filter, Mipmap mipmap) { + /* Only base mip level is supported on rectangle textures */ + if(target == GL_TEXTURE_RECTANGLE) mipmap = BaseMipLevel; + + bind(); + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter|mipmap); + unbind(); +} + +template void Texture::generateMipmap() { + if(target == GL_TEXTURE_RECTANGLE) return; + + bind(); + glGenerateMipmap(target); + unbind(); +} + /* Instantiate all textures */ template class Texture<1>; template class Texture<2>; diff --git a/src/Texture.h b/src/Texture.h index b5cb81ad7..5a2ddcea8 100644 --- a/src/Texture.h +++ b/src/Texture.h @@ -25,7 +25,7 @@ namespace Magnum { /** -@brief Texture +@brief %Texture Template class for one- to three-dimensional textures. Recommended usage is via subclassing and setting texture data from e.g. constructor with setData(). @@ -33,6 +33,20 @@ subclassing and setting texture data from e.g. constructor with setData(). @attention Don't forget to call setMinificationFilter() and setMagnificationFilter() after creating the texture, otherwise it will be unusable. + +The texture is bound via bind() and setting texture uniform on the shader to +desired texture layer. In shader, the texture is used via @c sampler1D, +@c sampler2D or @c sampler3D depending on dimension count. + +@section RectangleTextures Rectangle textures + +If you want to use rectangle textures, set target in constructor to +@c GL_TEXTURE_RECTANGLE and in shader use @c sampler2DRect. Unlike @c sampler2D, +which accepts coordinates between 0 and 1, @c sampler2DRect accepts coordinates +between 0 and @c textureSizeInGivenDirection-1. Note that rectangle textures +don't support mipmapping and repeating wrapping modes, see @ref Texture::Filter +"Filter", @ref Texture::Mipmap "Mipmap" and generateMipmap() documentation +for more information. */ template class Texture { public: @@ -54,17 +68,18 @@ template class Texture { /** @brief Mip level selection */ enum Mipmap { /** - * Select base mip level. + * Select base mip level */ BaseMipLevel = GL_NEAREST & ~GL_NEAREST, /** - * Select nearest mip level. + * Select nearest mip level. Unavailable on rectangle textures. */ NearestMipLevel = GL_NEAREST_MIPMAP_NEAREST & ~GL_NEAREST, /** - * Linear interpolation of nearest mip levels. + * Linear interpolation of nearest mip levels. Unavailable on + * rectangle textures. */ LinearMipInterpolation = GL_NEAREST_MIPMAP_LINEAR & ~GL_NEAREST }; @@ -72,12 +87,12 @@ template class Texture { /** @brief Texture wrapping on the edge */ enum Wrapping { /** - * Repeat texture + * Repeat texture. Unavailable on rectangle textures. */ Repeat = GL_REPEAT, /** - * Repeat mirrored texture + * Repeat mirrored texture. Unavailable on rectangle textures. */ MirroredRepeat = GL_MIRRORED_REPEAT, @@ -114,9 +129,9 @@ template class Texture { /** * @brief Constructor - * @param target Target, e.g. GL_TEXTURE_2D. If not set, target is - * based on dimension count (GL_TEXTURE_1D, GL_TEXTURE_2D, - * GL_TEXTURE_3D). + * @param target Target, e.g. @c GL_TEXTURE_RECTANGLE. If not set, + * target is based on dimension count (@c GL_TEXTURE_1D, + * @c GL_TEXTURE_2D, @c GL_TEXTURE_3D). * * Creates one OpenGL texture. */ @@ -152,20 +167,17 @@ template class Texture { * @brief Set minification filter * @param filter Filter * @param mipmap Mipmap filtering. If set to anything else than - * BaseLevel, make sure textures for all mip levels are set or call - * generateMipmap(). + * BaseMipLevel, make sure textures for all mip levels are set or + * call generateMipmap(). * * Sets filter used when the object pixel size is smaller than the - * texture size. + * texture size. For rectangle textures only some modes are supported, + * see @ref Texture::Filter "Filter" and @ref Texture::Mipmap "Mipmap" + * documentation for more information. * @attention This and setMagnificationFilter() must be called after * creating the texture, otherwise it will be unusable. - * @see generateMipmap() */ - inline void setMinificationFilter(Filter filter, Mipmap mipmap = BaseMipLevel) { - bind(); - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter|mipmap); - unbind(); - } + void setMinificationFilter(Filter filter, Mipmap mipmap = BaseMipLevel); /** * @brief Set magnification filter @@ -186,14 +198,18 @@ template class Texture { * @brief Set wrapping * @param wrapping Wrapping type for all texture dimensions * - * Sets wrapping type for coordinates out of range (-1, 1). + * Sets wrapping type for coordinates out of range (0, 1) for normal + * textures and (0, textureSizeInGivenDirection-1) for rectangle + * textures. Note that for rectangle textures repeating wrapping modes + * are unavailable. */ void setWrapping(const Math::Vector& wrapping); /** * @brief Set border color * - * Border color when wrapping is set to ClampToBorder. + * Border color when @ref Texture::Wrapping "wrapping" is set to + * @c ClampToBorder. */ inline void setBorderColor(const Vector4& color) { bind(); @@ -204,24 +220,22 @@ template class Texture { /** * @brief Generate mipmap * + * Does nothing on rectangle textures. * @see setMinificationFilter() */ - inline void generateMipmap() { - bind(); - glGenerateMipmap(target); - unbind(); - } + void generateMipmap(); protected: /** * @brief Set texture data * @param mipLevel Mip level * @param internalFormat Internal texture format. One value from - * InternalFormat or ColorFormat enum. - * @param _dimensions Texture dimensions + * @ref Texture::InternalFormat "InternalFormat" or + * @ref Texture::ColorFormat "ColorFormat" enum. + * @param _dimensions %Texture dimensions * @param colorFormat Color format of passed data. Data size per * color channel is detected from format of passed data array. - * @param data Texture data. + * @param data %Texture data */ template inline void setData(GLint mipLevel, int internalFormat, const Math::Vector& _dimensions, ColorFormat colorFormat, const T* data) { bind(); @@ -232,26 +246,26 @@ template class Texture { /** * @brief Helper for setting texture data * - * Workaround for partial partial template specialization, see - * http://stackoverflow.com/questions/1757791/c-template-partial-specialization-specializing-one-member-function-only + * Workaround for partial template specialization. */ template struct DataHelper { #ifdef DOXYGEN_GENERATING_OUTPUT /** * @brief Functor - * @param target Target, such as GL_TEXTURE_2D + * @param target Target, such as @c GL_TEXTURE_RECTANGLE * @param mipLevel Mip level * @param internalFormat Internal texture format. One value from - * InternalFormat or ColorFormat enum. - * @param _dimensions Texture dimensions - * @param colorFormat Color format of passed data. Data size per - * color channel is detected from format of passed data array. - * @param data Texture data. + * Texture::InternalFormat or Texture::ColorFormat enum. + * @param _dimensions %Texture dimensions + * @param colorFormat Color format of passed data. Data size + * per color channel is detected from format of passed data + * array. + * @param data %Texture data * - * Calls glTexImage1D, glTexImage2D, glTexImage3D depending on - * dimension count. + * Calls @c glTexImage1D, @c glTexImage2D, @c glTexImage3D depending + * on dimension count. */ - inline void operator()(GLenum target, GLint mipLevel, int internalFormat, const Math::Vector& _dimensions, ColorFormat colorFormat, const T* data); + inline void operator()(GLenum target, GLint mipLevel, int internalFormat, const Math::Vector& _dimensions, ColorFormat colorFormat, const T* data); #endif };