前言

跟着LearnOpenGL上学着做项目,的确对于知识掌握得更清晰一些了。

第一个项目

第一个项目,是关于简单的熟悉矩阵变换的,创建了10个立方体,代码如下。

 // 视图矩阵,看作是一个照相机
glm::mat4 view;
view = glm::translate(view, glm::vec3(0.0f, 0.0f, -6.0f));
view = glm::rotate(view, glm::radians(15.0f), glm::vec3(0.0f, 0.0f, 1.0f)); // 模型矩阵
glm::mat4 projection;
projection = glm::perspective(glm::radians(45.0f), static_cast<GLfloat>(WIDTH) / static_cast<GLfloat>(HEIGHT), 0.001f, 100.0f); glUniformMatrix4fv(glGetUniformLocation(shader.program, "view"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(shader.program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); while (!glfwWindowShouldClose(window))
{
glfwPollEvents(); // 因为已经涉及到了3d,所以需要开启深度测试,并且要每一帧都要清除颜色缓存和深度缓存 glClearColor(0.298f, 0.451f, 0.773f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glBindVertexArray(VAO); // 创建10个正方体
for (GLuint i = 0; i < 10; ++i) {
glm::mat4 model;
model = glm::translate(model, cubePositions[i]); if (i % 2) {
// 固定的旋转的角度
model = glm::rotate(model, glm::radians(20.0f * i), glm::vec3(0.0f, 0.3f, 0.5f));
}
else {
// 随时间旋转的角度
model = glm::rotate(model, glm::radians<GLfloat>(glfwGetTime() * 20.0f), glm::vec3(0.0f, 1.0f, 0.5f));
} glUniformMatrix4fv(glGetUniformLocation(shader.program, "model"), 1, GL_FALSE, glm::value_ptr(model)); // 一个四边形由两个三角形组成,两个三角形则包括了6个索引,所以6个面则需要36个索引
glDrawArrays(GL_TRIANGLES, 0, 36);
} glBindVertexArray(0); glfwSwapBuffers(window);
}

第二个项目

这个项目稍微复杂,涉及到了坐标系,摄像机的知识。

#include <iostream>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "SOIL.h"
#include "Shader.h" #include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp> const GLuint WIDTH = 800, HEIGHT = 600;
GLfloat mixValue = 0.2f; //------------------------------------2.----------------------------------
glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f);
// 为什么是负的呢,因为要知道摄像机指向的是z轴的负方向
glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f); //------------------------------------3.----------------------------------
bool keys[1024];//用来存储哪些按键被按下 //------------------------------------4.----------------------------------
GLfloat deltaTime = 0.0f; //当前帧和上一帧的时间差
GLfloat lastFrame = 0.0f; //上一帧时间 //------------------------------------5.----------------------------------
GLfloat yaw = -90.0f; // Yaw is initialized to -90.0 degrees since a yaw of 0.0 results in a direction vector pointing to the right (due to how Eular angles work) so we initially rotate a bit to the left.
//为偏航角
GLfloat pitch = 0.0f; //为俯仰角
GLfloat lastX = WIDTH / 2.0;
GLfloat lastY = HEIGHT / 2.0;
bool firstMouse = true; GLfloat fov = 1.0f; void isDoMovement() {
//------------------------------------3.----------------------------------
// GLfloat speed = 0.2f; //------------------------------------4.----------------------------------
GLfloat speed = 5.0f * deltaTime; // 照相机向z轴负方向移动
if (keys[GLFW_KEY_W]) {
cameraPos += cameraFront * speed;
}
// 照相机向z轴正方向移动
else if (keys[GLFW_KEY_S]) {
cameraPos -= cameraFront * speed;
}
// 照相机向x轴负方向
else if (keys[GLFW_KEY_A]) {
//cross表示叉乘,求出对于参数中的两个向量都垂直的向量,求完了以后还需要进行归一化得到向量
cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp)) * speed;
}
// 照相机向x轴正方向
else if (keys[GLFW_KEY_D]) {
cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp)) * speed;
}
} void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) {
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
glfwSetWindowShouldClose(window, GL_TRUE);
} // if (key == GLFW_KEY_UP && action == GLFW_PRESS)
// {
// mixValue += 0.1f;
// if (mixValue >= 1.0f)
// mixValue = 1.0f;
// }
// if (key == GLFW_KEY_DOWN && action == GLFW_PRESS)
// {
// mixValue -= 0.1f;
// if (mixValue <= 0.0f)
// mixValue = 0.0f;
// } //------------------------------------2.----------------------------------
// GLfloat speed = 0.2f;
//
// // 照相机向z轴负方向移动
// if (key == GLFW_KEY_W) {
// cameraPos += cameraFront * speed;
// }
// // 照相机向z轴正方向移动
// else if (key == GLFW_KEY_S) {
// cameraPos -= cameraFront * speed;
// }
// // 照相机向x轴负方向
// else if (key == GLFW_KEY_A) {
// //cross表示叉乘,求出对于参数中的两个向量都垂直的向量,求完了以后还需要进行归一化得到向量
// cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp)) * speed;
// }
// // 照相机向x轴正方向
// else if (key == GLFW_KEY_D) {
// cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp)) * speed;
// } //------------------------------------3.----------------------------------
// 在第三种方法中,这个函数用来监听
// 先判断有没有按下,不再按下的时候,把该按下的按键进行重置
if(action == GLFW_PRESS) {
// 照相机向z轴负方向移动
if (key == GLFW_KEY_W) {
keys[key] = true;
}
// 照相机向z轴正方向移动
else if (key == GLFW_KEY_S) {
keys[key] = true;
}
// 照相机向x轴负方向
else if (key == GLFW_KEY_A) {
//cross表示叉乘,求出对于参数中的两个向量都垂直的向量,求完了以后还需要进行归一化得到向量
keys[key] = true;
}
// 照相机向x轴正方向
else if (key == GLFW_KEY_D) {
keys[key] = true;
}
}
else if(action == GLFW_RELEASE) {
keys[key] = false;
}
} //------------------------------------5.----------------------------------
// 其中的xpos和ypos代表的是鼠标x和y的位置,摄像头上下左右指向
void mouse_callback(GLFWwindow* window, double xpos, double ypos) {
// 第一次移动鼠标
if(firstMouse)
{
//对上一帧x和y的方向上的位置进行赋值
lastX = xpos;
lastY = ypos;
firstMouse = false;
} GLfloat xoffset = xpos - lastX;//计算x轴上的偏移量
GLfloat yoffset = lastY - ypos;//计算y轴上的偏移量
lastX = xpos;
lastY = ypos; GLfloat sensitivity = 0.05;
xoffset *= sensitivity;
yoffset *= sensitivity; yaw += xoffset;
pitch += yoffset; if(pitch > 89.0f)
pitch = 89.0f;
if(pitch < -89.0f)
pitch = -89.0f; glm::vec3 front;
front.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));//同求z的原理
front.y = sin(glm::radians(pitch)); // 以xz作为一个平面,y轴向上,形成一个三角形,可以用sin求出俯仰角的移动
front.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));// cos则可以求出xz平面,其中xz平面,z轴向上,x轴向右,可以根据sin偏航角计算出z
cameraFront = glm::normalize(front); //归一化
} //摄像头靠近或者进行远离
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
if(fov >= 1.0f && fov <= 45.0f)
fov -= yoffset * 0.05f; //如果在规定的fov范围,可以进行减小,超过则进行重置
if(fov <= 1.0f)
fov = 1.0f;
if(fov >= 45.0f)
fov = 45.0f;
} int main() {
glfwInit();
// glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
// glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
// glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "OpenGL", nullptr, nullptr);
if (window == nullptr)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window); glfwSetKeyCallback(window, key_callback); glfwSetCursorPosCallback(window, mouse_callback);
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
glfwSetScrollCallback(window, scroll_callback); glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
std::cout << "Failed to initialize GLEW" << std::endl;
return -1;
} glViewport(0, 0, WIDTH, HEIGHT); // ¯ÂȉÂ˚
Shader shader("/Users/staff/Desktop/practise/fgh/fgh/vertexShader.vsh", "/Users/staff/Desktop/practise/fgh/fgh/fragmentShader.fsh"); // ÚÂÍÒÚÛ‡ 1
GLuint texture1;
glGenTextures(1, &texture1);
glBindTexture(GL_TEXTURE_2D, texture1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); int width, height;
unsigned char* image = SOIL_load_image("/Users/staff/Desktop/practise/fgh/fgh/wall.jpg", &width, &height, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image);
glBindTexture(GL_TEXTURE_2D, 0); // ÚÂÍÒÚÛ‡ 2
GLuint texture2;
glGenTextures(1, &texture2);
glBindTexture(GL_TEXTURE_2D, texture2); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); image = SOIL_load_image("/Users/staff/Desktop/practise/fgh/fgh/awesomeface.png", &width, &height, 0, SOIL_LOAD_RGBA);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image);
glBindTexture(GL_TEXTURE_2D, 0); // 6个面上的顶点信息
GLfloat vertices[] = {
// Positions // Texture Coords //colors
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f
}; GLuint VBO, VAO, EBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); GLuint _positionSlot = glGetAttribLocation(shader.program, "position");
GLuint _colorSlot = glGetAttribLocation(shader.program, "color");
GLuint _textureCoordsSlot = glGetAttribLocation(shader.program, "texCoord");
//GLuint _textureSlot = glGetUniformLocation(shader.program, "ourTexture"); glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(_positionSlot); glVertexAttribPointer(_textureCoordsSlot, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(_textureCoordsSlot); glVertexAttribPointer(_colorSlot, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
glEnableVertexAttribArray(_colorSlot); glBindVertexArray(0); // 10个立方体的位置
glm::vec3 cubePositions[] = {
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(2.0f, 5.0f, -15.0f),
glm::vec3(-1.5f, -2.2f, -2.5f),
glm::vec3(-3.8f, -2.0f, -12.3f),
glm::vec3(2.4f, -0.4f, -3.5f),
glm::vec3(-1.7f, 3.0f, -7.5f),
glm::vec3(1.3f, -2.0f, -2.5f),
glm::vec3(1.5f, 2.0f, -2.5f),
glm::vec3(1.5f, 0.2f, -1.5f),
glm::vec3(-1.3f, 1.0f, -1.5f)
}; while (!glfwWindowShouldClose(window))
{
glfwPollEvents();
//------------------------------------4.----------------------------------
GLfloat curTime = glfwGetTime();
deltaTime = curTime - lastFrame;
lastFrame = curTime; //------------------------------------3.----------------------------------
isDoMovement(); // 因为已经涉及到了3d,所以需要开启深度测试,并且要每一帧都要清除颜色缓存和深度缓存 glClearColor(0.298f, 0.451f, 0.773f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); shader.use(); glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1);
glUniform1i(glGetUniformLocation(shader.program, "ourTexture1"), 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);
glUniform1i(glGetUniformLocation(shader.program, "ourTexture2"), 1);
glUniform1f(glGetUniformLocation(shader.program, "mixValue"), mixValue); //----------------------------------------1.-------------------------------------------
glm::mat4 view;
// 照相机向量
// GLfloat radius = 20.0f;
// GLfloat camX = sinf(glfwGetTime()) * radius;
// GLfloat camZ = cosf(glfwGetTime()) * radius;
// // 首先要知道lookAt函数的参数的意思,分别是eye,center,up,分别代表的是摄像机的位置向量,目标,上向量
// // 这里实现的是照相机绕着顶点(0,0,0)进行旋转
// view = glm::lookAt(glm::vec3(camX, 0.0f, camZ), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f)); //----------------------------------------2.-------------------------------------------
//view = glm::lookAt(cameraPos, glm::vec3(0.0f, 0.0f, 0.0f), cameraUp); //----------------------------------------5.-------------------------------------------
view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp); // 模型矩阵
glm::mat4 projection; // projection = glm::perspective(glm::radians(45.0f), static_cast<GLfloat>(WIDTH) / static_cast<GLfloat>(HEIGHT), 0.001f, 100.0f); //----------------------------------------5.-------------------------------------------
projection = glm::perspective(fov, (GLfloat)WIDTH/(GLfloat)HEIGHT, 0.1f, 100.0f); glUniformMatrix4fv(glGetUniformLocation(shader.program, "view"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(shader.program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); glBindVertexArray(VAO);
// 创建10个正方体
for (GLuint i = 0; i < 10; ++i) {
glm::mat4 model;
model = glm::translate(model, cubePositions[i]); if (i % 2) {
// 固定的旋转的角度
model = glm::rotate(model, glm::radians(20.0f * i), glm::vec3(0.0f, 0.3f, 0.5f));
}
else {
// 随时间旋转的角度
model = glm::rotate(model, glm::radians<GLfloat>(glfwGetTime() * 20.0f), glm::vec3(0.0f, 1.0f, 0.5f));
} glUniformMatrix4fv(glGetUniformLocation(shader.program, "model"), 1, GL_FALSE, glm::value_ptr(model)); // 一个四边形由两个三角形组成,两个三角形则包括了6个索引,所以6个面则需要36个索引
glDrawArrays(GL_TRIANGLES, 0, 36);
} glBindVertexArray(0); glfwSwapBuffers(window);
} // Û‰‡ÎˇÂÏ, Á‡‚Â¯‡ÂÏ
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO); glfwTerminate(); return 0;
}

