我正在用OpenGL在3D中重建2D场景。我的目标是用显示器、塔、键盘和鼠标重新创建一张桌子的图像。到目前为止,我已经渲染了监视器和监视器的屏幕。监视器(灰色框)的z坐标最初大于平坦白色屏幕的z坐标,因为屏幕应该在它的前面。但是,当它渲染时,会出现与预期完全相反的情况。屏幕在矩形立方体后面渲染。我可以判断何时对旋转矩阵应用180度旋转。因此,当我调整z坐标使屏幕大于显示器时,它就会出现在前面。但是随着z坐标的增加,物体应该会向更远的地方移动,所以这真的很奇怪。
以下是屏幕的z坐标大于显示器的z坐标时的屏幕截图:
以下是旋转了45度的两个相同对象:
当然,这就是它应该看起来的样子,但只有当屏幕的坐标小于显示器的坐标时。这里有一些相关的代码可以帮助你理解我在说什么。我遗漏了一些我认为不相关的代码。如果你需要我提供更多代码,请告诉我。
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);
}
我尝试更改顶点数组对象绑定的顺序,但正如我所料,这并没有改变任何事情。
感谢大家的帮助,谢谢。