0

I'm recreating a 2D scene in 3D with OpenGL. My goal is to recreate an image of a desk with a monitor, tower, keyboard, and mouse. So far I have rendered the monitor and screen for the monitor. The z-coordinates for the monitor (the gray box) originally were greater than the z-coordinates for the flat white screen since the screen is supposed to be in front of it. However, when it renders, the exact opposite of what you would expect occurs. The screen renders behind the rectangular cube. I can tell when I apply a 180 degree rotation to my rotation matrix. So when I adjust the z-coordinates to make the screen's greater than the monitor's, then it appears in front. But as the z-coordinate increases, objects should be going further into the distance, so that's really odd.

Here's a screenshot of when the screen's z-coordinates are greater than the monitor's:

monitor with screen

Here are the same two objects rotated 45 degrees:

monitor with screen rotated 45 degrees

Of course, that's how it's supposed to look, but only when the screen's coordinates are less than the monitor's. Here's some relevant code to help you understand what I'm talking about. I left some code out that I didn't think would be relevant. Please tell me if you need me to provide more code.

void uCreateScreenMesh(GLMesh& mesh) {
    GLfloat vertices[] = {
        -0.25f, 0.95f, 0.81f,       1.0f, 1.0f, 1.0f, 1.0f, //0
        -0.25f, 0.65f, 0.81f,       1.0f, 1.0f, 1.0f, 1.0f, //1
         0.25f, 0.65f, 0.81f,       1.0f, 1.0f, 1.0f, 1.0f, //2
         0.25f, 0.95f, 0.81f,       1.0f, 1.0f, 1.0f, 1.0f  //3
    };

    GLushort indices[] = {
        0, 1, 2,
        0, 3, 2
    };

    const GLuint floatsPerVertex = 3;
    const GLuint floatsPerColor = 4;
    const GLint stride = sizeof(float) * (floatsPerVertex + floatsPerColor);
    mesh.nIndices = sizeof(indices) / sizeof(indices[0]);

    glGenVertexArrays(1, &mesh.vao);
    glBindVertexArray(mesh.vao);

    glGenBuffers(2, mesh.vbo);
    glBindBuffer(GL_ARRAY_BUFFER, mesh.vbo[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.vbo[1]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    //create vertex attribute pointers
    glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0);
    glEnableVertexAttribArray(0);

    glVertexAttribPointer(1, floatsPerColor, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float) * floatsPerVertex));
    glEnableVertexAttribArray(1);
}

void uCreateMonitorMesh(GLMesh& mesh)
{
    GLfloat vertices[] = {
        //monitor (rectangle)
        -0.3f, 1.0f, 0.75f,         0.5f, 0.5f, 0.5f, 1.0f, //0
        -0.3f, 1.0f, 0.8f,          0.5f, 0.5f, 0.5f, 1.0f, //1
        
        -0.3f, 0.6f, 0.75f,         0.5f, 0.5f, 0.5f, 1.0f, //2
        -0.3f, 0.6f, 0.8f,          0.5f, 0.5f, 0.5f, 1.0f, //3
 
         0.3f, 0.6f, 0.75f,          0.5f, 0.5f, 0.5f, 1.0f, //4
         0.3f, 0.6f, 0.8f,           0.5f, 0.5f, 0.5f, 1.0f, //5

         0.3f, 1.0f, 0.75f,          0.5f, 0.5f, 0.5f, 1.0f, //6
         0.3f, 1.0f, 0.8f,           0.5f, 0.5f, 0.5f, 1.0f  //7



        
    };

    GLushort indices[] = {
        //monitor front
        0, 2, 4,
        0, 6, 4,

        //top
        0, 1, 7,
        0, 6, 7,

        //left side
        0, 3, 1,
        0, 2, 1,

        //bottom side
        2, 3, 5,
        2, 5, 4,

        //right side
        4, 5, 6,
        4, 7, 6,

        //monitor back
        1, 3, 5,
        1, 7, 5
    };

    const GLuint floatsPerVertex = 3;
    const GLuint floatsPerColor = 4;
    const GLint stride = sizeof(float) * (floatsPerVertex + floatsPerColor);
    mesh.nIndices = sizeof(indices) / sizeof(indices[0]);

    glGenVertexArrays(1, &mesh.vao);
    glBindVertexArray(mesh.vao);

    glGenBuffers(2, mesh.vbo);
    glBindBuffer(GL_ARRAY_BUFFER, mesh.vbo[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.vbo[1]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    //create vertex attribute pointers
    glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0);
    glEnableVertexAttribArray(0);

    glVertexAttribPointer(1, floatsPerColor, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float) * floatsPerVertex));
    glEnableVertexAttribArray(1);
}

