前言

跟着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. 加密文件之Java改进版

    对应Python版:加密文件之Python版Java版比Python版要快得多,两个版本不在一个量级上.在加密解密1G大文件时,Java版花费的时间是秒级,而Python版花费的时间是10分钟级. i ...

  2. Mysql中truncate table和delete语句的区别

    Mysql中的truncate table和delete语句都可以删除表里面所有数据,但是在一些情况下有些不同! 例子: truncate table gag; (1)truncate table删除 ...

  3. redis学习笔记之redis简介

    redis简介 Redis是一个开源的,高性能的,基于键值对的缓存与存储系统,通过设置各种键值数据类型来适应不同场景下的缓存与存储需求.同事redis的诸多高层级功能使其可以胜任消息队列,任务队列等不 ...

  4. 关于Java中final关键字的详细介绍

    Java中的final关键字非常重要,它可以应用于类.方法以及变量.这篇文章中我将带你看看什么是final关键字?将变量,方法和类声明为final代表了什么?使用final的好处是什么?最后也有一些使 ...

  5. mybatis比hibernate处理速度快的原因

    mybatis:是面向结果集的.当要展示的页面需要几个字段时,springmvc会提供这几个字段并将其拼接成结果集,在转化为相应的对象. hibernate:是面向对象的.要展示的页面需要某些字段时, ...

  6. linux查看内存、CPU占用资源最多的进程

    [内存占用] #利用ps命令,默认使用ps参数会显示的结果 ps -aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 ...

  7. 洛谷P2312解方程

    传送门 思路分析 怎么求解呢? 其实我们可以把左边的式子当成一个算式来计算,从1到 $ m $ 枚举,只要结果是0,那么当前枚举到的值就是这个等式的解了.可以通过编写一个 $ bool $ 函数来判断 ...

  8. 洛谷P1725 琪露诺

    传送门啦 本人第一个单调队列优化 $ dp $,不鼓励鼓励? 琪露诺这个题,$ dp $ 还是挺好想的对不,但是暴力 $ dp $ 的话会 $ TLE $ ,所以我们考虑用单调队列优化. 原题中说她只 ...

  9. JAVA复习笔记分布式篇:kafka

    前言:第一次使用消息队列是在实在前年的时候,那时候还不了解kafka,用的是阿里的rocket_mq,当时觉得挺好用的,后来听原阿里的同事说rocket_mq是他们看来kafka的源码后自己开发了一套 ...

  10. Knockout应用开发指南 应用举例(简单、高级)

    Knockout应用开发指南 第八章:简单应用举例(1)http://www.cnblogs.com/TomXu/archive/2011/11/30/2257067.htmlKnockout应用开发 ...