Texture.cc 11.3 KB
Newer Older
1 2 3 4 5
/***********************************************************************
 * Copyright 2011-2012 Computer Graphics Group RWTH Aachen University. *
 * All rights reserved.                                                *
 * Distributed under the terms of the MIT License (see LICENSE.TXT).   *
 **********************************************************************/
Robert Menzel's avatar
Robert Menzel committed
6

Robert Menzel's avatar
Robert Menzel committed
7
#include <ACGL/OpenGL/Objects/Texture.hh>
8
#include <ACGL/OpenGL/glloaders/extensions.hh> // for anisotrophic filtering
Robert Menzel's avatar
Robert Menzel committed
9

Robert Menzel's avatar
Robert Menzel committed
10
using namespace ACGL::OpenGL;
Robert Menzel's avatar
Robert Menzel committed
11

12 13 14 15 16 17 18 19 20 21 22 23 24 25
void TextureBase::setMinFilter(GLint _value)
{
    GLuint prevTexture = bindAndGetOldTexture();
    glTexParameteri(mTarget, GL_TEXTURE_MIN_FILTER, _value);
    glBindTexture(mTarget, prevTexture);
}

void TextureBase::setMagFilter(GLint _value)
{
    GLuint prevTexture = bindAndGetOldTexture();
    glTexParameteri(mTarget, GL_TEXTURE_MAG_FILTER, _value);
    glBindTexture(mTarget, prevTexture);
}

26
#ifndef ACGL_OPENGLES_VERSION_20
Robert Menzel's avatar
Robert Menzel committed
27
void TextureBase::setWrapS( GLenum _wrapS )
28
{
29 30 31
    GLuint prevTexture = bindAndGetOldTexture();
    glTexParameteri(mTarget, GL_TEXTURE_WRAP_S, _wrapS);
    glBindTexture(mTarget, prevTexture);
32 33
}

Robert Menzel's avatar
Robert Menzel committed
34
void TextureBase::setWrapT( GLenum _wrapT )
35
{
36 37 38
    GLuint prevTexture = bindAndGetOldTexture();
    glTexParameteri(mTarget, GL_TEXTURE_WRAP_T, _wrapT);
    glBindTexture(mTarget, prevTexture);
39 40
}

Robert Menzel's avatar
Robert Menzel committed
41
void TextureBase::setWrapR( GLenum _wrapR )
42
{
43 44 45
    GLuint prevTexture = bindAndGetOldTexture();
    glTexParameteri(mTarget, GL_TEXTURE_WRAP_R, _wrapR);
    glBindTexture(mTarget, prevTexture);
46 47
}

Robert Menzel's avatar
Robert Menzel committed
48
void TextureBase::setWrap( GLenum _wrapS, GLenum _wrapT, GLenum _wrapR )
Robert Menzel's avatar
Robert Menzel committed
49
{
50
    setWrapS(_wrapS);
Robert Menzel's avatar
Robert Menzel committed
51 52 53

    if(_wrapT != 0)
    {
54
        setWrapT(_wrapT);
Robert Menzel's avatar
Robert Menzel committed
55 56 57 58
    }

    if(_wrapR != 0)
    {
59
        setWrapR(_wrapR);
Robert Menzel's avatar
Robert Menzel committed
60 61
    }
}
62
#endif // ACGL_OPENGLES_VERSION_20
Robert Menzel's avatar
Robert Menzel committed
63

64 65
void TextureBase::setMinLOD(  GLint _lod )
{
66
    GLuint prevTexture = bindAndGetOldTexture();
67
    glTexParameteri( mTarget, GL_TEXTURE_MIN_LOD, _lod);
68
    glBindTexture(mTarget, prevTexture);
69 70 71 72
}

void TextureBase::setMaxLOD(  GLint _lod )
{
73
    GLuint prevTexture = bindAndGetOldTexture();
74
    glTexParameteri( mTarget, GL_TEXTURE_MAX_LOD, _lod);
75
    glBindTexture(mTarget, prevTexture);
76 77 78 79
}

