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:
Here are the same two objects 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.