In the last article we introduced the texture API in OpenGL. This article will use a tunnel example to apply the texture in detail. The effect is as follows:

The tunnel

1. Load the texture

This example uses three textures, so use a for loop to bind and load the textures one by one.

// Assign texture object glGenTextures(TEXTURE_COUNT, textures);for(iLoop=0; iLoop<TEXTURE_COUNT; // Bind texture object glBindTexture(GL_TEXTURE_2D, textures[iLoop]); PBytes = gltReadTGABits(szTextureFiles[iLoop], &iWidth, &iHeigth, &iComponents, &eFormat); GL_TEXTURE_MAG_FILTER GL_NEAREST glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER GL_NEAREST); GL_TEXTURE_MIN_FILTER; GL_NEAREST; glTexParameteri; GL_TEXTURE_MIN_FILTER; GL_TEXTURE_WRAP_S(s-axis wrap),GL_CLAMP_TO_EDGE(wrap mode forces texture coordinates out of range to be sampled along the last row or column of a valid texture unit) glTEXture_2d GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); //GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE(Surround mode forces texture coordinates out of range to be sampled along the last row or column of a valid texture unit) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); // Load the texture glTexImage2D(GL_TEXTURE_2D, 0, iComponents, iHeigth, iHeigth, 0, eFormat, GL_UNSIGNED_BYTE, pBytes); GlGenerateMipmap glGenerateMipmap(GL_TEXTURE_2D); Free (pBytes); // Free the original texture data. }Copy the code

2. Determine the coordinates

Take the floor coordinates for example. The floor vertex coordinates are drawn in the form of triangle with GL_TRIANGLE_STRIP. Two triangles can form a square graph. The corresponding texture coordinates are determined according to the following figure.

// Set the geometry vertex GLfloatz, x=10, y=10; floorBatch.Begin(GL_TRIANGLE_STRIP, 28, 1); // Floor z indicates tunnel depthfor(z=60; z>=0; Z - = 10) {floorBatch. MultiTexCoord2f (0, 0.0, 0.0); floorBatch.Vertex3f(-x, -y, z); FloorBatch. MultiTexCoord2f (0, 1.0, 0). floorBatch.Vertex3f(x, -y, z); FloorBatch. MultiTexCoord2f (0, 0, 1.0); floorBatch.Vertex3f(-x, -y, z-10); FloorBatch. MultiTexCoord2f (0, 1.0, 1.0); floorBatch.Vertex3f(x, -y, z-10); } floorBatch.End();Copy the code

The other coordinates can be determined by referring to the Settings above.

3. Draw

Drawing is relatively easy, remember to bind the corresponding texture object before drawing.

modelViewMatrix.PushMatrix();
modelViewMatrix.Translate(0, 0, viewZ);

shaderManager.UseStockShader(GLT_SHADER_TEXTURE_REPLACE, transformPipeline.GetModelViewProjectionMatrix(), 0);

glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_FLOOR]);
floorBatch.Draw();

glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_BRICK]);
leftWallBatch.Draw();

glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_BRICK]);
rightBatch.Draw();

glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_CEILING]);
ceilingBatch.Draw();

modelViewMatrix.PopMatrix();
glutSwapBuffers();
Copy the code

Run the code, and we’ll get what we want.

4. Camera movement

The above shows only a static effect and cannot be moved, so we add a method that responds to a particular key. To move the camera. The end result is the same as the GIF above.

// Move the viewport back and forth to respond to the arrow keys void SpecialKeys(int key, int x, int y) {if(key == GLUT_KEY_UP) {viewZ += 0.5f; }if(key == GLUT_KEY_DOWN) {viewZ -= 0.5f; } glutPostRedisplay(); }Copy the code

5. Compare some effects

Finally, we can add a right-click list to set different parameters and compare the different effects of different parameter Settings. Add menu entry:

 glutCreateMenu(ProcessMenu);
 glutAddMenuEntry("GL_NEAREST", 0);
 glutAddMenuEntry("GL_LINEAR", 1);
 glutAddMenuEntry("GL_NEAREST_MIPMAP_NEAREST", 2);
 glutAddMenuEntry("GL_NEAREST_MIPMAP_LINEAR", 3);
 glutAddMenuEntry("GL_LINEAR_MIPMAP_NEAREST", 4);
 glutAddMenuEntry("GL_LINEAR_MIPMAP_LINEAR", 5);
 glutAddMenuEntry("Anisotropic Filter", 6);
 glutAddMenuEntry("Anisotropic Off", 7);
 glutAttachMenu(GLUT_RIGHT_BUTTON);
Copy the code

Event handling:

// Menu bar select void ProcessMenu(int value) {GLuint iLoop;for (iLoop = 0; iLoop<TEXTURE_COUNT; iLoop++) {
        glBindTexture(GL_TEXTURE_2D, textures[iLoop]);
        
        switch (value) {
            case 0:
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
                break;
            case 1:
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                break;
            case 2:
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
                break;
            case 3:
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
                break;
            case 4:
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
            case 5:
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
                
            case 6:
                GLfloatfLargest; glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fLargest); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, fLargest); Default: glTexParameterf (GL_TEXTURE_2D GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0 f);break;
        }
    }
    glutPostRedisplay();
}
Copy the code