Texture.hh 12.5 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
#include <ACGL/Math/Math.hh>

#include <vector>
Robert Menzel's avatar
Robert Menzel committed
22
#include <tr1/memory>
Robert Menzel's avatar
Robert Menzel committed
23
24

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

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

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

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

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

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

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

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

122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
    //! 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);
        }
    }

143
144
145
146
147
148
149
150
151
    //! _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 );
152
            glBindTexture(mTarget, mObjectName);
153
154
155
156
157
158
159
160
161
162
163
            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;
        }
    }

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

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

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

    //! Set texture data
261
    inline void setImageData2D(const GLvoid* _pData = NULL)
262
    {
263
        glBindTexture(mTarget, mObjectName);
Robert Menzel's avatar
Robert Menzel committed
264
265
266
267
268
269
270
271
272
273
        glTexImage2D(
            mTarget,
            0,
            mInternalFormat,
            mWidth,
            mHeight,
            0,//no border
            mFormat,
            mType,
            _pData);
274
275
276
        if (openGLCriticalErrorOccured() ) {
            ACGL::Utils::error() << "could not generate texture!d" << std::endl;
        }
Robert Menzel's avatar
Robert Menzel committed
277
278
279
280
281
282
    }

    //! 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.
283
        Note: The function is not const, because it changes the corresponding GPU data
Robert Menzel's avatar
Robert Menzel committed
284
     */
285
    inline void setImageDataMipMap2D(
Robert Menzel's avatar
Robert Menzel committed
286
        const GLvoid* _pData,
287
288
289
        GLint         _mipmapLevel,
        GLsizei       _width = 0,
        GLsizei       _height = 0)
Robert Menzel's avatar
Robert Menzel committed
290
    {
291
        glBindTexture(mTarget, mObjectName);
Robert Menzel's avatar
Robert Menzel committed
292
293
294
295
        glTexImage2D(
            mTarget,
            _mipmapLevel,
            mInternalFormat,
296
297
            _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
298
299
300
301
302
            0,//no border
            mFormat,
            mType,
            _pData);
    }
303

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

    //! Set data for specific area within the 3D texture
327
    //! Note: The function is not const, because it changes the corresponding GPU data
328
    inline void setSubImageData3D(
329
330
331
332
333
334
335
336
            const GLvoid* _pData,
            int _x,
            int _y,
            int _z,
            int _width,
            int _height,
            int _depth)
    {
337
        glBindTexture(mTarget, mObjectName);
338
339
340
341
342
343
344
345
346
347
348
        glTexSubImage3D(
            mTarget,
            0,
            _x,
            _y,
            _z,
            _width,
            _height,
            _depth,
            mFormat,
            mType,
349
350
            _pData);
    }
Robert Menzel's avatar
Robert Menzel committed
351
    
352
353
354
    //! 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
355
    {
356
        glBindTexture(mTarget, mObjectName);
Robert Menzel's avatar
Robert Menzel committed
357
#if (!defined ACGL_OPENGL_PROFILE_CORE)
358
        // on some ATI systems texturing has to be enabled to generate MipMaps
Robert Menzel's avatar
Robert Menzel committed
359
360
        // 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
361
        glEnable(mTarget);
Robert Menzel's avatar
Robert Menzel committed
362
363
        openGLRareError();
#endif
364
365
366
367
#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
368
        glGenerateMipmap(mTarget);
369
#endif
370
        openGLRareError();
Robert Menzel's avatar
Robert Menzel committed
371
372
373
374
375
376
    } 

    // =================================================================================================== \/
    // ============================================================================================ FIELDS \/
    // =================================================================================================== \/
private:
377
    GLuint  mObjectName;
378
    GLenum  mTarget;
Robert Menzel's avatar
Robert Menzel committed
379
380
381
382
383
384
    GLsizei mWidth;
    GLsizei mHeight;
    GLsizei mDepth;
    GLenum  mInternalFormat;
    GLenum  mFormat;
    GLenum  mType;
385
386
    GLint   mMinFilter;
    GLint   mMagFilter;
387
388
389
    GLenum  mWrapS;
    GLenum  mWrapT;
    GLenum  mWrapR;
Robert Menzel's avatar
Robert Menzel committed
390
391
};

392
393
ACGL_SHARED_TYPEDEF(Texture)

Robert Menzel's avatar
Robert Menzel committed
394
395

} // OpenGL
Robert Menzel's avatar
Robert Menzel committed
396
397
} // ACGL

398
#endif // ACGL_OPENGL_OBJECTS_TEXTURE_HH