Texture.hh 11.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
49
        mInternalFormat(GL_RGBA),
        mFormat(GL_RGBA),
        mType(GL_UNSIGNED_BYTE),
        mMinFilter(GL_NEAREST_MIPMAP_LINEAR),
        mMagFilter(GL_LINEAR)
Robert Menzel's avatar
Robert Menzel committed
50
    {
51
        glGenTextures(1, &mObjectName);
52
53
54
        if (openGLCriticalErrorOccured() ) {
            ACGL::Utils::error() << "could not generate texture!" << std::endl;
        }
Robert Menzel's avatar
Robert Menzel committed
55
56
57
58
    }

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

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

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

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

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

116
117
118
119
120
121
122
123
124
    //! _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 );
125
            glBindTexture(mTarget, mObjectName);
126
127
128
129
130
131
132
133
134
135
136
            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;
        }
    }

137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
    //! 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
156
        GLsizei _width,
157
158
        GLsizei _height,
        GLsizei _depth)
Robert Menzel's avatar
Robert Menzel committed
159
160
161
162
163
164
165
166
167
168
    {
        mWidth = _width;
        mHeight = _height;
        mDepth = _depth;
        if(mWidth > 0 && mHeight > 0 && mDepth > 0)
        {
            //3D
        }
        else if(mWidth > 0 && mHeight > 0)
        {
169
            setImageData2D(_pData);
Robert Menzel's avatar
Robert Menzel committed
170
171
172
173
174
175
176
        }
        else if(mWidth > 0)
        {
            //1D
        }
    }

177
178
179
    //! Set texture data for 1D, 2D or 3D textures
    inline void setImageData(
        const GLvoid* _pData,
Robert Menzel's avatar
Robert Menzel committed
180
        GLsizei _width,
181
182
183
184
185
        GLsizei _height,
        GLsizei _depth,
        GLenum _internalFormat,
        GLenum _format,
        GLenum _type)
Robert Menzel's avatar
Robert Menzel committed
186
187
188
    {
        mWidth = _width;
        mHeight = _height;
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
        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
208
209
210
211
212
213
214
    inline void setImageData2D(
        const GLvoid* _pData,
        GLsizei _width,
        GLsizei _height,
        GLenum  _internalFormat,
        GLenum  _format,
        GLenum  _type)
215
    {
216
217
218
219
        mInternalFormat = _internalFormat;
        mFormat         = _format;
        mType           = _type;
        setImageData2D( _pData, _width, _height );
Robert Menzel's avatar
Robert Menzel committed
220
221
    }

222
    //! Set texture data
223
224
225
226
    inline void setImageData2D(
        const GLvoid* _pData,
        GLsizei _width,
        GLsizei _height)
Robert Menzel's avatar
Robert Menzel committed
227
    {
228
        mWidth  = _width;
229
        mHeight = _height;
230
        setImageData2D( _pData );
231
232
233
    }

    //! Set texture data
234
    inline void setImageData2D(const GLvoid* _pData = NULL)
235
    {
236
        glBindTexture(mTarget, mObjectName);
Robert Menzel's avatar
Robert Menzel committed
237
238
239
240
241
242
243
244
245
246
        glTexImage2D(
            mTarget,
            0,
            mInternalFormat,
            mWidth,
            mHeight,
            0,//no border
            mFormat,
            mType,
            _pData);
247
248
249
        if (openGLCriticalErrorOccured() ) {
            ACGL::Utils::error() << "could not generate texture!d" << std::endl;
        }
Robert Menzel's avatar
Robert Menzel committed
250
251
252
253
254
255
    }

    //! 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.
256
        Note: The function is not const, because it changes the corresponding GPU data
Robert Menzel's avatar
Robert Menzel committed
257
     */
258
    inline void setImageDataMipMap2D(
Robert Menzel's avatar
Robert Menzel committed
259
        const GLvoid* _pData,
260
261
262
        GLint         _mipmapLevel,
        GLsizei       _width = 0,
        GLsizei       _height = 0)
Robert Menzel's avatar
Robert Menzel committed
263
    {
264
        glBindTexture(mTarget, mObjectName);
Robert Menzel's avatar
Robert Menzel committed
265
266
267
268
        glTexImage2D(
            mTarget,
            _mipmapLevel,
            mInternalFormat,
269
270
            _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
271
272
273
274
275
            0,//no border
            mFormat,
            mType,
            _pData);
    }
276

277
    //! Set data for specific area within the 2D texture
278
    //! Note: The function is not const, because it changes the corresponding GPU data
279
    inline void setSubImageData2D(
280
281
282
283
284
285
            const GLvoid* _pData,
            int _x,
            int _y,
            int _width,
            int _height)
    {
286
        glBindTexture(mTarget, mObjectName);
287
288
289
290
291
292
293
294
        glTexSubImage2D(
            mTarget,
            0,
            _x,
            _y,
            _width,
            _height,
            mFormat,
295
296
297
298
299
            mType,
            _pData);
    }

    //! Set data for specific area within the 3D texture
300
    //! Note: The function is not const, because it changes the corresponding GPU data
301
    inline void setSubImageData3D(
302
303
304
305
306
307
308
309
            const GLvoid* _pData,
            int _x,
            int _y,
            int _z,
            int _width,
            int _height,
            int _depth)
    {
310
        glBindTexture(mTarget, mObjectName);
311
312
313
314
315
316
317
318
319
320
321
        glTexSubImage3D(
            mTarget,
            0,
            _x,
            _y,
            _z,
            _width,
            _height,
            _depth,
            mFormat,
            mType,
322
323
            _pData);
    }
Robert Menzel's avatar
Robert Menzel committed
324
    
325
326
327
    //! 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
328
    {
329
        glBindTexture(mTarget, mObjectName);
Robert Menzel's avatar
Robert Menzel committed
330
#if (!defined ACGL_OPENGL_PROFILE_CORE)
331
        // on some ATI systems texturing has to be enabled to generate MipMaps
Robert Menzel's avatar
Robert Menzel committed
332
333
        // 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
334
        glEnable(mTarget);
Robert Menzel's avatar
Robert Menzel committed
335
336
        openGLRareError();
#endif
337
338
339
340
#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
341
        glGenerateMipmap(mTarget);
342
#endif
343
        openGLRareError();
Robert Menzel's avatar
Robert Menzel committed
344
345
346
347
348
349
    } 

    // =================================================================================================== \/
    // ============================================================================================ FIELDS \/
    // =================================================================================================== \/
private:
350
    GLuint  mObjectName;
351
    GLenum  mTarget;
Robert Menzel's avatar
Robert Menzel committed
352
353
354
355
356
357
    GLsizei mWidth;
    GLsizei mHeight;
    GLsizei mDepth;
    GLenum  mInternalFormat;
    GLenum  mFormat;
    GLenum  mType;
358
359
    GLint   mMinFilter;
    GLint   mMagFilter;
Robert Menzel's avatar
Robert Menzel committed
360
361
};

362
363
ACGL_SHARED_TYPEDEF(Texture)

Robert Menzel's avatar
Robert Menzel committed
364
365

} // OpenGL
Robert Menzel's avatar
Robert Menzel committed
366
367
} // ACGL

368
#endif // ACGL_OPENGL_OBJECTS_TEXTURE_HH