Texturing in OpenGL

OpenGL allows us to map an image (also referred to as a texture) to a 3D shape or polygon. This process is also called texture mapping. Qt appears to be the best combination with OpenGL in this case because it provides an easy way to load images that belong to one of the common formats (BMP, JPEG, PNG, TARGA, TIFF, and so on) and you don't have to implement it by yourself. We will use the previous example with a spinning cube and try to map it with a texture!

How to do it…

  1. First of all, open up mainwindow.h and add the following header to it:
    #include <QGLWidget>
  2. Next, declare an array that stores the texture IDs created by OpenGL. We will be using it later when it comes to rendering:
    private:
      QOpenGLContext* context;
      QOpenGLFunctions* openGLFunctions;
    
      float rotation;
      GLuint texID[1];
    
  3. After that, open up mainwindow.cpp and add the following code to initializeGL() to load the texture file:
    void MainWindow::initializeGL()
    {
      // Enable Z-buffer depth test
      glEnable(GL_DEPTH_TEST);
    
      // Enable texturing
      glEnable(GL_TEXTURE_2D);
    
      QImage image("bricks");
      QImage texture = QGLWidget::convertToGLFormat(image);
    
      glGenTextures(1, &texID[0]);
      glBindTexture(GL_TEXTURE_2D, texID[0]);
    
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    
      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture.width(), texture.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, texture.bits());
    
      // Make sure render at the correct aspect ratio
      resizeGL(this->width(), this->height());
    }
  4. Then, add the following code to the paintGL() function to apply the texture to the 3D cube:
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, texID[0]);
    
    // FRONT
    glBegin(GL_POLYGON);
      glColor3f(0.0, 0.0, 0.0);
      glTexCoord2f(0.0f, 0.0f); glVertex3f(0.5, -0.5, -0.5);
      glTexCoord2f(1.0f, 0.0f); glVertex3f(0.5, 0.5, -0.5);
      glTexCoord2f(1.0f, 1.0f); glVertex3f(-0.5, 0.5, -0.5);
      glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.5, -0.5, -0.5);
    glEnd();
    
    // BACK
    glBegin(GL_POLYGON);
      glColor3f(0.0, 1.0, 0.0);
      glTexCoord2f(1.0f, 0.0f); glVertex3f(0.5, -0.5, 0.5);
      glTexCoord2f(1.0f, 1.0f); glVertex3f(0.5, 0.5, 0.5);
      glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.5, 0.5, 0.5);
      glTexCoord2f(0.0f, 0.0f); glVertex3f(-0.5, -0.5, 0.5);
    glEnd();
    
    // RIGHT
    glBegin(GL_POLYGON);
      glColor3f(1.0, 0.0, 1.0);
      glTexCoord2f(0.0f, 1.0f); glVertex3f(0.5, -0.5, -0.5);
      glTexCoord2f(0.0f, 0.0f); glVertex3f(0.5, 0.5, -0.5);
      glTexCoord2f(1.0f, 0.0f); glVertex3f(0.5, 0.5, 0.5);
      glTexCoord2f(1.0f, 1.0f); glVertex3f(0.5, -0.5, 0.5);
    glEnd();
    
    // LEFT
    glBegin(GL_POLYGON);
      glColor3f(1.0, 1.0, 0.0);
      glTexCoord2f(1.0f, 1.0f); glVertex3f(-0.5, -0.5, 0.5);
      glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.5, 0.5, 0.5);
      glTexCoord2f(0.0f, 0.0f); glVertex3f(-0.5, 0.5, -0.5);
      glTexCoord2f(1.0f, 0.0f); glVertex3f(-0.5, -0.5, -0.5);
    glEnd();
    
    // TOP
    glBegin(GL_POLYGON);
      glColor3f(0.0, 0.0, 1.0);
      glTexCoord2f(1.0f, 0.0f); glVertex3f(0.5, 0.5, 0.5);
      glTexCoord2f(1.0f, 1.0f); glVertex3f(0.5, 0.5, -0.5);
      glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.5, 0.5, -0.5);
      glTexCoord2f(0.0f, 0.0f); glVertex3f(-0.5, 0.5, 0.5);
    glEnd();
    
    // Red side - BOTTOM
    glBegin(GL_POLYGON);
      glColor3f(1.0, 0.0, 0.0);
      glTexCoord2f(0.0f, 0.0f); glVertex3f( 0.5, -0.5, -0.5);
      glTexCoord2f(1.0f, 0.0f); glVertex3f( 0.5, -0.5, 0.5);
      glTexCoord2f(1.0f, 1.0f); glVertex3f(-0.5, -0.5, 0.5);
      glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.5, -0.5, -0.5);
    glEnd();
    
    glDisable(GL_TEXTURE_2D);
  5. If you compile and run the program now, you should see a brick cube rotating around the screen!
    How to do it…

How it works...

The variable GLuint texID[1] is an array that stores the texture ID generated by OpenGL when we call glGenTexture(), which OpenGL uses to allocate the texture from the memory during rendering. In this case, we set the size of the array to 1 because we are only using a single texture in this example. We must tell OpenGL to enable texturing by calling glEnable(GL_TEXTURE_2D) before doing anything related to texturing. We used two QImage classes to load the texture, the first one called image was used to load the image file, and the second one called texture was used to convert the image to an OpenGL-compatible format. Then we called glGenTextures() to generate an empty texture using OpenGL, and after that, we called glBindTexture() to select that particular texture. This step was needed so that the functions called after that will be applied to the texture that we just selected.

Next, we called glTexParameteri() twice to set both the texture minifying and texture magnification settings to point sampling. This will tell OpenGL how the texture should be rendered. More about that later. After that, we called glTexImage2D() to supply the pixel information from the texture file loaded by Qt to the empty OpenGL texture we just created. Call glEnabled(GL_TEXTURE_2D) and glBindTexture() to enable texturing in OpenGL and select the texture we wanted to use before we start rendering the 3D cube. Then, we must call glTexCoord2f() before calling glVertex3f() to tell OpenGL how the texture should be mapped. We supply the coordinates for the texture and OpenGL will figure out the rest for us.

Once you're done, call glDisable(GL_TEXTURE_2D) to disable texturing.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
52.15.42.128