Texture.hh 14.4 KB
Newer Older
Robert Menzel's avatar
Robert Menzel committed
1 2 3 4 5
////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2011, Computer Graphics Group RWTH Aachen University         //
// All rights reserved.                                                       //
////////////////////////////////////////////////////////////////////////////////

6 7
#ifndef ACGL_OPENGL_OBJECTS_TEXTURE_HH
#define ACGL_OPENGL_OBJECTS_TEXTURE_HH
Robert Menzel's avatar
Robert Menzel committed
8

Robert Menzel's avatar
Robert Menzel committed
9
/**
Robert Menzel's avatar
Robert Menzel committed
10 11 12 13
 * A Texture wrapps the OpenGL texture. To fill these with data from image files a
 * matching TextureControllerFile* is needed.
 */

Robert Menzel's avatar
Robert Menzel committed
14 15
#include <ACGL/ACGL.hh>

16
#include <ACGL/Base/Macros.hh>
Robert Menzel's avatar
Robert Menzel committed
17 18
#include <ACGL/OpenGL/GL.hh>
#include <ACGL/OpenGL/Tools.hh>
Robert Menzel's avatar
Robert Menzel committed
19 20 21 22 23
#include <ACGL/Math/Math.hh>

#include <vector>

namespace ACGL{
Robert Menzel's avatar
Robert Menzel committed
24
namespace OpenGL{
Robert Menzel's avatar
Robert Menzel committed
25 26 27

class Texture
{
28
    ACGL_NOT_COPYABLE(Texture)
Robert Menzel's avatar
Robert Menzel committed
29 30 31 32 33

    // ========================================================================================================= \/
    // ============================================================================================ CONSTRUCTORS \/
    // ========================================================================================================= \/
public:
34 35 36 37 38
    //!
    /*!
        Default texture parameters taken from: http://www.opengl.org/sdk/docs/man/xhtml/glTexParameter.xml
     */
    Texture(GLenum _target)
39
    :   mObjectName(0),
40
        mTarget(_target),
Robert Menzel's avatar
Robert Menzel committed
41 42 43
        mWidth(0),
        mHeight(0),
        mDepth(0),
44 45 46 47
        mInternalFormat(GL_RGBA),
        mFormat(GL_RGBA),
        mType(GL_UNSIGNED_BYTE),
        mMinFilter(GL_NEAREST_MIPMAP_LINEAR),
48 49 50 51
        mMagFilter(GL_LINEAR),
        mWrapS(GL_REPEAT),
        mWrapT(GL_REPEAT),
        mWrapR(GL_REPEAT)
Robert Menzel's avatar
Robert Menzel committed
52
    {
53
        glGenTextures(1, &mObjectName);
54 55 56
        if (openGLCriticalErrorOccured() ) {
            ACGL::Utils::error() << "could not generate texture!" << std::endl;
        }
Robert Menzel's avatar
Robert Menzel committed
57 58 59 60
    }

    virtual ~Texture(void)
    {
61 62
        // object name 0 will get ignored by OpenGL
        glDeleteTextures(1, &mObjectName);
Robert Menzel's avatar
Robert Menzel committed
63 64 65 66 67 68
    }

    // ==================================================================================================== \/
    // ============================================================================================ GETTERS \/
    // ==================================================================================================== \/
public:
69
    inline GLuint  getObjectName     (void) const { return mObjectName;     }
70
    inline GLenum  getTarget         (void) const { return mTarget;         }
Robert Menzel's avatar
Robert Menzel committed
71 72 73 74 75 76
    inline GLsizei getWidth          (void) const { return mWidth;          }
    inline GLsizei getHeight         (void) const { return mHeight;         }
    inline GLsizei getDepth          (void) const { return mDepth;          }
    inline GLenum  getInternalFormat (void) const { return mInternalFormat; }
    inline GLenum  getFormat         (void) const { return mFormat;         }
    inline GLenum  getType           (void) const { return mType;           }
77 78
    inline GLint   getMinFilter      (void) const { return mMinFilter;      }
    inline GLint   getMagFilter      (void) const { return mMagFilter;      }
79 80 81
    inline GLenum  getWrapS          (void) const { return mWrapS;          }
    inline GLenum  getWrapT          (void) const { return mWrapT;          }
    inline GLenum  getWrapR          (void) const { return mWrapR;          }
Robert Menzel's avatar
Robert Menzel committed
82 83 84 85 86 87

