sunLoadingImage
whowedImag
decoration left 1
decoration left 2
transhome
transprojects
transgallery
transarticles
decoration rigth
English

Show/Hide search bar
black cat logo variable logo
[21 Jan 2013]

Utility functions for OpenGL textures

This article provides utility functions that help to work with textures in OpenGL and Qt. The article covers following functions:
  • to create empty 2D texture (GL_TEXTURE_2D)
  • to load 2D texture from image file (GL_TEXTURE_2D)
  • to load cube texture from 6 image files (GL_TEXTURE_CUBE_MAP)
  • to load 3D texture from array of image files (GL_TEXTURE_3D)
  • Funcion that creates empty 2D texture with specified size and parameters
    GLuint create2DTexture(GLuint width, GLuint height,
                            GLenum internalFormat, GLenum format, GLenum elemType)
    {
       GLint texture;

       glGenTextures(1, &texture);
       glBindTexture(GL_TEXTURE_2D, texture);
       glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width,
                            height, 0, format, elemType, nullptr);
       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
       glGenerateMipmap(GL_TEXTURE_2D);
       glBindTexture(GL_TEXTURE_2D, 0);

       return texture;
    }
    Load 2D texture form file to OpenGL
    // loads texture from file
    GLuint load2DTexture(const qs & path)
    {
       GLint texture;

       // Load QImage from file
       QImage imageToConvert;
       if(!imageToConvert.load(path))
       {
          Log::instance().log("Texture2D::load() failed : " + path);
          return;
       }

       // Try to convert loaded image to OpenGL format
       QImage GL_formatted_image = QGLWidget::convertToGLFormat(imageToConvert);
       if(GL_formatted_image.isNull())
       {
          Log::instance().log("Texture2D::load() failed to convert : " + path);
          return;
       }

       // crate new texture from loaded data
       glGenTextures(1, &texture);
       glBindTexture(GL_TEXTURE_2D, texture);
       glTexImage2D(
             GL_TEXTURE_2D,
             0,
             GL_RGBA,
             GL_formatted_image.width(),
             GL_formatted_image.height(),
             0,
             GL_RGBA,
             GL_UNSIGNED_BYTE,
             GL_formatted_image.bits()
          );
       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
       glGenerateMipmap(GL_TEXTURE_2D);
       glBindTexture(GL_TEXTURE_2D, 0);

       return texture;
    }
    Load cube texture form file to OpenGL
    GLuint loadCubeTexture(const qs & path)
    {
       GLint texture;

       // get extension and name of the file
       qs pre = path.mid(0, path.lastIndexOf());
       qs ext = path.mid(path.lastIndexOf()+1, 3);

       // element for each side of cube texture
       GLenum cubesides[6] =
       {
          GL_TEXTURE_CUBE_MAP_POSITIVE_X,
          GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
          GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
          GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
          GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
          GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
       };

       // files for each side of cube texture
       qs cubepaths[6] =
       {
          pre + "_posx." + ext,
          pre + "_negx." + ext,
          pre + "_posy." + ext,
          pre + "_negy." + ext,
          pre + "_posz." + ext,
          pre + "_negz." + ext
       };

       // create new texture
       glGenTextures(1, &texture);
       glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
       glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
       glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
       glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
       glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
       glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
       glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_GENERATE_MIPMAP, GL_TRUE);

       // set data for each side of cube texture
       for(short i=0; i<6; i++)
       {
          QImage imageToConvert;
          if(!imageToConvert.load(cubepaths[i]))
          {
             Log::instance().log("ERROR : Cube face loading failed: " + cubepaths[i]);
             return;
          }

          QImage GL_formatted_image = QGLWidget::convertToGLFormat(imageToConvert);
          if(GL_formatted_image.isNull())
          {
             Log::instance().log("ERROR : Cube face - fail convert: " + path);
             return;
          }

          glTexImage2D(
             cubesides[i],
             0,
             GL_RGBA,
             GL_formatted_image.width(),
             GL_formatted_image.height(),
             0,
             GL_RGBA,
             GL_UNSIGNED_BYTE,
             GL_formatted_image.bits()
             );
       }

       glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);

       glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
       glBindTexture(GL_TEXTURE_CUBE_MAP, 0);

       return texture;
    }
    Load 3D texture form file to OpenGL
    // each element of pathes contains path to image file
    GLuint load3DTexture(const std::vector & pathes)
    {
       GLuint texture;
       if(pathes.size() == 0)
       {
          Log::instance().log("Texture3D::load() - empty array of pathes");
          return texture;
       }

       GLsizei width, height, depth = (GLsizei)pathes.size();

       std::vector formatedImages(pathes.size());

       // load and format each image
       {
          for(uint i=0; i       {
             QImage imageToConvert;
             if(!imageToConvert.load(pathes[i]))
             {
                Log::instance().log("Texture3D::load() failed : " + pathes[i]);
                return;
             }

             QImage GL_formatted_image = QGLWidget::convertToGLFormat(imageToConvert);
             if(GL_formatted_image.isNull())
             {
                Log::instance().log("Texture3D::load() failed to
                convert to gl format : " + pathes[i]);
                return;
             }

             formatedImages[i] = GL_formatted_image;

             if(i==0)
             {
                width = formatedImages[i].width();
                height = formatedImages[i].height();
             }
             else
             {
                if(width != formatedImages[i].width()
                      || height != formatedImages[i].height())
                {
                   Log::instance().log("Texture3D::load() failed :
                   different dimensions of images. " + pathes[0] + " " + pathes[i]);
                   return;
                }
             }
          }
       }

       // create empty 3D texture
       {
          glGenTextures(1, &m_texture);
          glBindTexture(GL_TEXTURE_3D, m_texture);
          glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
          glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
          glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT);
          glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT);
          glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

          // allocate memory for 3D texture
          glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, width,
                height, depth, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
       }

       // copy image data to each layer of 3D texture
       {
          for(uint i=0; i       {
             glTexSubImage3D(
                   GL_TEXTURE_3D, 0,
                   0, 0, (GLint)i,
                   width, height, 1,
                   GL_RGBA, GL_UNSIGNED_BYTE,
                   formatedImages[i].bits()
             );
          }
       }

       glGenerateMipmap(GL_TEXTURE_3D);
       glBindTexture(GL_TEXTURE_3D, 0);
    }
    Don't forget to remove texture:
    glDeleteTextures(1, &texture);


    Sun and Black Cat- Igor Dykhta (igor dykhta email) 2007-2014