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
    //! 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
141
142

        openGLRareError();
143
144
    }

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

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

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

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

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

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

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

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

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

394
395
ACGL_SHARED_TYPEDEF(Texture)

Robert Menzel's avatar
Robert Menzel committed
396
397

} // OpenGL
Robert Menzel's avatar
Robert Menzel committed
398
399
} // ACGL

400
#endif // ACGL_OPENGL_OBJECTS_TEXTURE_HH