我正在研究OpenGL中的相机移动。当我旋转相机时,我视图中的物体在经过我时会产生不寻常的拉伸效果。这可以在我的YouTube视频(https://youtu.be/RviJ0bVw880)上看到。我相信我的投影矩阵或视图矩阵有问题,但我不确定。
主要问题:旋转相机时,如何防止物体拉伸?
这是我的C ++代码(我相信你要找的是接近底部):
//Load functions from usr/include/
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <glm/glm.hpp>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/ext.hpp>
#include "glm/gtx/string_cast.hpp"
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
/**/#include <iostream>
/**/#include <vector>
//Main function
int main() {
std::ios_base::sync_with_stdio(false);//Disables the synchronization between the C and C++ standard streams (though mixing C- and C++ style I/O will be a challenge)
std::cin.tie(NULL);//Unties cin from cout for faster cin and cout functions (this does mean that they are off sync but if you are not using cin than it doesnt matter)
if(!glfwInit()) {
//Initialization failed
fprintf(stderr,"Failed to initialize GLFW\n");//Initialization error
return -1;//A -1 returned to the main function indicates a unsuccessful run
}
//Window hints change the way the window works (like settings)
glfwWindowHint(GLFW_SAMPLES,4);//4x antialiasing
//"Major" and "minor" are two components of a single version number, separated by a dot.
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);//Version 3...
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3);//.3
//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT,GL_TRUE);//To make MacOS happy; should not be needed
glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE);//We don't want the old OpenGL
const GLFWvidmode*mode=glfwGetVideoMode(glfwGetPrimaryMonitor());//Constant (not-changable) GLFWvideomode (variable type) is named "mode", is set to the primary monitor
glfwWindowHint(GLFW_RED_BITS,mode->redBits);
glfwWindowHint(GLFW_GREEN_BITS,mode->greenBits);
glfwWindowHint(GLFW_BLUE_BITS,mode->blueBits);
glfwWindowHint(GLFW_REFRESH_RATE,mode->refreshRate);
GLFWwindow*window=glfwCreateWindow(mode->width,mode->height,"My Title",glfwGetPrimaryMonitor(),NULL);//Create window that is the size of "mode" (constant primary monitor), named "", on the primary monitor
if(window==NULL) { //If glfw window does not exist
fprintf(stderr,"Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible.\n");
glfwTerminate();//End glfw processes
return -1;
}
glfwMakeContextCurrent(window);//Initialize GLEW
glewExperimental=true;//Needed in core profile
if(glewInit()!=GLEW_OK) { //If glew is not okay
fprintf(stderr,"Failed to initialize GLEW\n");
return -1;
}
glEnable(GL_DEPTH_TEST);
static const GLfloat g_vertex_buffer_data[]= { //Creates static (only runs once) constant (not-changable) array for VBO data
-1.0f,-1.0f,-1.0f, // triangle 1 : begin
-1.0f,-1.0f, 1.0f,
-1.0f, 1.0f, 1.0f, // triangle 1 : end
1.0f, 1.0f,-1.0f, // triangle 2 : begin
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f,-1.0f, // triangle 2 : end
1.0f,-1.0f, 1.0f,
-1.0f,-1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f,-1.0f,
1.0f,-1.0f, 1.0f,
-1.0f,-1.0f, 1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f,-1.0f, 1.0f,
1.0f,-1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f,-1.0f,
-1.0f, 1.0f,-1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f
};
GLuint vao;//Declares variable vbo, GLuint (opengl's unsigned interger)
glGenVertexArrays(1,&vao);
glBindVertexArray(vao);
//Upload this vertex data to the graphics card
GLuint vbo;//Declares variable vbo, GLuint (opengl's unsigned interger)
glGenBuffers(1,&vbo);//Generate 1 buffer
glBindBuffer(GL_ARRAY_BUFFER,vbo);//To upload the actual data to the graphics card you first have to make it the active object
glBufferData(GL_ARRAY_BUFFER,sizeof(g_vertex_buffer_data),g_vertex_buffer_data,GL_STATIC_DRAW);//Now that our VBO is active we can copy the vertex data to it
const char*vertexSource=R"glsl(
#version 150 core
in vec4 position;
uniform mat4 model;
uniform mat4 view;
uniform mat4 project;
void main()
{
gl_Position=project*view*model*position;
}
)glsl";
GLuint vertexShader=glCreateShader(GL_VERTEX_SHADER);//Creates shader object
glShaderSource(vertexShader,1,&vertexSource,NULL);//Loads data to shader object
glCompileShader(vertexShader);//Compiles shader object
//Vertex compile error message
//*
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if(!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
//*/
const char* fragmentSource=R"glsl(
#version 150 core
out vec4 outColor;
void main()
{
outColor = vec4(1.0, 0.5, 0.0, 1.0);
}
)glsl";
//The fragment shader is compiled in exactly the same way
GLuint fragmentShader=glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader,1,&fragmentSource,NULL);
glCompileShader(fragmentShader);
//Fragment compile error message
//*
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if(!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
//*/
//Combines shaders into one program
GLuint shaderProgram=glCreateProgram();//Create shader program
//Attatch vertex shader and fragment shader to new shader program
glAttachShader(shaderProgram,vertexShader);
glAttachShader(shaderProgram,fragmentShader);
glLinkProgram(shaderProgram);//Links shader program
//Shader program linking error message
//*
GLint linked;
int InfoLogLength;
glGetProgramiv(shaderProgram, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0) {
std::vector<char> ProgramErrorMessage(InfoLogLength+1);
glGetProgramInfoLog(shaderProgram, InfoLogLength, NULL, &ProgramErrorMessage[0]);
printf("%s\n", &ProgramErrorMessage[0]);
}
//*/
//To actually start using the shaders in the program, you just have to call:
glUseProgram(shaderProgram);
//You first need to retrieve a reference to the position input in the vertex shader
GLint posAttrib=glGetAttribLocation(shaderProgram,"position");
glVertexAttribPointer(posAttrib,3,GL_FLOAT,GL_FALSE,0,0);//Specify how the data for that input is retrieved from the array
glEnableVertexAttribArray(posAttrib);
glm::mat4 model = glm::mat4(1.0f);
model = glm::scale(model,glm::vec3(1.f));
model = glm::translate(model,glm::vec3(0.f,0.f,0.f));
glUniformMatrix4fv(glGetUniformLocation(shaderProgram,"model"),1,GL_FALSE,glm::value_ptr(model));
float apple;
glm::mat4 view = glm::lookAt(glm::vec3(0,0,1),glm::vec3(0,0,0),glm::vec3(0,1,0));
glUniformMatrix4fv(glGetUniformLocation(shaderProgram,"view"),1,GL_FALSE,glm::value_ptr(view));
std::cout<<glm::to_string(view);
glm::mat4 project = glm::perspective(90.0f,(float)mode->width/(float)mode->height,0.1f,-10.0f);
int prj_loc = glGetUniformLocation(shaderProgram,"project");
glUniformMatrix4fv(prj_loc,1,GL_FALSE,glm::value_ptr(project));
while(!glfwWindowShouldClose(window)){
glClearColor(0.5f,0.5f,0.5f,1.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES,0,12*3);
glfwSwapBuffers(window);
glfwPollEvents();
if(glfwGetKey(window,GLFW_KEY_RIGHT)==GLFW_PRESS)
apple+=0.1;
view = glm::rotate(view, glm::radians(apple),{0,1,0});
if(glfwGetKey(window,GLFW_KEY_LEFT)==GLFW_PRESS)
apple-=0.1;
view = glm::rotate(view, glm::radians(apple),{0,1,0});
if(glfwGetKey(window,GLFW_KEY_DOWN)==GLFW_PRESS)
apple=0;
if(glfwGetKey(window,GLFW_KEY_UP)==GLFW_PRESS)
apple=0;
glm::mat4 project = glm::perspective(90.0f,(float)mode->width/(float)mode->height,0.1f,100.0f);
int prj_loc = glGetUniformLocation(shaderProgram,"project");
glUniformMatrix4fv(prj_loc,1,GL_FALSE,glm::value_ptr(project));
glm::mat4 view = glm::lookAt(glm::vec3(0,0,5),glm::vec3(sin(apple)*5,0,cos(apple))*5,glm::vec3(0,1,0));
glUniformMatrix4fv(glGetUniformLocation(shaderProgram,"view"),1,GL_FALSE,glm::value_ptr(view));
}
glfwTerminate();
return 0;//A 0 returned to the main function indicates a successful run
}
答案 0 :(得分:0)
假设您想摆脱透视失真,而不是:
glm::mat4 project = glm::perspective(90.0f,(float)mode->width/(float)mode->height,0.1f,100.0f);
你可以尝试:
glm::mat4 project = glm::ortho(0.f,(float)mode->width/(float)mode->height,0.0,1.0,0.1f,100.0f);
为了设置正交投影。