void TextureBase::setLODBias( GLfloat _bias )
{
80
    GLuint prevTexture = bindAndGetOldTexture();
81
    glTexParameterf( mTarget, GL_TEXTURE_LOD_BIAS, _bias);
82
    glBindTexture(mTarget, prevTexture);
83 84 85 86
}

void TextureBase::setCompareMode( GLenum _mode )
{
87
    GLuint prevTexture = bindAndGetOldTexture();
88
    glTexParameteri( mTarget, GL_TEXTURE_COMPARE_MODE, _mode);
89
    glBindTexture(mTarget, prevTexture);
90 91 92 93
}

void TextureBase::setCompareFunc( GLenum _func )
{
94
    GLuint prevTexture = bindAndGetOldTexture();
95
    glTexParameteri( mTarget, GL_TEXTURE_COMPARE_FUNC, _func);
96
    glBindTexture(mTarget, prevTexture);
97 98 99
}


Robert Menzel's avatar
Robert Menzel committed
100
void TextureBase::setAnisotropicFilter( GLfloat _sampleCount )
Robert Menzel's avatar
Robert Menzel committed
101
{
102
    if ( ACGL_EXT_texture_filter_anisotrophic() ) {
Robert Menzel's avatar
Robert Menzel committed
103
        // anisotrophic filtering is supported:
104 105
        GLuint prevTexture = bindAndGetOldTexture();

106 107
        _sampleCount = std::max( _sampleCount, 1.0f );
        _sampleCount = std::min( _sampleCount, ACGL_MAX_TEXTURE_MAX_ANISOTROPY );
Robert Menzel's avatar
Robert Menzel committed
108
        glTexParameterf( mTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, _sampleCount );
109 110

        glBindTexture(mTarget, prevTexture);
Robert Menzel's avatar
Robert Menzel committed
111 112 113
        openGLRareError();
    } else
    {
Robert Menzel's avatar
Robert Menzel committed
114 115 116 117 118 119
        if (_sampleCount != 1.0f ) {
            // anisotropic filtering will just increase the image quality, so this is just
            // a warning and no error, 1 sample is equal to no anisotrophic filtering, so ignore
            // that case entirely!
            ACGL::Utils::warning() << "Anisotropic filtering is not supported, ignored" << std::endl;
        }
Robert Menzel's avatar
Robert Menzel committed
120 121
    }
}
Janis Born's avatar
Janis Born committed
122

Robert Menzel's avatar
Robert Menzel committed
123 124
void TextureBase::generateMipmaps(void)
{
125 126
    GLuint prevTexture = bindAndGetOldTexture();

Robert Menzel's avatar
Robert Menzel committed
127 128 129 130 131 132 133 134 135 136 137 138 139
#if (!defined ACGL_OPENGL_PROFILE_CORE)
    // on some ATI systems texturing has to be enabled to generate MipMaps
    // this is not needed by the spec an deprecated on core profiles (generates
    // an error on MacOS X Lion)
    glEnable(mTarget);
    openGLRareError();
#endif
#ifdef ACGL_OPENGL_VERSION_21
    // OpenGL 2 way to generate MipMaps
    glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
#else
    glGenerateMipmap(mTarget);
#endif
140 141

    glBindTexture(mTarget, prevTexture);
Robert Menzel's avatar
Robert Menzel committed
142 143 144
    openGLRareError();
}

145 146 147 148 149 150
GLint   TextureBase::getParameterI( GLenum _name ) const
{
    GLuint prevTexture = bindAndGetOldTexture();
    GLint param;
    glGetTexParameteriv( mTarget, _name, &param );
    glBindTexture(mTarget, prevTexture);
151
    openGLRareError();
152 153 154 155 156 157 158 159 160
    return param;
}

GLfloat TextureBase::getParameterF( GLenum _name ) const
{
    GLuint prevTexture = bindAndGetOldTexture();
    GLfloat param;
    glGetTexParameterfv( mTarget, _name, &param );
    glBindTexture(mTarget, prevTexture);
161
    openGLRareError();
162 163 164 165 166 167 168
    return param;
}

