Search code examples
c++opengltextures

Textures render very weirdly in OpenGL


I am trying to draw a box in OpenGL (top is open). I gave it textures but they seem to render very weirdly. The side texture appears to be on the bottom sometimes when I rotate the box and what not.

This is the front view:

Front view

After rotating it a bit:

Rotated view

Clearly, something is wrong here. The blue one is the texture for the side panel but when it is rotated, it appears to go on the floor. And the grey one is texture for the front panel. So, in the front view, the back panel shouldn't be visible at all. But, it can be seen.

Code snippets:

Method for drawing the container (lid not included):

void box::drawContainer() {
    GLuint tex = loadTexture("wood.bmp");
    glPushMatrix();

    glBindTexture(GL_TEXTURE_2D, tex);
    drawBlock(vertex(0, 0, 0), length + 0.2, length + 0.2, thickness); // bottom

    tex = loadTexture("tiles.bmp");
    glBindTexture(GL_TEXTURE_2D, tex);
    drawBlock(
            vertex((length - thickness) / 2.0,
                    (containerHeight + thickness) / 2.0, 0), thickness, breadth,
            containerHeight); // right

    tex = loadTexture("ocean.bmp");
    glBindTexture(GL_TEXTURE_2D, tex);
    drawBlock(
            vertex((thickness - length) / 2.0,
                    (containerHeight + thickness) / 2.0, 0), thickness, breadth,
            containerHeight); // left

    tex = loadTexture("smoke.bmp");
    glBindTexture(GL_TEXTURE_2D, tex);
    drawBlock(
            vertex(0, (containerHeight + thickness) / 2.0,
                    (breadth - thickness) / 2.0), (length - 2.0 * thickness),
            thickness, containerHeight); // front

    tex = loadTexture("lightning.bmp");
    glBindTexture(GL_TEXTURE_2D, tex);
    drawBlock(
            vertex(0, (containerHeight + thickness) / 2.0,
                    (thickness - breadth) / 2.0), (length - 2.0 * thickness),
            thickness, containerHeight); // back

    glPopMatrix();
}

The drawBlock method:

void object::drawBlock(vertex center, float length, float breadth,
        float height) {
    glPushMatrix();
    glTranslatef(center.x, center.y, center.z);
    glScalef(length, height, breadth);
    glBegin(GL_QUADS);
    drawPrimitive(vertex(-0.5, 0.5, 0.5), vertex(-0.5, -0.5, 0.5),
            vertex(0.5, -0.5, 0.5), vertex(0.5, 0.5, 0.5),
            vertex(-0.5, 0.5, -0.5), vertex(-0.5, -0.5, -0.5),
            vertex(0.5, -0.5, -0.5), vertex(0.5, 0.5, -0.5));
    glEnd();
    glPopMatrix();
}

drawPrimitive method:

void object::drawPrimitive(vertex v1, vertex v2, vertex v3, vertex v4,
        vertex v5, vertex v6, vertex v7, vertex v8) {
    drawFace(v1, v2, v3, v4);
    drawFace(v5, v6, v7, v8);
    drawFace(v1, v5, v6, v2);
    drawFace(v4, v3, v7, v8);
    drawFace(v1, v4, v8, v5);
    drawFace(v2, v6, v7, v3);
}

And, drawFace method:

void object::drawFace(vertex v1, vertex v2, vertex v3, vertex v4) {
    glTexCoord2f(0, 1);
    glVertex3f(v1.x, v1.y, v1.z);
    glTexCoord2f(0, 0);
    glVertex3f(v2.x, v2.y, v2.z);
    glTexCoord2f(1, 0);
    glVertex3f(v3.x, v3.y, v3.z);
    glTexCoord2f(1, 1);
    glVertex3f(v4.x, v4.y, v4.z);
}

The main function:

int main(int argc, char** argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA);
    glutInitWindowSize(640, 480);
    glutInitWindowPosition(50, 50);
    glutCreateWindow(title);

    glutDisplayFunc(display);

    glutKeyboardFunc(processKey);

    glutReshapeFunc(reshape);
    initGL();
    glutMainLoop();
    return 0;
}

initGL method:

void initGL() {
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set background color to black and opaque
    glClearDepth(1.0f);                   // Set background depth to farthest
    glEnable(GL_DEPTH_TEST);   // Enable depth testing for z-culling
    glDepthFunc(GL_LEQUAL);    // Set the type of depth-test
    glShadeModel(GL_FLAT);
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Nice perspective corrections
}

loadTexture method:

GLuint inline loadTexture(const char* fName) {
    // Data read from the header of the BMP file
    unsigned char header[54]; // Each BMP file begins by a 54-bytes header
    unsigned int dataPos;   // Position in the file where the actual data begins
    unsigned char * data;
    unsigned int imageSize;
    unsigned int width, height;
    // Actual RGB data
    // Open the file
    FILE * file = fopen(fName, "rb");
    if (!file) {
        printf("Image could not be opened\n");
    }
    if (fread(header, 1, 54, file) != 54) { // If not 54 bytes read : problem
        printf("Not a correct BMP file\n");
        return 0;
    }
    if (header[0] != 'B' || header[1] != 'M') {
        printf("Not a correct BMP file\n");
        return 0;
    }
    // Read ints from the byte array
    dataPos = *(int*) &(header[0x0A]);
    imageSize = *(int*) &(header[0x22]);
    width = *(int*) &(header[0x12]);
    height = *(int*) &(header[0x16]);

    // Some BMP files are misformatted, guess missing information
    if (imageSize == 0)
        imageSize = width * height * 3; // 3 : one byte for each Red, Green and Blue component
    if (dataPos == 0)
        dataPos = 54;
    // Create a buffer
    data = new unsigned char[imageSize];

    // Read the actual data from the file into the buffer
    fread(data, 1, imageSize, file);

    //Everything is in memory now, the file can be closed
    fclose(file);
    // Create one OpenGL texture
    GLuint textureID;
    glGenTextures(1, &textureID);

    // "Bind" the newly created texture : all future texture functions will modify this texture
    glBindTexture(GL_TEXTURE_2D, textureID);

    // Give the image to OpenGL
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR,
            GL_UNSIGNED_BYTE, data);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    return textureID;
}

The draw method which calls drawContainer:

void box::draw()
{
        glEnable(GL_TEXTURE_2D);
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
        drawContainer();
        glDisable(GL_TEXTURE_2D);
}

Please tell me if any more code needs to be inserted or anything needs to be removed.


Solution

  • Turns out I gave the z-perspective wrong. Thanks for all the help