Texture.hh 15.6 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
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
70
    inline GLuint  operator()        (void) const { return mObjectName;     }
    inline GLuint  getObjectName     (void) const { return mObjectName;     }
71
    inline GLenum  getTarget         (void) const { return mTarget;         }
Robert Menzel's avatar
Robert Menzel committed
72
73
74
75
76
77
    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;           }
78
79
    inline GLint   getMinFilter      (void) const { return mMinFilter;      }
    inline GLint   getMagFilter      (void) const { return mMagFilter;      }
80
81
82
    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
83
84
85
86
87
88
89
90
91

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

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

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

121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
    //! Note: The function is not const, because it changes the corresponding GPU data
    inline void setWrap(GLenum _wrapS, GLenum _wrapT = 0, GLenum _wrapR = 0)
    {
        glBindTexture(mTarget, mObjectName);

        mWrapS = _wrapS;
        glTexParameteri(mTarget, GL_TEXTURE_WRAP_S, mWrapS);

        if(_wrapT != 0)
        {
            mWrapT = _wrapT;
            glTexParameteri(mTarget, GL_TEXTURE_WRAP_T, mWrapT);
        }

        if(_wrapR != 0)
        {
            mWrapR = _wrapR;
            glTexParameteri(mTarget, GL_TEXTURE_WRAP_R, mWrapR);
        }
Janis Born's avatar
Janis Born committed
140
141

        openGLRareError();
142
143
    }

144
145
146
147
148
149
150
151
152
    //! _sampleCount = 1.0 to deactivate anisotrop filtering, maximum is often 16. If a value is too high it will get clamped to the maximum
    void setAnisotropicFilter( GLfloat _sampleCount )
    {
#ifdef ACGL_USE_GLEW
        if (GLEW_EXT_texture_filter_anisotropic) {
            GLfloat maxAnisotropicSamples;
            glGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropicSamples );
            _sampleCount = std::max( 1.0f, _sampleCount );
            _sampleCount = std::min( maxAnisotropicSamples, _sampleCount );
153
            glBindTexture(mTarget, mObjectName);
154
155
156
157
158
159
160
161
162
163
164
            glTexParameterf( mTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, _sampleCount);
            openGLRareError();
        } else
#endif
        {
            // anisotropic filtering will just increase the image quality, so this is just
            // a warning and no error
            ACGL::Utils::warning() << "Anisotropic filtering is not supported, ignored" << std::endl;
        }
    }

165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
    //! 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
184
        GLsizei _width,
185
186
        GLsizei _height,
        GLsizei _depth)
Robert Menzel's avatar
Robert Menzel committed
187
188
189
190
191
192
193
194
195
196
    {
        mWidth = _width;
        mHeight = _height;
        mDepth = _depth;
        if(mWidth > 0 && mHeight > 0 && mDepth > 0)
        {
            //3D
        }
        else if(mWidth > 0 && mHeight > 0)
        {
197
            setImageData2D(_pData);
Robert Menzel's avatar
Robert Menzel committed
198
199
200
201
202
203
204
        }
        else if(mWidth > 0)
        {
            //1D
        }
    }

205
206
207
    //! Set texture data for 1D, 2D or 3D textures
    inline void setImageData(
        const GLvoid* _pData,
Robert Menzel's avatar
Robert Menzel committed
208
        GLsizei _width,
209
210
211
212
213
        GLsizei _height,
        GLsizei _depth,
        GLenum _internalFormat,
        GLenum _format,
        GLenum _type)