GLuint TextureBase::bindAndGetOldTexture() const
{
    GLint prevTexture = 0;

169 170 171 172 173 174 175 176 177 178 179
    if     (mTarget == GL_TEXTURE_1D)                   glGetIntegerv(GL_TEXTURE_BINDING_1D,                   &prevTexture);
    else if(mTarget == GL_TEXTURE_2D)                   glGetIntegerv(GL_TEXTURE_BINDING_2D,                   &prevTexture);
    else if(mTarget == GL_TEXTURE_3D)                   glGetIntegerv(GL_TEXTURE_BINDING_3D,                   &prevTexture);
    else if(mTarget == GL_TEXTURE_1D_ARRAY)             glGetIntegerv(GL_TEXTURE_BINDING_1D_ARRAY,             &prevTexture);
    else if(mTarget == GL_TEXTURE_2D_ARRAY)             glGetIntegerv(GL_TEXTURE_BINDING_2D_ARRAY,             &prevTexture);
    else if(mTarget == GL_TEXTURE_RECTANGLE)            glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE,            &prevTexture);
    else if(mTarget == GL_TEXTURE_2D_MULTISAMPLE)       glGetIntegerv(GL_TEXTURE_BINDING_2D_MULTISAMPLE,       &prevTexture);
    else if(mTarget == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) glGetIntegerv(GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY, &prevTexture);
    else if(mTarget == GL_TEXTURE_CUBE_MAP)             glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP,             &prevTexture);
    else if(mTarget == GL_TEXTURE_CUBE_MAP_ARRAY)       glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP_ARRAY,       &prevTexture);
    else if(mTarget == GL_TEXTURE_BUFFER)               glGetIntegerv(GL_TEXTURE_BINDING_BUFFER,               &prevTexture);
180 181 182 183 184 185 186 187 188
    else {
        ACGL::Utils::error() << "Unknown texture target, will create sideeffecs as old bound texture can not get restored!" << std::endl;
    }

    glBindTexture(mTarget, mObjectName);

    return (GLuint) prevTexture;
}

189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 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 278 279 280 281 282 283 284
GLenum TextureBase::getCompatibleFormat( GLenum _internalFormat )
{
    if (   _internalFormat == GL_DEPTH_COMPONENT
        || _internalFormat == GL_DEPTH_COMPONENT16
        || _internalFormat == GL_DEPTH_COMPONENT24
        || _internalFormat == GL_DEPTH_COMPONENT32F
        || _internalFormat == GL_DEPTH24_STENCIL8) {
        return GL_DEPTH_COMPONENT;
    }

    if (   _internalFormat == GL_R8I
        || _internalFormat == GL_R8UI
        || _internalFormat == GL_R16I
        || _internalFormat == GL_R16UI
        || _internalFormat == GL_R32I
        || _internalFormat == GL_R32UI
        || _internalFormat == GL_RG8I
        || _internalFormat == GL_RG8UI
        || _internalFormat == GL_RG16I
        || _internalFormat == GL_RG16UI
        || _internalFormat == GL_RG32I
        || _internalFormat == GL_RG32UI
        || _internalFormat == GL_RGB8I
        || _internalFormat == GL_RGB8UI
        || _internalFormat == GL_RGB16I
        || _internalFormat == GL_RGB16UI
        || _internalFormat == GL_RGB32I
        || _internalFormat == GL_RGB32UI
        || _internalFormat == GL_RGBA8I
        || _internalFormat == GL_RGBA8UI
        || _internalFormat == GL_RGBA16I
        || _internalFormat == GL_RGBA16UI
        || _internalFormat == GL_RGBA32I
        || _internalFormat == GL_RGBA32UI ) {
        return GL_RGBA_INTEGER;
    }

    // there are probably some cases missing that don't work with RGBA
    return GL_RGBA;
}

