前言

跟着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. mysql条件查询中AND与OR联合使用的注意事项!

    mysql查询中经常会用到AND与OR一起使用的情况,可如果写法不对,往往会起到相反的效果,这不,前几天就碰到了,最后测试果然提了一堆bug!!!! 废话就不多说了,主要总结一下几点: 一 当mysq ...

  2. 修复TortoiseGit文件夹和文件图标不显示问题的多种解决办法以及重启之后TortoiseGit图标注册表又不见了的解决办法

    一 首先进行第一种尝试 打开 regedit.exe ,准备修改注册表 找到 HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\ ...

  3. Oracle11g用户、权限、角色、概要文件管理及审计

    第10章 安全管理 1 用户管理 2 权限管理 3 角色管理    : 4 概要文件管理 5 审计 操作系统:win7    Oracle安装目录:E盘 数据库名字:orcl  密码:123456 先 ...

  4. openjudge-NOI 2.5基本算法之搜索 专题题解目录

    1.1700 八皇后问题 2.1756 八皇后 3.1789 算24

  5. javaScript一些需要注意的细节

    变量声明早于代码运行. 函数声明早于变量声明. this指针代表的是执行当前代码的对象的所有者. JavaScript执行完同步,才能执行异步队列.如:alert,for if while 同步执行, ...

  6. Mysql建表语句

    create table messages( id int unsigned primary key auto_increment, sender varchar(64) not null, gett ...

  7. oralce 笔记

    查某一表的行数 select max(rownum) from tablename 插入数据之前判断是否重复 insert into tablename (coloum1,coloum2) selec ...

  8. jmock2.5 基本教程

    目录 第0章 概述 第1章 jmock初体验 第2章 期望 第3章 返回值 第4章 参数匹配 第5章 指定方法调用次数 第6章 指定执行序列 第7章 状态机 第0章 概述 现在的dev不是仅仅要写co ...

  9. 一步一步学习IdentityServer3 (14) 启用Https

    申领一个CA证书,我用了一个腾讯的免费证书night-c.cn,这是腾讯云买域名送的一个证书 是单域名,非泛域名 1:安装证书  IIS选择证书 2:将证书加载到Identityserver3中,并启 ...

  10. require.js 加载 vue组件 r.js 合并压缩

    https://www.taoquns.com 自己搭的个人博客 require.js 参考阮一峰 Javascript模块化编程(三):require.js的用法 r.js 合并压缩 参考司徒正美 ...