这里面的1,2,3,4,5分别是版本的演化;

  1. 其中1是最开始的版本:增加了照相机向量,不过是固定的;
  2. 其中2是增加了摄像机移动的功能;
  3. 其中3是因为2无法实现同时按下两个按键进行移动的功能,因为用数组进行记录,最后统一处理;
  4. 其中4是因为3中的移动距离在每个机器上都不太一样,有的会在同一时间段内比其他人绘制更多帧,导致运动速度会变得大,造成效果不好,因此,增加时间差,记录时间差,乘以固定的值,如果时间差变大时,意味着上一帧渲染时间多,那就会得到更高的移动速度,否之,则相反。这样就会和上一帧平衡了。这就好比走路和跑步,跑步的移动速度肯定是要高于走路,总不能要求走路和跑步的移动速度是一样的吧。
  5. 其中5则在之前的基础上增加了上下左右移动摄像机,以及通过滚轮实现靠近和远离的功能。这里面涉及到了许多的数学知识,不过不是很难,仔细看看教程还是能看懂的。

教程地址

第二个项目的延伸

之所以说是延伸是因为,第二个项目所有东西都堆在了一起,耦合程度高,因此教程把这些都封装了起来。

.h文件

#pragma once
#include <vector>
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp> enum Camera_Movement {
FORWARD,
BACKWARD,
LEFT,
RIGHT
}; const GLfloat YAW = -90.0f;
const GLfloat PITCH = 0.0f;
const GLfloat SPEED = 3.0f;
const GLfloat SENSITIVTY = 0.25f;
const GLfloat ZOOM = 45.0f; class Camera {
public:
glm::vec3 Position;
glm::vec3 Front;
glm::vec3 Up;
glm::vec3 Right;
glm::vec3 WorldUp;
GLfloat Yaw;
GLfloat Pitch;
GLfloat MovementSpeed;
GLfloat MouseSensitivity;
GLfloat Zoom; Camera(glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f), GLfloat yaw = YAW, GLfloat pitch = PITCH);
Camera(GLfloat posX, GLfloat posY, GLfloat posZ, GLfloat upX, GLfloat upY, GLfloat upZ, GLfloat yaw, GLfloat pitch);
glm::mat4 GetViewMatrix();
// 处理按键事件
void ProcessKeyboard(Camera_Movement direction, GLfloat deltaTime);
// 处理鼠标移动事件
void ProcessMouseMovement(GLfloat xoffset, GLfloat yoffset, GLboolean constrainPitch = true);
// 处理鼠标滚动事件
void ProcessMouseScroll(GLfloat yoffset);
private:
void updateCameraVectors();
};