GLenum TextureBase::getCompatibleType(   GLenum _internalFormat )
{
    if (   _internalFormat == GL_R8I
        || _internalFormat == GL_R8UI
        || _internalFormat == GL_R16I
        || _internalFormat == GL_R16UI
        || _internalFormat == GL_R32I
        || _internalFormat == GL_R32UI
        || _internalFormat == GL_RG8I
        || _internalFormat == GL_RG8UI
        || _internalFormat == GL_RG16I
        || _internalFormat == GL_RG16UI
        || _internalFormat == GL_RG32I
        || _internalFormat == GL_RG32UI
        || _internalFormat == GL_RGB8I
        || _internalFormat == GL_RGB8UI
        || _internalFormat == GL_RGB16I
        || _internalFormat == GL_RGB16UI
        || _internalFormat == GL_RGB32I
        || _internalFormat == GL_RGB32UI
        || _internalFormat == GL_RGBA8I
        || _internalFormat == GL_RGBA8UI
        || _internalFormat == GL_RGBA16I
        || _internalFormat == GL_RGBA16UI
        || _internalFormat == GL_RGBA32I
        || _internalFormat == GL_RGBA32UI ) {
        return GL_INT;
    }
    // not sure if this works for all formats:
    return GL_BYTE;
}

void TextureRectangle::resize( const glm::uvec2 &_newSize )
{
    if (_newSize.x != (unsigned int)mWidth || _newSize.y != (unsigned int)mHeight) {
        mWidth  = _newSize.x;
        mHeight = _newSize.y;

        openGLCriticalErrorOccured();
        bind();
        glTexImage2D(
            mTarget,
            0, // there are no mipmaps for Rect Textures!
            mInternalFormat,
            mWidth,
            mHeight,
            0, // no border
            getCompatibleFormat( mInternalFormat ), // nothing gets uploaded, but this still has to be compatible with the internal format
            getCompatibleType(   mInternalFormat ), // nothing gets uploaded, but this still has to be compatible with the internal format
            NULL );
        openGLCriticalErrorOccured(); // the guess of compatible formats might be wrong so better test for errors!
    }
}


Robert Menzel's avatar
Robert Menzel committed
285 286 287 288
//////////////////////////////////////////////////////////////////////////
//
// old Texture class:

289
#ifndef ACGL_OPENGLES_VERSION_20
290
SharedTextureData Texture::getImageData(GLint _lod, GLenum _type) const
Janis Born's avatar
Janis Born committed
291
{
292
    if(_type == GL_INVALID_ENUM) _type = mType;
Janis Born's avatar
Janis Born committed
293

294 295
    // remember the previously bound texture and bind this one
    GLuint prevTexture = bindAndGetOldTexture();
296
    
Janis Born's avatar
Janis Born committed
297 298
    // determine the required buffer size to hold the requested LOD level
    GLint width, height, depth;
299
    glGetTexLevelParameteriv(mTarget, _lod, GL_TEXTURE_WIDTH,  &width);
Janis Born's avatar
Janis Born committed
300
    glGetTexLevelParameteriv(mTarget, _lod, GL_TEXTURE_HEIGHT, &height);
301
    glGetTexLevelParameteriv(mTarget, _lod, GL_TEXTURE_DEPTH,  &depth);
Janis Born's avatar
Janis Born committed
302 303

    // fetch the image data
304 305 306 307
    int channels = 4;
    if (mFormat == GL_RGB) channels = 3; // TODO: check the other channel types

    GLubyte* imageData = new GLubyte[width * height * getGLTypeSize(_type) * channels];
308
    glGetTexImage(mTarget, _lod, mFormat, _type, (GLvoid*)imageData);
Janis Born's avatar
Janis Born committed
309

310 311 312
    // revert to the previously bound texture
    glBindTexture(mTarget, prevTexture);

Janis Born's avatar
Janis Born committed
313 314 315 316 317 318
    // store the image data and meta information in a TextureData object
    SharedTextureData dataObject = SharedTextureData(new TextureData());
    dataObject->setWidth(width);
    dataObject->setHeight(height);
    dataObject->setDepth(depth);
    dataObject->setType(_type);
319
    dataObject->setFormat(mFormat);
Janis Born's avatar
Janis Born committed
320 321 322 323
    dataObject->setData(imageData); // dataObject will take care of freeing imageData

    return dataObject;
}
324
#endif // ES 2.0