    // ===================================================================================================== \/
    // ============================================================================================ WRAPPERS \/
    // ===================================================================================================== \/
public:
    //! Activate texture unit and bind this texture.
88
    inline void bind(GLuint _textureUnit) const
Robert Menzel's avatar
Robert Menzel committed
89 90
    {
        glActiveTexture(GL_TEXTURE0 + _textureUnit);
91
        glBindTexture(mTarget, mObjectName);
92
        openGLRareError();
Robert Menzel's avatar
Robert Menzel committed
93 94 95 96 97
    }
    
    //! Bind this texture.
    inline void bind(void) const
    {
98
        glBindTexture(mTarget, mObjectName);
99
        openGLRareError();
Robert Menzel's avatar
Robert Menzel committed
100 101
    }

102
    //! Note: The function is not const, because it changes the corresponding GPU data
103
    inline void setMinFilter(GLint _value)
Robert Menzel's avatar
Robert Menzel committed
104
    {
105
        mMinFilter = _value;
106
        glBindTexture(mTarget, mObjectName);
107
        glTexParameteri(mTarget, GL_TEXTURE_MIN_FILTER, mMinFilter);
108
        openGLRareError();
Robert Menzel's avatar
Robert Menzel committed
109 110
    }

111
    //! Note: The function is not const, because it changes the corresponding GPU data
112
    inline void setMagFilter(GLint _value)
Robert Menzel's avatar
Robert Menzel committed
113
    {
114
        mMagFilter = _value;
115
        glBindTexture(mTarget, mObjectName);
116
        glTexParameteri(mTarget, GL_TEXTURE_MAG_FILTER, mMagFilter);
117
        openGLRareError();
Robert Menzel's avatar
Robert Menzel committed
118 119
    }

120 121 122 123
	void setWrapS( GLenum _wrapS = GL_REPEAT );
	void setWrapT( GLenum _wrapT = GL_REPEAT );
	void setWrapR( GLenum _wrapR = GL_REPEAT );

124
    //! Note: The function is not const, because it changes the corresponding GPU data
Robert Menzel's avatar
Robert Menzel committed
125
    void setWrap(GLenum _wrapS, GLenum _wrapT = 0, GLenum _wrapR = 0);
126

127
    //! _sampleCount = 1.0 to deactivate anisotrop filtering, maximum is often 16. If a value is too high it will get clamped to the maximum
Robert Menzel's avatar
Robert Menzel committed
128
    void setAnisotropicFilter( GLfloat _sampleCount );
129

130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
    //! Set texture data for 1D, 2D or 3D textures
    inline void setImageData(const GLvoid* _pData = NULL)
    {
        if(mWidth > 0 && mHeight > 0 && mDepth > 0)
        {
            //3D
        }
        else if(mWidth > 0 && mHeight > 0)
        {
            setImageData2D(_pData);
        }
        else if(mWidth > 0)
        {
            //1D
        }
    }
    //! Set texture data for 1D, 2D or 3D textures
    inline void setImageData(
        const GLvoid* _pData,
Robert Menzel's avatar
Robert Menzel committed
149
        GLsizei _width,
150 151
        GLsizei _height,
        GLsizei _depth)
Robert Menzel's avatar
Robert Menzel committed
152 153 154 155 156 157 158 159 160 161
    {
        mWidth = _width;
        mHeight = _height;
        mDepth = _depth;
        if(mWidth > 0 && mHeight > 0 && mDepth > 0)
        {
            //3D
        }
        else if(mWidth > 0 && mHeight > 0)
        {
162
            setImageData2D(_pData);
Robert Menzel's avatar
Robert Menzel committed
163 164 165 166 167 168 169
        }
        else if(mWidth > 0)
        {
            //1D
        }
    }

170 171 172
    //! Set texture data for 1D, 2D or 3D textures
    inline void setImageData(
        const GLvoid* _pData,
Robert Menzel's avatar
Robert Menzel committed
173
        GLsizei _width,
174 175 176 177 178
        GLsizei _height,
        GLsizei _depth,
        GLenum _internalFormat,
        GLenum _format,
        GLenum _type)
Robert Menzel's avatar
Robert Menzel committed
179 180 181
    {
        mWidth = _width;
        mHeight = _height;
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
        mDepth = _depth;
        mInternalFormat = _internalFormat;
        mFormat = _format;
        mType = _type;
        if(mWidth > 0 && mHeight > 0 && mDepth > 0)
        {
            //3D
        }
        else if(mWidth > 0 && mHeight > 0)
        {
            setImageData2D(_pData);
        }
        else if(mWidth > 0)
        {
            //1D
        }
    }