Robert Menzel's avatar
Robert Menzel committed
214
215
216
    {
        mWidth = _width;
        mHeight = _height;
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
        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
236
237
238
239
240
241
242
    inline void setImageData2D(
        const GLvoid* _pData,
        GLsizei _width,
        GLsizei _height,
        GLenum  _internalFormat,
        GLenum  _format,
        GLenum  _type)
243
    {
244
245
246
247
        mInternalFormat = _internalFormat;
        mFormat         = _format;
        mType           = _type;
        setImageData2D( _pData, _width, _height );
Robert Menzel's avatar
Robert Menzel committed
248
249
    }

250
    //! Set texture data
251
252
253
254
    inline void setImageData2D(
        const GLvoid* _pData,
        GLsizei _width,
        GLsizei _height)
Robert Menzel's avatar
Robert Menzel committed
255
    {
256
        mWidth  = _width;
257
        mHeight = _height;
258
        setImageData2D( _pData );
259
260
    }

261
    //! Set texture data using the specified target for uploading the data
262
    inline void setImageData2D(const GLvoid* _pData = NULL)
263
    {
264
        setImageData2D(mTarget, mFormat, mType, _pData);
Robert Menzel's avatar
Robert Menzel committed
265
266
    }

267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
    //! 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
313
314
315
316
    //! 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.
317
        Note: The function is not const, because it changes the corresponding GPU data
Robert Menzel's avatar
Robert Menzel committed
318
     */
319
    inline void setImageDataMipMap2D(
Robert Menzel's avatar
Robert Menzel committed
320
        const GLvoid* _pData,
321
322
323
        GLint         _mipmapLevel,
        GLsizei       _width = 0,
        GLsizei       _height = 0)
Robert Menzel's avatar
Robert Menzel committed
324
    {
325
        glBindTexture(mTarget, mObjectName);
Robert Menzel's avatar
Robert Menzel committed
326
327
328
329
        glTexImage2D(
            mTarget,
            _mipmapLevel,
            mInternalFormat,
330
331
            _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
332
333
334
335
336
            0,//no border
            mFormat,
            mType,
            _pData);
    }
337

338
    //! Set data for specific area within the 2D texture
339
    //! Note: The function is not const, because it changes the corresponding GPU data
340
    inline void setSubImageData2D(
341
            const GLvoid* _pData,
342
343
344
345
            GLint _x,
            GLint _y,
            GLsizei _width,
            GLsizei _height)
346
    {
347
        glBindTexture(mTarget, mObjectName);
348
349
350
351
352
353
354
355
        glTexSubImage2D(
            mTarget,
            0,
            _x,
            _y,
            _width,
            _height,
            mFormat,
356
357
358
359
360
            mType,
            _pData);
    }

    //! Set data for specific area within the 3D texture
361
    //! Note: The function is not const, because it changes the corresponding GPU data
362
    inline void setSubImageData3D(
363
            const GLvoid* _pData,
364
365
366
367
368
369
            GLint _x,
            GLint _y,
            GLint _z,
            GLsizei _width,
            GLsizei _height,
            GLsizei _depth)
370
    {
371
        glBindTexture(mTarget, mObjectName);
372
373
374
375
376
377
378
379
380
381
382
        glTexSubImage3D(
            mTarget,
            0,
            _x,
            _y,
            _z,
            _width,
            _height,
            _depth,
            mFormat,
            mType,
383
384
            _pData);
    }
Robert Menzel's avatar
Robert Menzel committed
385
    
386
387
388
    //! 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
389
    {
390
        glBindTexture(mTarget, mObjectName);
Robert Menzel's avatar
Robert Menzel committed
391
#if (!defined ACGL_OPENGL_PROFILE_CORE)
392
        // on some ATI systems texturing has to be enabled to generate MipMaps
Robert Menzel's avatar
Robert Menzel committed
393
394
        // 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
395
        glEnable(mTarget);
Robert Menzel's avatar
Robert Menzel committed
396
397
        openGLRareError();
#endif
398
399
400
401
#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
402
        glGenerateMipmap(mTarget);
403
#endif
404
        openGLRareError();
Robert Menzel's avatar
Robert Menzel committed
405
406
    } 

407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
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
427
428
429
430
    // =================================================================================================== \/
    // ============================================================================================ FIELDS \/
    // =================================================================================================== \/
private:
431
    GLuint  mObjectName;
432
    GLenum  mTarget;
Robert Menzel's avatar
Robert Menzel committed
433
434
435
436
437
438
    GLsizei mWidth;
    GLsizei mHeight;
    GLsizei mDepth;
    GLenum  mInternalFormat;
    GLenum  mFormat;
    GLenum  mType;
439
440
    GLint   mMinFilter;
    GLint   mMagFilter;
441
442
443
    GLenum  mWrapS;
    GLenum  mWrapT;
    GLenum  mWrapR;
Robert Menzel's avatar
Robert Menzel committed
444
445
};

446
447
ACGL_SHARED_TYPEDEF(Texture)

Robert Menzel's avatar
Robert Menzel committed
448
449

} // OpenGL
Robert Menzel's avatar
Robert Menzel committed
450
451
} // ACGL

452
#endif // ACGL_OPENGL_OBJECTS_TEXTURE_HH