opengl 矩阵变换
opengl 坐标系的变换如下图:
我们给我们的图形,设置好顶点坐标后,通过Model Matrix 变换为世界坐标,然后 view Matrix相机坐标,Projection Matrix 屏幕坐标x,y ∈(-1,1)。
矩阵变换的结果是把三维的世界最终裁剪为二维的屏幕,数学的说法就是从一个集合到另一个集合的映射。
#include "glew.h"
#include
#include "common/loadShader.h"
#include "glm.hpp"
#include "ext.hpp"
int main(void)
{
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
return -1;
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(480, 320, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
// Needed in core profile
if( glewInit() != GLEW_OK)
{
glfwTerminate();
return -1;
}
// An array of 3 vectors which represents 3 vertices
static const GLfloat g_vertex_buffer_data[] = {
-1.0f,-1.0f,0.0f,
1.0f,-1.0f,0.0f,
0.0f,1.0f,0.0f,
};
//This will identify our vertex buffer
GLuint vertexbuffer;
//Generate 1 buffer,put the resulting identifier in vertexbuffer
glGenBuffers(1,&vertexbuffer);
//The following commands will talk about our 'vertexbuffer' buffer
glBindBuffer(GL_ARRAY_BUFFER,vertexbuffer);
//Give our vertices to OpenGL.
glBufferData(GL_ARRAY_BUFFER,sizeof(g_vertex_buffer_data),g_vertex_buffer_data,GL_STATIC_DRAW);
GLuint programID = LoadShaders("./shader/vertex.shader","./shader/fragment.shader");
glUseProgram(programID);
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
/* Loop until the user closes the window */
// Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit 100 units
//glm::mat4 Projection = glm::ortho(-4.0f/3.0f, 4.0f/3.0f, -1.0f, 1.0f, 0.1f, 100.0f);
glm::mat4 Projection = glm::perspective(45.0f,4.0f/3.0f,0.1f,100.f);
glm::mat4 View = glm::lookAt(
glm::vec3(4,3,3), // Camera is at (4,3,3), in World Space
glm::vec3(0,0,0), // and looks at the origin
glm::vec3(0,1,0) // Head is up (set to 0,-1,0 to look upside-down)
);
// Model matrix : an identity matrix (model will be at the origin)
glm::mat4 Model = glm::mat4(1.0f);
Model = glm::translate(Model,glm::vec3(2.0f,0.0f,0.0f));
Model = glm::rotate(Model,45.f,glm::vec3(0.0f,1.0f,0.0f));
Model = glm::scale(Model,glm::vec3(1.0f,2.0f,1.0f));
// Our ModelViewProjection : multiplication of our 3 matrices
glm::mat4 MVP = Projection * View * Model;// Remember, matrix multiplication is the other way around
// Get a handle for our "MVP" uniform.
// Only at initialisation time.
GLuint MatrixID = glGetUniformLocation(programID,"MVP");
// Send our transformation to the currently bound shader,
// in the "MVP" uniform
// For each model you render, since the MVP will be different (at least the M part)
glUniformMatrix4fv(MatrixID,1,GL_FALSE,&MVP[0][0]);
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnableVertexAttribArray(0);
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
glDrawArrays(GL_TRIANGLES,0,3);// Starting from vertex 0; 3 vertices total -> 1 triangle
glDisableVertexAttribArray(0);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}
首先,model为一个单位矩阵,glm::mat4 Model = glm::mat4(1.0f);
然后平移,旋转,缩放,
Model = glm::translate(Model,glm::vec3(2.0f,0.0f,0.0f));
Model = glm::rotate(Model,45.f,glm::vec3(0.0f,1.0f,0.0f));
Model = glm::scale(Model,glm::vec3(1.0f,2.0f,1.0f));
最后通过矩阵乘法,连接到一起。
glm::mat4 Projection = glm::perspective(45.0f,4.0f/3.0f,0.1f,100.f);
glm::mat4 View = glm::lookAt(
glm::vec3(4,3,3), // Camera is at (4,3,3), in World Space
glm::vec3(0,0,0), // and looks at the origin
glm::vec3(0,1,0) // Head is up (set to 0,-1,0 to look upside-down)
);
// Our ModelViewProjection : multiplication of our 3 matrices
glm::mat4 MVP = Projection * View * Model;// Remember, matrix multiplication is the other way around
得到shader中变量指针
GLuint MatrixID = glGetUniformLocation(programID,"MVP");
将矩阵传入shader
glUniformMatrix4fv(MatrixID,1,GL_FALSE,&MVP[0][0]);
来看shader的语法:
#version 330 core
layout(location = 0) in vec3 vertexPosition_modelspace;
uniform mat4 MVP;
void main(){
vec4 v = vec4(vertexPosition_modelspace,1);
gl_Position = MVP * v;
}
shader里将当前顶点与之前矩阵相乘。