    //! Set texture data
201 202 203 204 205 206 207
    inline void setImageData2D(
        const GLvoid* _pData,
        GLsizei _width,
        GLsizei _height,
        GLenum  _internalFormat,
        GLenum  _format,
        GLenum  _type)
208
    {
209 210 211 212
        mInternalFormat = _internalFormat;
        mFormat         = _format;
        mType           = _type;
        setImageData2D( _pData, _width, _height );
Robert Menzel's avatar
Robert Menzel committed
213 214
    }

215
    //! Set texture data
216 217 218 219
    inline void setImageData2D(
        const GLvoid* _pData,
        GLsizei _width,
        GLsizei _height)
Robert Menzel's avatar
Robert Menzel committed
220
    {
221
        mWidth  = _width;
222
        mHeight = _height;
223
        setImageData2D( _pData );
224 225
    }

226
    //! Set texture data using the specified target for uploading the data
227
    inline void setImageData2D(const GLvoid* _pData = NULL)
228
    {
229
        setImageData2D(mTarget, mFormat, mType, _pData);
Robert Menzel's avatar
Robert Menzel committed
230 231
    }

232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
    //! Set format for the cube maps that are uploaded
    inline void setCubeMapFormat(
        GLsizei _size,
        GLenum _internalFormat)
    {
        mWidth = _size;
        mHeight = _size;
        mDepth = 0;
        mInternalFormat = _internalFormat;
    }

    //! Set format for the cube maps that are uploaded including a default format and type
    inline void setCubeMapFormat(
        GLsizei _size,
        GLenum _internalFormat,
        GLenum _format,
        GLenum _type)
    {
        mWidth = _size;
        mHeight = _size;
        mDepth = 0;
        mInternalFormat = _internalFormat;
        mFormat = _format;
        mType = _type;
    }

    //! Set texture data for cube maps using the default format and type
    /// @{
    inline void setImageDataCubeMapPositiveX(const GLvoid* _pData = NULL) { setImageData2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, mFormat, mType, _pData); }
    inline void setImageDataCubeMapNegativeX(const GLvoid* _pData = NULL) { setImageData2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, mFormat, mType, _pData); }
    inline void setImageDataCubeMapPositiveY(const GLvoid* _pData = NULL) { setImageData2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, mFormat, mType, _pData); }
    inline void setImageDataCubeMapNegativeY(const GLvoid* _pData = NULL) { setImageData2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, mFormat, mType, _pData); }
    inline void setImageDataCubeMapPositiveZ(const GLvoid* _pData = NULL) { setImageData2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, mFormat, mType, _pData); }
    inline void setImageDataCubeMapNegativeZ(const GLvoid* _pData = NULL) { setImageData2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, mFormat, mType, _pData); }
    /// @}

    //! Set texture data for cube maps using a specific upload format and type per face
    /// @{
    inline void setImageDataCubeMapPositiveX(GLenum _format, GLenum _type, const GLvoid* _pData = NULL) { setImageData2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, _format, _type, _pData); }
    inline void setImageDataCubeMapNegativeX(GLenum _format, GLenum _type, const GLvoid* _pData = NULL) { setImageData2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, _format, _type, _pData); }
    inline void setImageDataCubeMapPositiveY(GLenum _format, GLenum _type, const GLvoid* _pData = NULL) { setImageData2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, _format, _type, _pData); }
    inline void setImageDataCubeMapNegativeY(GLenum _format, GLenum _type, const GLvoid* _pData = NULL) { setImageData2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, _format, _type, _pData); }
    inline void setImageDataCubeMapPositiveZ(GLenum _format, GLenum _type, const GLvoid* _pData = NULL) { setImageData2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, _format, _type, _pData); }
    inline void setImageDataCubeMapNegativeZ(GLenum _format, GLenum _type, const GLvoid* _pData = NULL) { setImageData2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, _format, _type, _pData); }
    /// @}

Robert Menzel's avatar
Robert Menzel committed
278 279 280 281
    //! Set texture data for some mipmap level.
    /*!
        If you upload a texture for a higher mipmap level, the function will automatically determine
        its size calculating (w,h)/2^level where w and h are the width and height of the base texture.
282
        Note: The function is not const, because it changes the corresponding GPU data
Robert Menzel's avatar
Robert Menzel committed
283
     */
284
    inline void setImageDataMipMap2D(
Robert Menzel's avatar
Robert Menzel committed
285
        const GLvoid* _pData,
286 287 288
        GLint         _mipmapLevel,
        GLsizei       _width = 0,
        GLsizei       _height = 0)
Robert Menzel's avatar
Robert Menzel committed
289
    {
290
        glBindTexture(mTarget, mObjectName);
Robert Menzel's avatar
Robert Menzel committed
291 292 293 294
        glTexImage2D(
            mTarget,
            _mipmapLevel,
            mInternalFormat,
295 296
            _width > 0 ? _width : mWidth  / GLsizei(Math::Functions::pow(2.0f, float(_mipmapLevel))),
            _height > 0 ? _height : mHeight / GLsizei(Math::Functions::pow(2.0f, float(_mipmapLevel))),
Robert Menzel's avatar
Robert Menzel committed
297 298 299 300 301
            0,//no border
            mFormat,
            mType,
            _pData);
    }