.cpp文件

#include "Camera.h"

Camera::Camera(glm::vec3 position, glm::vec3 up, GLfloat yaw, GLfloat pitch)
: Front(glm::vec3(0.0f, 0.0f, -1.0f))
, MovementSpeed(SPEED)
, MouseSensitivity(SENSITIVTY)
, Zoom(ZOOM)
{
Position = position;
WorldUp = up;
Yaw = yaw;
Pitch = pitch;
updateCameraVectors();
} Camera::Camera(GLfloat posX, GLfloat posY, GLfloat posZ, GLfloat upX, GLfloat upY, GLfloat upZ, GLfloat yaw, GLfloat pitch) : Front(glm::vec3(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVTY), Zoom(ZOOM)
{
Position = glm::vec3(posX, posY, posZ);
WorldUp = glm::vec3(upX, upY, upZ);
Yaw = yaw;
Pitch = pitch;
updateCameraVectors();
} glm::mat4 Camera::GetViewMatrix() {
return glm::lookAt(Position, Position + Front, Up);
} void Camera::ProcessKeyboard(Camera_Movement direction, GLfloat deltaTime) {
GLfloat velocity = MovementSpeed * deltaTime;
if (direction == FORWARD)
Position += glm::normalize(glm::cross(WorldUp, Right)) * velocity;
if (direction == BACKWARD)
Position -= glm::normalize(glm::cross(WorldUp, Right)) * velocity;
if (direction == LEFT)
Position -= Right * velocity;
if (direction == RIGHT)
Position += Right * velocity;
} void Camera::ProcessMouseMovement(GLfloat xoffset, GLfloat yoffset, GLboolean constrainPitch) {
xoffset *= MouseSensitivity;
yoffset *= MouseSensitivity; Yaw += xoffset;
Pitch += yoffset; if (constrainPitch) {
if (Pitch > 89.0f)
Pitch = 89.0f;
if (Pitch < -89.0f)
Pitch = -89.0f;
} updateCameraVectors();
} void Camera::ProcessMouseScroll(GLfloat yoffset) {
if (Zoom >= 1.0f && Zoom <= 45.0f)
Zoom -= yoffset;
if (Zoom <= 1.0f)
Zoom = 1.0f;
if (Zoom >= 45.0f)
Zoom = 45.0f;
} void Camera::updateCameraVectors() {
glm::vec3 front;
front.x = cos(glm::radians(Yaw)) * cos(glm::radians(Pitch));
front.y = sin(glm::radians(Pitch));
front.z = sin(glm::radians(Yaw)) * cos(glm::radians(Pitch));
Front = glm::normalize(front);
Right = glm::normalize(glm::cross(Front, WorldUp));
Up = glm::normalize(glm::cross(Right, Front));
}

[LearnOpenGL]照相机的变换、坐标系、摄像机的更多相关文章

  1. Codeforces Gym 100531J Joy of Flight 变换坐标系

    Joy of Flight 题目连接: http://codeforces.com/gym/100531/attachments Description Jacob likes to play wit ...

  2. OPENGL_变换与坐标系

    参考:http://blog.csdn.net/kandyer/article/details/12449973 坐标系 世界坐标系:绝对坐标 物体坐标系:以物体自身为原点的坐标系 摄像机坐标系:以摄 ...

  3. 理解SVG坐标系统和变换: transform属性

    SVG元素可以通过缩放,移动,倾斜和旋转来变换-类似HTML元素使用CSS transform来变换.然而,当涉及到坐标系时这些变换所产生的影响必然有一定差别.在这篇文章中我们讨论SVG的transf ...

  4. View Transform(视图变换)详解

    http://www.cnblogs.com/graphics/archive/2012/07/12/2476413.html 什么是View Transform 我们可以用照相机的原理来阐释3D图形 ...

  5. (转)View Transform(视图变换)详解

    原文作者讲得太好了,唯有这篇让我对视图矩阵了解的清晰了很多. --------------------------------------------------------------------- ...

  6. 【3D研发笔记】之【数学相关】(一):坐标系

    现在开始学习3D基础相关的知识,本系列的数学相关笔记是基于阅读书籍<3D数学基础:图形与游戏开发>而来,实现代码使用AS3,项目地址是:https://github.com/hammerc ...

  7. OpenGL 的空间变换(下):空间变换

    通过本文的上篇 OpenGL 的空间变换(上):矩阵在空间几何中的应用 ,我们了解到矩阵的基础概念.并且掌握了矩阵在空间几何中的应用.接下来,我们将结合矩阵来了解 OpenGL 的空间变换. 在使用 ...

  8. DirectX11 With Windows SDK--10 摄像机类

    前言 DirectX11 With Windows SDK完整目录:http://www.cnblogs.com/X-Jun/p/9028764.html 由于考虑后续的项目需要有一个比较好的演示环境 ...

  9. OpenGL坐标系的理解

    搬运自: https://learnopengl-cn.github.io/01%20Getting%20started/08%20Coordinate%20Systems/#3d 为了将坐标从一个坐 ...

随机推荐

  1. Oracle Certified Java Programmer 经典题目分析(二)

    ...接上篇 what is reserved(保留) words in java? A. run B. default C. implement D. import Java 关键字列表 (依字母排 ...

  2. 【LinuxC】GCC编译C程序,关闭随机基址

    1.编译.链接和运行程序 C代码示例: #include <stdio.h> #include <stdlib.h> int main() { printf("hel ...

  3. numpy细碎知识点

    np.random.rand() 基于python自带模块random的random函数的一个延伸吧,生成指定数量的列表 np.random.rand(a,b) 参数a,b均为整型,生成含有a个元素的 ...

  4. 一步一步搭建oracle 11gR2 rac+dg之database安装(五)【转】

    一步一步在RHEL6.5+VMware Workstation 10上搭建 oracle 11gR2 rac + dg 之database安装 (五)   转自 一步一步搭建oracle 11gR2 ...

  5. javascript按照指定格式获取上一个月的日期

    //get pre month//get pre month function getPreMonth() { var date=new Date().Format("yyyy-MM-dd& ...

  6. c# 通过Windows服务启动外部程序

    1. 新建一个Windows服务应用程序 创建项目——>Visual C# 左侧的"+"——>Windows ——>Windows 服务(右侧模板)——>输 ...

  7. docker stack 部署 seafile(http)

    =============================================== 2018/5/13_第1次修改                       ccb_warlock == ...

  8. Centos 软连接和硬链接

    1.软链接: 建立软链接:ln -s /usr/local/node-v4.2.6-linux-x86/bin/node /usr/local/bin/node 解释:将/usr/local/node ...

  9. 孤的Scrapy官文阅读进程

    上月底开始学习Scrapy爬虫框架,看了一些中文文档,讲应用.讲基础的,对其有一些了解了.终于在28日打开Scrapy的官网,并制作了其文档的思维导图,进而开启了其文档的阅读之旅. 本文展示了从6月2 ...

  10. 洛谷P1782 旅行商的背包

    传送门啦 这个题不用二进制优化的话根本不行,现学的二进制优化,调了一段时间终于A了,不容易.. 如果不懂二进制优化的话可以去看我那个博客 二进制优化多重背包入口 不想TLE,不要打memset,一定要 ...