void uRender()
{
    //enable z-depth
    glEnable(GL_DEPTH_TEST);

    //clear frame and z buffers
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glm::mat4 scale = glm::scale(glm::vec3(1.2f, 1.2f, 1.2f));
    glm::mat4 rotation = glm::rotate(glm::radians(0.f), glm::vec3(0.0f, 1.0f, 0.0f));
    glm::mat4 translation = glm::translate(glm::vec3(0.0f, 0.0f, 0.0f));

    glm::mat4 model = translation * rotation * scale;

    glm::mat4 view = glm::translate(glm::vec3(0.0f, 0.0f, -3.5f));

    glm::mat4 projection = glm::perspective(45.0f, (GLfloat)WINDOW_WIDTH / (GLfloat)WINDOW_HEIGHT, 0.1f, 100.0f);

    glUseProgram(programId);

    GLint modelLoc = glGetUniformLocation(programId, "model");
    GLint viewLoc = glGetUniformLocation(programId, "view");
    GLint projLoc = glGetUniformLocation(programId, "projection");

    glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
    glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
    glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));

    glBindVertexArray(screenMesh.vao);
    glDrawElements(GL_TRIANGLES, screenMesh.nIndices, GL_UNSIGNED_SHORT, NULL);

    glBindVertexArray(monitorMesh.vao);
    glDrawElements(GL_TRIANGLES, monitorMesh.nIndices, GL_UNSIGNED_SHORT, NULL);
    
    

    glBindVertexArray(0);
    glfwSwapBuffers(window);
}

I tried changing the order in which the vertex array object is binded, but as I expected that didn't change anything.

All help appreciated, thank you.

CodyT96
  • 165
  • 1
  • 3
  • 12
  • 2
    Opengl z axis decreases into the negative as you go into the screen. Try putting negative z values – Sync it Jan 24 '21 at 04:07
  • Hmm, interesting. For some reason when I decrease the z-coordinate for my view matrix into the negatives, the camera gets further away, and increase in the positive range it gets closer. But when I adjusted the z-coordinates for my shapes, they did indeed get further the more negative they were. I wonder why that is.. Thanks for the answer by the way. – CodyT96 Jan 24 '21 at 04:47
  • That's how the opengl [co-ordinate system](https://learnopengl.com/Getting-started/Coordinate-Systems) works. Greate website have a look – Sync it Jan 24 '21 at 05:21
  • @CodyT96 Perhaps this [discussion](https://stackoverflow.com/questions/15588860/what-exactly-are-eye-space-coordinates/15592361#15592361) may help with your understanding of camera positioning and eye coordinates. – radical7 Jan 24 '21 at 07:50
  • In general the OpenGL coordinate system is a [Right-handed](https://en.wikipedia.org/wiki/Right-hand_rule) system. In view space the X-axis points to the right and the Y-axis points up. Since the Z-axis is the [Cross product](https://en.wikipedia.org/wiki/Cross_product) of the X-axis and the Y-axis, it points out of the viewport – Rabbid76 Jan 24 '21 at 08:07

0 Answers0