OpenGL C++透视投影异常问题求助(已解决附方案)
3D立方体透视投影渲染问题
我尝试在窗口中渲染3D立方体并观察透视投影效果:在顶点Shader中不乘以投影矩阵时,立方体可正常渲染但无透视效果;乘以透视投影矩阵后,立方体出现过度放大现象或窗口直接显示黑屏。
原始代码
顶点Shader
//Vertex Shader #version 420 core layout (location = 0) in vec3 pos; out vec4 col; uniform mat4 model; uniform mat4 projection; void main(){ gl_Position = model * projection * vec4(pos,1.0f); col = vec4(clamp(pos, 0.1f, 100.0f), 1.0f); }
main.cpp
#include <iostream> #include <vector> #include <stdio.h> #include <GL/glew.h> #include <GLFW/glfw3.h> #include <GLM/glm.hpp> #include <GLM/gtc/matrix_transform.hpp> #include <GLM/gtc/type_ptr.hpp> #include "Window.h" #include "Shader.h" #include "Buffers.h" #include "Camera.h" Window window; std::vector<Buffers*> bufferList; std::vector<Shader> shaderList; static const char* vShader = "Shaders/shader.vert"; static const char* fShader = "Shaders/shader.frag"; void CreateObjects() { GLfloat Cubevertices[] = { 1.0f,1.0f,1.0f, //0 -1.0f,1.0f,1.0f, //1 1.0f,-1.0f,1.0f, //2 -1.0f,-1.0f,1.0f, //3 1.0f,1.0f,-1.0f, //4 -1.0f,1.0f,-1.0f, //5 -1.0f,-1.0f,-1.0f, //6 1.0f,-1.0f,-1.0f, //7 }; unsigned int Cubeindices[] = { 0,1,3, 3,0,2, 3,2,6, 6,7,2, 1,3,5, 5,6,3, 0,1,4, 4,5,1, 2,0,7, 7,4,0, 5,6,4, 4,7,6 }; Buffers* obj1 = new Buffers(); obj1->CreateBuffer(Cubevertices, Cubeindices, 24, 36); //24 36 bufferList.push_back(obj1); } void CreateShaders() { Shader* shader1 = new Shader(); shader1->createFromFiles(vShader, fShader); shaderList.push_back(*shader1); } GLfloat toRad = 3.14159265359f/180.0f; GLfloat r_angle = 0.0f; bool direction = true; float offset = 0.0f; float maxoffset = 0.7f; float inc = 0.0005f; float cursize = 0.5f; bool sizedir = true; int main() { window = Window(500, 500, "Cube"); window.Initialize(); CreateObjects(); CreateShaders(); GLuint u_model = 0, u_project = 0, u_view = 0; glm::mat4 projection = glm::perspective(glm::radians(10.0f), (GLfloat)window.getBufferWidth() / window.getBufferHeight(), 1.0f, 100.0f); while (!window.windowClose()) { glfwPollEvents(); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glEnable(GL_DEPTH_TEST); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); shaderList[0].UseShader(); u_model = shaderList[0].getUniformModelLocation(); u_project = shaderList[0].getProjectionModelLocation(); glm::mat4 model(1.0f); //TRANSLATION if (direction) { offset += inc; } else { offset -= inc; } if (abs(offset) >= maxoffset) { direction = !direction; } model = glm::scale(model, glm::vec3(0.3f, 0.3f, 0.3f)); model = glm::translate(model, glm::vec3(0.0f, offset, 0.0f)); model = glm::rotate(model, toRad*45.0f, glm::vec3(1.0f, 1.0f, 1.0f)); glUniformMatrix4fv(u_project, 1, GL_FALSE, glm::value_ptr(projection)); glUniformMatrix4fv(u_model, 1, GL_FALSE, glm::value_ptr(model)); bufferList[0]->Render(); window.swapBuffers(); } return 0; }
已解决
透视投影中相机默认位于原点,需将立方体沿-Z轴平移才能正常观察。以下是修正后的代码及渲染效果:
修正后的顶点Shader
#version 330 layout (location = 0) in vec3 pos; out vec4 vCol; uniform mat4 model; uniform mat4 projection; void main(){ gl_Position = projection * model * vec4(pos,1.0); vCol = vec4(clamp(pos,0.0f,1.0f),1.0f); }
修正后的main.cpp
#include <stdio.h> #include <string.h> #include <cmath> #include <vector> #include <GL\glew.h> #include <GLFW\glfw3.h> #include <glm\glm.hpp> #include <glm\gtc\matrix_transform.hpp> #include <glm\gtc\type_ptr.hpp> #include "Window.h" #include "Mesh.h" #include "Shader.h" Window mainWindow; std::vector<Mesh*> meshList; std::vector<Shader> shaderList; static const char* vShader = "Shaders/shader.vert"; static const char* fShader = "Shaders/shader.frag"; void CreateObjects() { unsigned int indices[] = { 0,1,2, 2,3,0, 4,5,6, 6,7,4, 1,6,5, 5,2,1, 7,0,3, 3,4,7, 3,2,5, 5,4,3, 7,6,1, 1,0,7 }; GLfloat vertices[] = { -0.5f,-0.5f,-0.5f, -0.5f,0.5f,-0.5f, 0.5f,0.5f,-0.5f, 0.5f,-0.5f,-0.5f, 0.5f,-0.5f,0.5f, 0.5f,0.5f,0.5f, -0.5f,0.5f,0.5f, -0.5f,-0.5f,0.5f }; Mesh* obj = new Mesh(); obj->CreateMesh(vertices, indices, 24, 36); meshList.push_back(obj); } void CreateShader() { Shader* shader = new Shader(); shader->CreateFromFiles(vShader, fShader); shaderList.push_back(*shader); } GLfloat r_angle = 0.0f; int main() { mainWindow = Window(800, 600); mainWindow.Initialize(); CreateObjects(); CreateShader(); GLuint uniformProjection = 0, uniformModel = 0; glm::mat4 projection = glm::perspective(glm::radians(45.0f), (GLfloat)mainWindow.getBufferWidth() / mainWindow.getBufferHeight(), 0.1f, 100.0f); while (!mainWindow.getShouldClose()) { glfwPollEvents(); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); shaderList[0].UseShader(); uniformModel = shaderList[0].GetModelLocation(); uniformProjection = shaderList[0].GetProjectionLocation(); r_angle += 0.05f; if (r_angle >= 360) { r_angle -= 360; } glm::mat4 model(1.0f); model = glm::translate(model, glm::vec3(0.0f, 0.0f, -2.0f)); model = glm::rotate(model, glm::radians(r_angle), glm::vec3(0.0f, 1.0f, 0.0f)); glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model)); glUniformMatrix4fv(uniformProjection, 1, GL_FALSE, glm::value_ptr(projection)); meshList[0]->RenderMesh(); glUseProgram(0); mainWindow.swapBuffers(); } return 0; }
渲染效果
可正常显示带透视投影的旋转立方体,远处的面尺寸更小,近处的面尺寸更大,完全符合透视投影的视觉规律。
内容的提问来源于stack exchange,提问作者arudhraC
相关产品推荐
相关产品推荐