302

303
    //! Set data for specific area within the 2D texture
304
    //! Note: The function is not const, because it changes the corresponding GPU data
305
    inline void setSubImageData2D(
306
            const GLvoid* _pData,
307 308 309 310
            GLint _x,
            GLint _y,
            GLsizei _width,
            GLsizei _height)
311
    {
312
        glBindTexture(mTarget, mObjectName);
313 314 315 316 317 318 319 320
        glTexSubImage2D(
            mTarget,
            0,
            _x,
            _y,
            _width,
            _height,
            mFormat,
321 322 323 324 325
            mType,
            _pData);
    }

    //! Set data for specific area within the 3D texture
326
    //! Note: The function is not const, because it changes the corresponding GPU data
327
    inline void setSubImageData3D(
328
            const GLvoid* _pData,
329 330 331 332 333 334
            GLint _x,
            GLint _y,
            GLint _z,
            GLsizei _width,
            GLsizei _height,
            GLsizei _depth)
335
    {
336
        glBindTexture(mTarget, mObjectName);
337 338 339 340 341 342 343 344 345 346 347
        glTexSubImage3D(
            mTarget,
            0,
            _x,
            _y,
            _z,
            _width,
            _height,
            _depth,
            mFormat,
            mType,
348 349
            _pData);
    }
Robert Menzel's avatar
Robert Menzel committed
350
    
351 352 353
    //! Generate mipmaps from the current base texture (i.e. the texture from level 0)
    //! Note: The function is not const, because it changes the corresponding GPU data
    void generateMipmaps(void)
Robert Menzel's avatar
Robert Menzel committed
354
    {
355
        glBindTexture(mTarget, mObjectName);
Robert Menzel's avatar
Robert Menzel committed
356
#if (!defined ACGL_OPENGL_PROFILE_CORE)
357
        // on some ATI systems texturing has to be enabled to generate MipMaps
Robert Menzel's avatar
Robert Menzel committed
358 359
        // this is not needed by the spec an deprecated on core profiles (generates
        // an error on MacOS X Lion)
Robert Menzel's avatar
Robert Menzel committed
360
        glEnable(mTarget);
Robert Menzel's avatar
Robert Menzel committed
361 362
        openGLRareError();
#endif
363 364 365 366
#ifdef ACGL_OPENGL_VERSION_21
        // OpenGL 2 way to generate MipMaps
        glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
#else
Robert Menzel's avatar
Robert Menzel committed
367
        glGenerateMipmap(mTarget);
368
#endif
369
        openGLRareError();
Robert Menzel's avatar
Robert Menzel committed
370 371
    } 

372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
private:
    //! Set texture data
    inline void setImageData2D(GLenum _uploadTarget, GLenum _uploadFormat, GLenum _uploadType, const GLvoid* _pData = NULL)
    {
        glBindTexture(mTarget, mObjectName);
        glTexImage2D(
            _uploadTarget,
            0,
            mInternalFormat,
            mWidth,
            mHeight,
            0,//no border
            _uploadFormat,
            _uploadType,
            _pData);
        if (openGLCriticalErrorOccured() ) {
            ACGL::Utils::error() << "could not generate texture!" << std::endl;
        }
    }

Robert Menzel's avatar
Robert Menzel committed
392 393 394 395
    // =================================================================================================== \/
    // ============================================================================================ FIELDS \/
    // =================================================================================================== \/
private:
396
    GLuint  mObjectName;
397
    GLenum  mTarget;
Robert Menzel's avatar
Robert Menzel committed
398 399 400 401 402 403
    GLsizei mWidth;
    GLsizei mHeight;
    GLsizei mDepth;
    GLenum  mInternalFormat;
    GLenum  mFormat;
    GLenum  mType;
404 405
    GLint   mMinFilter;
    GLint   mMagFilter;
406 407 408
    GLenum  mWrapS;
    GLenum  mWrapT;
    GLenum  mWrapR;
Robert Menzel's avatar
Robert Menzel committed
409 410
};

Robert Menzel's avatar
Robert Menzel committed
411
ACGL_SMARTPOINTER_TYPEDEFS(Texture)
412

Robert Menzel's avatar
Robert Menzel committed
413 414

} // OpenGL
Robert Menzel's avatar
Robert Menzel committed
415 416
} // ACGL

417
#endif // ACGL_OPENGL_OBJECTS_TEXTURE_HH