OpenGL 试图渲染一个立方体,但平面之间有奇怪的线条
OpenGL Trying to render a cube but there are weird lines between planes
立方体渲染
嘿,我认为我将数据发送到顶点的方式或者我的索引使用 GL_CCW
排序的方式可能有误
struct Vertex
{
glm::vec3 position;
glm::vec3 color;
glm::vec3 normal;
};
使用顶点结构的顶点
Vertex vertices[] =
{
/*FRONT SQUARE*/
///BOTTOM LEFT
glm::vec3(-0.5f, -0.5f, 1.f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f),
///bottom RIGHT
glm::vec3(0.5f, -0.5f, 1.0f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f),
////TOP RIGHT
glm::vec3(0.5f, 0.5f, 1.0f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f),
///TOP LEFT
glm::vec3(-0.5f, 0.5f, 1.0f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f),
///BOTTOM LEFT
glm::vec3(-0.5f, -0.5f, -1.f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f),
///bottom RIGHT
glm::vec3(0.5f, -0.5f, -1.0f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f),
////TOP RIGHT
glm::vec3(0.5f, 0.5f, -1.0f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f),
///TOP LEFT
glm::vec3(-0.5f, 0.5f, -1.0f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f)
};
unsigned noOfVertices = sizeof(vertices) / sizeof(Vertex);
这是我的指数排序
GLuint indices[] =
{
// /front face
0, 1, 2,
2, 3, 0,
// right
1, 5, 6,
6, 2, 1,
// back
7, 6, 5,
5, 4, 7,
// left
4, 0, 3,
3, 7, 4,
// bottom
4, 5, 1,
1, 0, 4,
// top
3, 2, 6,
6, 7, 3
};
unsigned noOfIndices = sizeof(indices) / sizeof(GLuint);
主要功能和初始化window
int main()
{
启动window
///initialise GLFW for Window
if (glfwInit() == GLFW_FALSE)
{
std::cout << "ERROR::GLFW-INTI::FAILED" << "\n";
glfwTerminate();
}
///Create window with functions
GLFWwindow* window;
const int window_height = 480;
int window_width = 680;
int framebuffer_height = window_height;
int framebuffer_width = window_width;
char* title = "mytutorial";
int GLverMAJ = 3;
int GLverMin = 3;
///sets how the window should be drawn and which hints
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, GLverMAJ);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, GLverMin);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
///create the window with the previously set options
window = glfwCreateWindow(window_width, window_height, title, NULL, NULL);
//checks if window created
if (window == nullptr)
{
std::cout << "ERROR:::GLFWCREATEWINDOWFAILED" << "\n";
}
///sets the frame buffer size
glfwGetFramebufferSize(window, &framebuffer_width, &framebuffer_height);
glfwMakeContextCurrent(window);
//need to read on this part
glewExperimental = GL_TRUE;
//initiliase the glew
if (glewInit() != GLEW_OK)
{
std::cout << "ERROR::GLEWINIT::FAILED" << "\n";
}
初始化 opengl 选项
///enable functions first
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glEnable(GL_CULL_FACE);
//initialise the enabled functions
glCullFace(GL_BACK);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthFunc(GL_LESS);
///set the way its draw
glFrontFace(GL_CCW);
///set the polygon mode and fill ////Set as GL_LINE TO LOOK AT CUBE MESH
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
这是我初始化视图、项目和模型矩阵的地方
///初始化矩阵
///view
///front, position, up then use in lookat
glm::vec3 cameraPos(0.f, 0.f, 1.f);
glm::vec3 cameraUp(0.f, 1.f, 0.f);
glm::vec3 cameraFront(0.f, 0.f, -0.1f);
glm::mat4 ViewMatrix(1.f);
ViewMatrix = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);
///set up prespective projection
float fov = 90.f;
float nearPlane = -1.f;
float farPlane = 1000.f;
///projection
glm::mat4 ProjectionMatrix(1.f);
ProjectionMatrix = glm::perspective(glm::radians(fov), static_cast<float>(framebuffer_width / framebuffer_height), nearPlane, farPlane);
//Model Matrix
glm::mat4 ModelMatrix(1.f);
然后我创建我的着色器
///set up SHADERS
char infolog[512];
GLint success;
GLuint Vertexshader = glCreateShader(GL_VERTEX_SHADER);
///std::string str_src =
std::string temp = "";
std::string src = "";
std::ifstream infile;
infile.open("vert.glsl");
if (infile.is_open())
{
while (std::getline(infile, temp))
src += temp + "\n";
}
infile.close();
const GLchar* source = src.c_str();
///link created shader with shader source
glShaderSource(Vertexshader, 1, &source, NULL);
glCompileShader(Vertexshader);
///error check compilation status
glGetShaderiv(Vertexshader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(Vertexshader, 512, NULL, infolog);
std::cout << infolog;
}
success = 0;
GLuint FragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
///std::string str_src =
temp = "";
src = "";
infile.open("frag.glsl");
if (infile.is_open())
{
while (std::getline(infile, temp))
src += temp + "\n";
}
infile.close();
source = src.c_str();
///link created shader with shader source
glShaderSource(FragmentShader, 1, &source, NULL);
glCompileShader(FragmentShader);
///error check compilation status
glGetShaderiv(FragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(FragmentShader, 512, NULL, infolog);
std::cout << infolog;
}
Link 使用程序创建的着色器
///create and link the program
success = 0;
GLuint programID;
programID = glCreateProgram();
glAttachShader(programID, Vertexshader);
glAttachShader(programID, FragmentShader);
glLinkProgram(programID);
glGetProgramiv(programID, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(programID, 512, NULL, infolog);
std::cout << "ERROR::SHADER::COULD_NOT_LINK_PROGRAM" << "\n";
std::cout << infolog << "\n";
}
链接未使用和删除缓冲区后
///after linking we unuse the program and delete the shaders
glUseProgram(0);
glDeleteShader(Vertexshader);
glDeleteShader(FragmentShader);
这是我初始化 VAO VBO 和 EBO 的地方
///vbo, ebo and vertex array
GLuint VAO;
GLuint VBO;
GLuint EBO;
//gen and bind vao
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
///gen vbo
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, noOfVertices * sizeof(Vertex), vertices, GL_STATIC_DRAW);
///gen EBO
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, noOfIndices * sizeof(GLuint), indices, GL_STATIC_DRAW);
这是我觉得可能有问题的部分
///tell buffer where data is located
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, position));
glEnableVertexAttribArray(0);
//colour
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, color));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, normal));
glEnableVertexAttribArray(2);
glBindVertexArray(0);
///use program send in uniforms to the shader.
glUseProgram(programID);
///GLuint s = glGetUniformLocation(programID, "ViewMatrix");
GLuint s = glGetUniformLocation(programID, "ModelMatrix");
glUniformMatrix4fv(s, 1, GL_FALSE, glm::value_ptr(ModelMatrix));
s = glGetUniformLocation(programID, "ProjectionMatrix");
glUniformMatrix4fv(s, 1, GL_FALSE, glm::value_ptr(ProjectionMatrix));
s = glGetUniformLocation(programID, "ViewMatrix");
glUniformMatrix4fv(s, 1, GL_FALSE, glm::value_ptr(ViewMatrix));
glUseProgram(0);
///main while loop
while (!glfwWindowShouldClose(window))
{
//clear
glClearColor(0.f, 0.f, 0.f, 1.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
///draw
glfwPollEvents();
glUseProgram(programID);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, noOfIndices, GL_UNSIGNED_INT, 0);
///flush
glfwSwapBuffers(window);
glFlush();
///unuse
glBindVertexArray(0);
glUseProgram(0);
}
return 0;
}
对我来说,您的程序似乎运行正常。如果我没记错的话,那么你的相机位于立方体内部,从其中一张脸的位置直视另一侧的脸。在这种情况下,您所看到的正是人们期望看到的。在图像的中央,您有两个三角形,它们构成了您正在看的脸的背面。您得到的 "weird lines" 只是构成其他面的三角形的边。由于您的相机位于立方体内部,因此这些面一定会一直延伸到您的相机后面,并且所有东西都会在近平面处被切断,这是您从 "encloses" 所有东西中获得外部矩形的地方。
因为这个
一切都有点压扁
static_cast<float>(framebuffer_width / framebuffer_height)
不会产生您最可能希望的效果。你这里还在做整数除法
此外,我不确定您对近平面使用负值的确切预期效果是什么。很可能,它也不是您真正想要的,我建议您使用一些正值,例如 0.1f
那里...
近平面和远平面都必须为正值,因为 glm::perspective
并且 static_cast<float>(framebuffer_width / framebuffer_height)
将是整数除法:
float fov = 90.f;
float nearPlane = 0.1f; // 0.1 instead of -1.0
float farPlane = 1000.f;
glm::mat4 ProjectionMatrix(1.f);
ProjectionMatrix = glm::perspective(glm::radians(fov),
static_cast<float>(framebuffer_width) / static_cast<float>(framebuffer_height),
nearPlane, farPlane);
GLM_FUNC_DECL mat<4, 4, T, defaultp> glm::perspective(
T fovy,
T aspect,
T near,
T far
)
[...]
near
Specifies the distance from the viewer to the near clipping plane (always positive).
far
Specifies the distance from the viewer to the far clipping plane (always positive).
glm 库提供与 OpenGL 和 GLSL 相关的矩阵运算。 glm API documentation refers to The OpenGL Shading Language specification 4.20。
参见The OpenGL Shading Language 4.6, 5.4.2 Vector and Matrix Constructors, page 101:
To initialize a matrix by specifying vectors or scalars, the components are assigned to the matrix elements in column-major order.
mat4(float, float, float, float, // first column
float, float, float, float, // second column
float, float, float, float, // third column
float, float, float, float); // fourth column
这意味着顶点着色器中顶点坐标的变换必须是:
gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * vec4(vertex_position,1.0);
另见 GLSL Programming/Vector and Matrix Operations:
通过将 glUniformMatrix4fv
的第 3 个参数设置为 GL_TRUE
,当设置为 uniform 时矩阵可能会被转置:
GLuint s = glGetUniformLocation(programID, "ModelMatrix");
glUniformMatrix4fv(s, 1, GL_TRUE, glm::value_ptr(ModelMatrix));
s = glGetUniformLocation(programID, "ProjectionMatrix");
glUniformMatrix4fv(s, 1, GL_TRUE, glm::value_ptr(ProjectionMatrix));
s = glGetUniformLocation(programID, "ViewMatrix");
glUniformMatrix4fv(s, 1, GL_TRUE, glm::value_ptr(ViewMatrix));
并以相反的顺序计算顶点坐标变换:
gl_Position = vec4(vertex_position,1.0) * ModelMatrix * ViewMatrix * ProjectionMatrix;
另外,立方体a的面的缠绕顺序是顺时针的,所以必须是:
glFrontFace(GL_CCW);
glFrontFace(GL_CW);
将相机位置更改为
glm::vec3 cameraPos(0.f, 0.f, 2.f);
你会得到以下结果:
立方体渲染
嘿,我认为我将数据发送到顶点的方式或者我的索引使用 GL_CCW
排序的方式可能有误struct Vertex
{
glm::vec3 position;
glm::vec3 color;
glm::vec3 normal;
};
使用顶点结构的顶点
Vertex vertices[] =
{
/*FRONT SQUARE*/
///BOTTOM LEFT
glm::vec3(-0.5f, -0.5f, 1.f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f),
///bottom RIGHT
glm::vec3(0.5f, -0.5f, 1.0f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f),
////TOP RIGHT
glm::vec3(0.5f, 0.5f, 1.0f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f),
///TOP LEFT
glm::vec3(-0.5f, 0.5f, 1.0f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f),
///BOTTOM LEFT
glm::vec3(-0.5f, -0.5f, -1.f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f),
///bottom RIGHT
glm::vec3(0.5f, -0.5f, -1.0f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f),
////TOP RIGHT
glm::vec3(0.5f, 0.5f, -1.0f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f),
///TOP LEFT
glm::vec3(-0.5f, 0.5f, -1.0f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f)
};
unsigned noOfVertices = sizeof(vertices) / sizeof(Vertex);
这是我的指数排序
GLuint indices[] =
{
// /front face
0, 1, 2,
2, 3, 0,
// right
1, 5, 6,
6, 2, 1,
// back
7, 6, 5,
5, 4, 7,
// left
4, 0, 3,
3, 7, 4,
// bottom
4, 5, 1,
1, 0, 4,
// top
3, 2, 6,
6, 7, 3
};
unsigned noOfIndices = sizeof(indices) / sizeof(GLuint);
主要功能和初始化window
int main()
{
启动window
///initialise GLFW for Window
if (glfwInit() == GLFW_FALSE)
{
std::cout << "ERROR::GLFW-INTI::FAILED" << "\n";
glfwTerminate();
}
///Create window with functions
GLFWwindow* window;
const int window_height = 480;
int window_width = 680;
int framebuffer_height = window_height;
int framebuffer_width = window_width;
char* title = "mytutorial";
int GLverMAJ = 3;
int GLverMin = 3;
///sets how the window should be drawn and which hints
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, GLverMAJ);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, GLverMin);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
///create the window with the previously set options
window = glfwCreateWindow(window_width, window_height, title, NULL, NULL);
//checks if window created
if (window == nullptr)
{
std::cout << "ERROR:::GLFWCREATEWINDOWFAILED" << "\n";
}
///sets the frame buffer size
glfwGetFramebufferSize(window, &framebuffer_width, &framebuffer_height);
glfwMakeContextCurrent(window);
//need to read on this part
glewExperimental = GL_TRUE;
//initiliase the glew
if (glewInit() != GLEW_OK)
{
std::cout << "ERROR::GLEWINIT::FAILED" << "\n";
}
初始化 opengl 选项
///enable functions first
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glEnable(GL_CULL_FACE);
//initialise the enabled functions
glCullFace(GL_BACK);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthFunc(GL_LESS);
///set the way its draw
glFrontFace(GL_CCW);
///set the polygon mode and fill ////Set as GL_LINE TO LOOK AT CUBE MESH
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
这是我初始化视图、项目和模型矩阵的地方
///初始化矩阵
///view
///front, position, up then use in lookat
glm::vec3 cameraPos(0.f, 0.f, 1.f);
glm::vec3 cameraUp(0.f, 1.f, 0.f);
glm::vec3 cameraFront(0.f, 0.f, -0.1f);
glm::mat4 ViewMatrix(1.f);
ViewMatrix = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);
///set up prespective projection
float fov = 90.f;
float nearPlane = -1.f;
float farPlane = 1000.f;
///projection
glm::mat4 ProjectionMatrix(1.f);
ProjectionMatrix = glm::perspective(glm::radians(fov), static_cast<float>(framebuffer_width / framebuffer_height), nearPlane, farPlane);
//Model Matrix
glm::mat4 ModelMatrix(1.f);
然后我创建我的着色器
///set up SHADERS
char infolog[512];
GLint success;
GLuint Vertexshader = glCreateShader(GL_VERTEX_SHADER);
///std::string str_src =
std::string temp = "";
std::string src = "";
std::ifstream infile;
infile.open("vert.glsl");
if (infile.is_open())
{
while (std::getline(infile, temp))
src += temp + "\n";
}
infile.close();
const GLchar* source = src.c_str();
///link created shader with shader source
glShaderSource(Vertexshader, 1, &source, NULL);
glCompileShader(Vertexshader);
///error check compilation status
glGetShaderiv(Vertexshader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(Vertexshader, 512, NULL, infolog);
std::cout << infolog;
}
success = 0;
GLuint FragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
///std::string str_src =
temp = "";
src = "";
infile.open("frag.glsl");
if (infile.is_open())
{
while (std::getline(infile, temp))
src += temp + "\n";
}
infile.close();
source = src.c_str();
///link created shader with shader source
glShaderSource(FragmentShader, 1, &source, NULL);
glCompileShader(FragmentShader);
///error check compilation status
glGetShaderiv(FragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(FragmentShader, 512, NULL, infolog);
std::cout << infolog;
}
Link 使用程序创建的着色器
///create and link the program
success = 0;
GLuint programID;
programID = glCreateProgram();
glAttachShader(programID, Vertexshader);
glAttachShader(programID, FragmentShader);
glLinkProgram(programID);
glGetProgramiv(programID, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(programID, 512, NULL, infolog);
std::cout << "ERROR::SHADER::COULD_NOT_LINK_PROGRAM" << "\n";
std::cout << infolog << "\n";
}
链接未使用和删除缓冲区后
///after linking we unuse the program and delete the shaders
glUseProgram(0);
glDeleteShader(Vertexshader);
glDeleteShader(FragmentShader);
这是我初始化 VAO VBO 和 EBO 的地方
///vbo, ebo and vertex array
GLuint VAO;
GLuint VBO;
GLuint EBO;
//gen and bind vao
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
///gen vbo
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, noOfVertices * sizeof(Vertex), vertices, GL_STATIC_DRAW);
///gen EBO
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, noOfIndices * sizeof(GLuint), indices, GL_STATIC_DRAW);
这是我觉得可能有问题的部分
///tell buffer where data is located
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, position));
glEnableVertexAttribArray(0);
//colour
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, color));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, normal));
glEnableVertexAttribArray(2);
glBindVertexArray(0);
///use program send in uniforms to the shader.
glUseProgram(programID);
///GLuint s = glGetUniformLocation(programID, "ViewMatrix");
GLuint s = glGetUniformLocation(programID, "ModelMatrix");
glUniformMatrix4fv(s, 1, GL_FALSE, glm::value_ptr(ModelMatrix));
s = glGetUniformLocation(programID, "ProjectionMatrix");
glUniformMatrix4fv(s, 1, GL_FALSE, glm::value_ptr(ProjectionMatrix));
s = glGetUniformLocation(programID, "ViewMatrix");
glUniformMatrix4fv(s, 1, GL_FALSE, glm::value_ptr(ViewMatrix));
glUseProgram(0);
///main while loop
while (!glfwWindowShouldClose(window))
{
//clear
glClearColor(0.f, 0.f, 0.f, 1.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
///draw
glfwPollEvents();
glUseProgram(programID);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, noOfIndices, GL_UNSIGNED_INT, 0);
///flush
glfwSwapBuffers(window);
glFlush();
///unuse
glBindVertexArray(0);
glUseProgram(0);
}
return 0;
}
对我来说,您的程序似乎运行正常。如果我没记错的话,那么你的相机位于立方体内部,从其中一张脸的位置直视另一侧的脸。在这种情况下,您所看到的正是人们期望看到的。在图像的中央,您有两个三角形,它们构成了您正在看的脸的背面。您得到的 "weird lines" 只是构成其他面的三角形的边。由于您的相机位于立方体内部,因此这些面一定会一直延伸到您的相机后面,并且所有东西都会在近平面处被切断,这是您从 "encloses" 所有东西中获得外部矩形的地方。
因为这个
一切都有点压扁static_cast<float>(framebuffer_width / framebuffer_height)
不会产生您最可能希望的效果。你这里还在做整数除法
此外,我不确定您对近平面使用负值的确切预期效果是什么。很可能,它也不是您真正想要的,我建议您使用一些正值,例如 0.1f
那里...
近平面和远平面都必须为正值,因为 glm::perspective
并且 static_cast<float>(framebuffer_width / framebuffer_height)
将是整数除法:
float fov = 90.f;
float nearPlane = 0.1f; // 0.1 instead of -1.0
float farPlane = 1000.f;
glm::mat4 ProjectionMatrix(1.f);
ProjectionMatrix = glm::perspective(glm::radians(fov),
static_cast<float>(framebuffer_width) / static_cast<float>(framebuffer_height),
nearPlane, farPlane);
GLM_FUNC_DECL mat<4, 4, T, defaultp> glm::perspective( T fovy, T aspect, T near, T far )
[...]
near
Specifies the distance from the viewer to the near clipping plane (always positive).
far
Specifies the distance from the viewer to the far clipping plane (always positive).
glm 库提供与 OpenGL 和 GLSL 相关的矩阵运算。 glm API documentation refers to The OpenGL Shading Language specification 4.20。
参见The OpenGL Shading Language 4.6, 5.4.2 Vector and Matrix Constructors, page 101:
To initialize a matrix by specifying vectors or scalars, the components are assigned to the matrix elements in column-major order.
mat4(float, float, float, float, // first column float, float, float, float, // second column float, float, float, float, // third column float, float, float, float); // fourth column
这意味着顶点着色器中顶点坐标的变换必须是:
gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * vec4(vertex_position,1.0);
另见 GLSL Programming/Vector and Matrix Operations:
通过将 glUniformMatrix4fv
的第 3 个参数设置为 GL_TRUE
,当设置为 uniform 时矩阵可能会被转置:
GLuint s = glGetUniformLocation(programID, "ModelMatrix");
glUniformMatrix4fv(s, 1, GL_TRUE, glm::value_ptr(ModelMatrix));
s = glGetUniformLocation(programID, "ProjectionMatrix");
glUniformMatrix4fv(s, 1, GL_TRUE, glm::value_ptr(ProjectionMatrix));
s = glGetUniformLocation(programID, "ViewMatrix");
glUniformMatrix4fv(s, 1, GL_TRUE, glm::value_ptr(ViewMatrix));
并以相反的顺序计算顶点坐标变换:
gl_Position = vec4(vertex_position,1.0) * ModelMatrix * ViewMatrix * ProjectionMatrix;
另外,立方体a的面的缠绕顺序是顺时针的,所以必须是:
glFrontFace(GL_CCW);
glFrontFace(GL_CW);
将相机位置更改为
glm::vec3 cameraPos(0.f, 0.f, 2.f);
你会得到以下结果: