OpenGL--摄像机
目錄(?)[+]
一、 攝像機(jī)
1. 攝像機(jī)/觀察空間
定義一個(gè)攝像機(jī),我們需要一個(gè)攝像機(jī)在世界空間中的位置、觀察的方向、一個(gè)指向它的右測(cè)的向量以及一個(gè)指向它上方的向量。?
攝像機(jī)的位置?
獲取攝像機(jī)位置很簡(jiǎn)單。攝像機(jī)位置簡(jiǎn)單來說就是世界空間中代表攝像機(jī)位置的向量。我們把攝像機(jī)位置設(shè)置為前面教程中的那個(gè)相同的位置:
- 1
攝像機(jī)方向?
用攝像機(jī)位置向量減去場(chǎng)景原點(diǎn)向量的結(jié)果就是攝像機(jī)指向向量。由于我們知道攝像機(jī)指向z軸負(fù)方向,我們希望方向向量指向攝像機(jī)的z軸正方向。如果我們改變相減的順序,我們就會(huì)獲得一個(gè)指向攝像機(jī)正z軸方向的向量。
- 1
- 2
右軸?
我們需要的另一個(gè)向量是一個(gè)右向量(Right Vector),它代表攝像機(jī)空間的x軸的正方向。為獲取右向量我們需要先使用一個(gè)小技巧:定義一個(gè)上向量(Up Vector)。我們把上向量和第二步得到的攝像機(jī)方向向量進(jìn)行叉乘。兩個(gè)向量叉乘的結(jié)果就是同時(shí)垂直于兩向量的向量,因此我們會(huì)得到指向x軸正方向的那個(gè)向量(如果我們交換兩個(gè)向量的順序就會(huì)得到相反的指向x軸負(fù)方向的向量):
- 1
- 2
上軸?
現(xiàn)在我們已經(jīng)有了x軸向量和z軸向量,獲取攝像機(jī)的正y軸相對(duì)簡(jiǎn)單;我們把右向量和方向向量(Direction Vector)進(jìn)行叉乘:
- 1
使用這些攝像機(jī)向量我們就可以創(chuàng)建一個(gè)LookAt矩陣了,它在創(chuàng)建攝像機(jī)的時(shí)候非常有用。
2. LookAt
現(xiàn)在我們有了3個(gè)相互垂直的軸和一個(gè)定義攝像機(jī)空間的位置坐標(biāo),我們可以創(chuàng)建我們自己的LookAt矩陣了:?
?
R是右向量,U是上向量,D是方向向量P是攝像機(jī)位置向量。注意,位置向量是相反的,因?yàn)槲覀冏罱K希望把世界平移到與我們自身移動(dòng)的相反方向。?
GLM已經(jīng)提供了這些支持。我們要做的只是定義一個(gè)攝像機(jī)位置,一個(gè)目標(biāo)位置和一個(gè)表示上向量的世界空間中的向量(我們使用上向量計(jì)算右向量)。接著GLM就會(huì)創(chuàng)建一個(gè)LookAt矩陣,我們可以把它當(dāng)作我們的觀察矩陣:
- 1
- 2
- 3
- 4
3. 自由移動(dòng)
首先我們必須設(shè)置一個(gè)攝像機(jī)系統(tǒng),在我們的程序前面定義一些攝像機(jī)變量很有用:
glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f); glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f); glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);- 1
- 2
- 3
LookAt函數(shù)現(xiàn)在成了:
view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);- 1
我們首先設(shè)置之前定義的cameraPos為攝像機(jī)位置。方向(Direction)是當(dāng)前的位置加上我們剛剛定義的方向向量。這樣能保證無論我們?cè)趺匆苿?dòng),攝像機(jī)都會(huì)注視目標(biāo)。我們?cè)诎聪履硞€(gè)按鈕時(shí)更新cameraPos向量。
我們已經(jīng)為GLFW的鍵盤輸入定義了一個(gè)key_callback函數(shù),我們來添加幾個(gè)新按鍵命令:
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) {...GLfloat cameraSpeed = 0.05f;if (key == GLFW_KEY_W)cameraPos += cameraSpeed * cameraFront;if (key == GLFW_KEY_S)cameraPos -= cameraSpeed * cameraFront;if (key == GLFW_KEY_A)cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;if (key == GLFW_KEY_D)cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed; }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
當(dāng)我們按下WASD鍵,攝像機(jī)的位置都會(huì)相應(yīng)更新。如果我們希望向前或向后移動(dòng),我們就把位置向量加上或減去方向向量。如果我們希望向旁邊移動(dòng),我們做一個(gè)叉乘來創(chuàng)建一個(gè)右向量,沿著它移動(dòng)就可以了。這樣就創(chuàng)建了類似使用攝像機(jī)橫向、前后移動(dòng)的效果。
4. 視角移動(dòng)
歐拉角?
歐拉角(Euler Angle)是表示3D空間中可以表示任何旋轉(zhuǎn)的三個(gè)值,由萊昂哈德·歐拉在18世紀(jì)提出。有三種歐拉角:俯仰角(Pitch)、偏航角(Yaw)和滾轉(zhuǎn)角(Roll),下面的圖片展示了它們的含義:?
?
俯仰角是描述我們?nèi)绾瓮虾屯驴吹慕?#xff0c;它在第一張圖中表示。第二張圖顯示了偏航角,偏航角表示我們往左和往右看的大小。滾轉(zhuǎn)角代表我們?nèi)绾畏瓭L攝像機(jī)。?
對(duì)于我們的攝像機(jī)系統(tǒng)來說,我們只關(guān)心俯仰角和偏航角,所以我們不會(huì)討論滾轉(zhuǎn)角。用一個(gè)給定的俯仰角和偏航角,我們可以把它們轉(zhuǎn)換為一個(gè)代表新的方向向量的3D向量。
- 1
- 2
- 3
5. 鼠標(biāo)輸入
首先我們要告訴GLFW,應(yīng)該隱藏光標(biāo),并捕捉(Capture)它。捕捉鼠標(biāo)意味著當(dāng)應(yīng)用集中焦點(diǎn)到鼠標(biāo)上的時(shí)候光標(biāo)就應(yīng)該留在窗口中(除非應(yīng)用拾取焦點(diǎn)或退出)。我們可以進(jìn)行簡(jiǎn)單的配置:?
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);?
這個(gè)函數(shù)調(diào)用后,無論我們?cè)趺慈ヒ苿?dòng)鼠標(biāo),它都不會(huì)顯示了,也不會(huì)離開窗口。對(duì)于FPS攝像機(jī)系統(tǒng)來說很好:?
為計(jì)算俯仰角和偏航角我們需要告訴GLFW監(jiān)聽鼠標(biāo)移動(dòng)事件。我們用下面的原型創(chuàng)建一個(gè)回調(diào)函數(shù)來做這件事(和鍵盤輸入差不多):
- 1
這里的xpos和ypos代表當(dāng)前鼠標(biāo)的位置。我們注冊(cè)了GLFW的回調(diào)函數(shù),鼠標(biāo)一移動(dòng)mouse_callback函數(shù)就被調(diào)用:
glfwSetCursorPosCallback(window, mouse_callback);- 1
在處理FPS風(fēng)格的攝像機(jī)鼠標(biāo)輸入的時(shí)候,我們必須在獲取最終的方向向量之前做下面這幾步:
- 計(jì)算鼠標(biāo)和上一幀的偏移量。
- 把偏移量添加到攝像機(jī)和俯仰角和偏航角中。
- 對(duì)偏航角和俯仰角進(jìn)行最大和最小值的限制。
- 計(jì)算方向向量。
我們必須先儲(chǔ)存上一幀的鼠標(biāo)位置,我們把它的初始值設(shè)置為屏幕的中心(屏幕的尺寸是800乘600):
GLfloat lastX = 400, lastY = 300;- 1
然后在回調(diào)函數(shù)中計(jì)算方向向量:
void mouse_callback(GLFWwindow* window, double xpos, double ypos) {//第一次則將當(dāng)前位置設(shè)置為上一幀的位置來避免抖動(dòng)if (firstMouse){lastX = xpos;lastY = ypos;firstMouse = false;}//計(jì)算偏移量并保存當(dāng)前幀坐標(biāo)為上一幀坐標(biāo)GLfloat xoffset = xpos - lastX;GLfloat yoffset = lastY - ypos;lastX = xpos;lastY = ypos;//縮放偏轉(zhuǎn)量GLfloat sensitivity = 0.05;xoffset *= sensitivity;yoffset *= sensitivity;//計(jì)算偏轉(zhuǎn)位置yaw += xoffset;pitch += yoffset;//控制偏轉(zhuǎn)范圍if (pitch > 89.0f)pitch = 89.0f;if (pitch < -89.0f)pitch = -89.0f;//計(jì)算實(shí)際方向向量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));cameraFront = glm::normalize(front); }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
6. 縮放
當(dāng)視野變小時(shí)可視區(qū)域就會(huì)減小,產(chǎn)生放大了的感覺。我們用鼠標(biāo)滾輪來放大。和鼠標(biāo)移動(dòng)、鍵盤輸入一樣我們需要一個(gè)鼠標(biāo)滾輪的回調(diào)函數(shù):
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) {if (aspect >= 1.0f && aspect <= 45.0f)aspect -= yoffset;if (aspect <= 1.0f)aspect = 1.0f;if (aspect >= 45.0f)aspect = 45.0f; }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
yoffset值代表我們滾動(dòng)的大小。當(dāng)scroll_callback函數(shù)調(diào)用后,我們改變?nèi)謅spect變量的內(nèi)容。因?yàn)?5.0f是默認(rèn)的fov,我們將會(huì)把縮放級(jí)別限制在1.0f到45.0f。
我們現(xiàn)在在每一幀都必須把透視投影矩陣上傳到GPU,但這一次使aspect變量作為它的fov:
projection = glm::perspective(aspect, (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 100.0f);- 1
最后不要忘記注冊(cè)滾動(dòng)回調(diào)函數(shù):
glfwSetScrollCallback(window, scroll_callback);- 1
7. 攝像機(jī)類
直接貼出原教程給出的攝像機(jī)類:
#pragma once// Std. Includes #include <vector>// GL Includes #include <GL/glew.h> #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp>// Defines several possible options for camera movement. Used as abstraction to stay away from window-system specific input methods enum Camera_Movement {FORWARD,BACKWARD,LEFT,RIGHT };// Default camera values 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;// An abstract camera class that processes input and calculates the corresponding Eular Angles, Vectors and Matrices for use in OpenGL class Camera { public:// Camera Attributesglm::vec3 Position;glm::vec3 Front;glm::vec3 Up;glm::vec3 Right;glm::vec3 WorldUp;// Eular AnglesGLfloat Yaw;GLfloat Pitch;// Camera optionsGLfloat MovementSpeed;GLfloat MouseSensitivity;GLfloat Zoom;// Constructor with vectorsCamera(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) : Front(glm::vec3(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVTY), Zoom(ZOOM){this->Position = position;this->WorldUp = up;this->Yaw = yaw;this->Pitch = pitch;this->updateCameraVectors();}// Constructor with scalar valuesCamera(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){this->Position = glm::vec3(posX, posY, posZ);this->WorldUp = glm::vec3(upX, upY, upZ);this->Yaw = yaw;this->Pitch = pitch;this->updateCameraVectors();}// Returns the view matrix calculated using Eular Angles and the LookAt Matrixglm::mat4 GetViewMatrix(){return glm::lookAt(this->Position, this->Position + this->Front, this->Up);}// Processes input received from any keyboard-like input system. Accepts input parameter in the form of camera defined ENUM (to abstract it from windowing systems)void ProcessKeyboard(Camera_Movement direction, GLfloat deltaTime){GLfloat velocity = this->MovementSpeed * deltaTime;if (direction == FORWARD)this->Position += this->Front * velocity;if (direction == BACKWARD)this->Position -= this->Front * velocity;if (direction == LEFT)this->Position -= this->Right * velocity;if (direction == RIGHT)this->Position += this->Right * velocity;}// Processes input received from a mouse input system. Expects the offset value in both the x and y direction.void ProcessMouseMovement(GLfloat xoffset, GLfloat yoffset, GLboolean constrainPitch = true){xoffset *= this->MouseSensitivity;yoffset *= this->MouseSensitivity;this->Yaw += xoffset;this->Pitch += yoffset;// Make sure that when pitch is out of bounds, screen doesn't get flippedif (constrainPitch){if (this->Pitch > 89.0f)this->Pitch = 89.0f;if (this->Pitch < -89.0f)this->Pitch = -89.0f;}// Update Front, Right and Up Vectors using the updated Eular anglesthis->updateCameraVectors();}// Processes input received from a mouse scroll-wheel event. Only requires input on the vertical wheel-axisvoid ProcessMouseScroll(GLfloat yoffset){if (this->Zoom >= 1.0f && this->Zoom <= 45.0f)this->Zoom -= yoffset;if (this->Zoom <= 1.0f)this->Zoom = 1.0f;if (this->Zoom >= 45.0f)this->Zoom = 45.0f;}private:// Calculates the front vector from the Camera's (updated) Eular Anglesvoid updateCameraVectors(){// Calculate the new Front vectorglm::vec3 front;front.x = cos(glm::radians(this->Yaw)) * cos(glm::radians(this->Pitch));front.y = sin(glm::radians(this->Pitch));front.z = sin(glm::radians(this->Yaw)) * cos(glm::radians(this->Pitch));this->Front = glm::normalize(front);// Also re-calculate the Right and Up vectorthis->Right = glm::normalize(glm::cross(this->Front, this->WorldUp)); // Normalize the vectors, because their length gets closer to 0 the more you look up or down which results in slower movement.this->Up = glm::normalize(glm::cross(this->Right, this->Front));} };- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
轉(zhuǎn)載請(qǐng)注明出處:http://blog.csdn.net/ylbs110/article/details/52506033
二、 示例
代碼:
#include <iostream> using namespace std; // GLEW #define GLEW_STATIC #include <GL/glew.h> // GLFW #include <GLFW/glfw3.h> // SOIL #include <SOIL\SOIL.h>#include <glm\glm.hpp> #include <glm\gtc\matrix_transform.hpp> #include <glm\gtc\type_ptr.hpp>#include "Shader.h" #include "Camera.h"const GLuint WIDTH = 800, HEIGHT = 600;void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode); GLuint loadTexture(string fileName, GLint REPEAT, GLint FILTER); void do_movement(); void scroll_callback(GLFWwindow* window, double xoffset, double yoffset); void mouse_callback(GLFWwindow* window, double xpos, double ypos); // Shaders const GLchar* vertexShaderSource = "#version 330 core\n" "layout (location = 0) in vec3 position;\n"//頂點(diǎn)數(shù)據(jù)傳入的坐標(biāo) "layout (location = 1) in vec3 color;\n"//頂點(diǎn)數(shù)據(jù)傳入的顏色 "layout (location = 2) in vec2 texCoord;\n"//頂點(diǎn)數(shù)據(jù)傳入的顏色 "uniform vec4 offset;\n" "uniform float mixPar;\n" "uniform mat4 model;\n" "uniform mat4 view;\n" "uniform mat4 projection;\n" "out vec3 Color;\n" "out vec2 TexCoord;\n" "out vec4 vertexColor;\n"//將頂點(diǎn)坐標(biāo)作為顏色傳入片段著色器,測(cè)試所得效果 "out float MixPar;\n" "void main()\n" "{\n" "gl_Position =projection * view * model* vec4(position.x, position.y, position.z, 1.0)+offset;\n" "vertexColor=gl_Position*0.2f;\n" "Color=color*0.2f;\n" "TexCoord=texCoord;\n" "MixPar=mixPar;\n" "}\0";const GLchar* fragmentShaderSource = "#version 330 core\n" "out vec4 color;\n" "in vec4 vertexColor;\n" "in vec3 Color;\n" "in vec2 TexCoord;\n" "in float MixPar;\n" "uniform sampler2D ourTexture1;\n" "uniform sampler2D ourTexture2;\n" "void main()\n" "{\n" "color =mix(texture(ourTexture1, TexCoord),texture(ourTexture2, vec2(TexCoord.x,1-TexCoord.y)),MixPar)+vec4(Color, 1.0f)+vertexColor;\n"//合成兩張紋理并對(duì)第二張紋理進(jìn)行翻轉(zhuǎn)操作,混合比例由上下鍵控制 "}\n\0"; Camera mainCamera; Shader shader;//shader GLuint texContainer, texAwesomeface;//紋理idfloat key_UD = 0.5f;//混合比例 GLuint VBO, VAO;GLfloat deltaTime = 0.0f; // 當(dāng)前幀遇上一幀的時(shí)間差 GLfloat lastFrame = 0.0f; // 上一幀的時(shí)間bool keys[1024];GLfloat lastX = 400, lastY = 300; GLfloat scrollSpeed = 0.05f; bool firstMouse = true;glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f); glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f); glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);void shaderInit() {shader = Shader(vertexShaderSource, fragmentShaderSource); } void textureInit() {texContainer = loadTexture("container.jpg", GL_CLAMP_TO_EDGE, GL_LINEAR);texAwesomeface = loadTexture("awesomeface.png", GL_MIRRORED_REPEAT, GL_NEAREST); } GLuint loadTexture(string fileName,GLint REPEAT, GLint FILTER) {//創(chuàng)建紋理GLuint texture;glGenTextures(1, &texture);//綁定紋理glBindTexture(GL_TEXTURE_2D, texture);// 為當(dāng)前綁定的紋理對(duì)象設(shè)置環(huán)繞、過濾方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, FILTER);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, FILTER);//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(fileName.c_str(), &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);//釋放圖像的內(nèi)存并解綁紋理對(duì)象SOIL_free_image_data(image);glBindTexture(GL_TEXTURE_2D, 0);return texture; }void vertexObjectInit() {//不使用索引緩沖對(duì)象用兩個(gè)三角形繪制一個(gè)梯形// 設(shè)置頂點(diǎn)緩存和屬性指針GLfloat vertices[] = {-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f,0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f,1.0f, 0.0f,0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f,1.0f, 1.0f,0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f,1.0f, 1.0f,-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f,0.0f, 0.0f,-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f,0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 0.0f,1.0f, 0.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f,1.0f, 1.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f,1.0f, 1.0f,-0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f,-0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f,-0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f,1.0f, 0.0f,0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f,1.0f, 1.0f,0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f,0.0f, 1.0f,0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f,0.0f, 1.0f,0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 0.0f,0.0f, 0.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f,1.0f, 0.0f,-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f,1.0f, 1.0f,0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 0.0f,1.0f, 0.0f,0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 0.0f,1.0f, 0.0f,-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f,-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f,1.0f, 1.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f,1.0f, 0.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f,1.0f, 0.0f,-0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f,-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f};//創(chuàng)建索引緩沖對(duì)象glGenBuffers(1, &VBO);glGenVertexArrays(1, &VAO);glBindVertexArray(VAO);// 把頂點(diǎn)數(shù)組復(fù)制到緩沖中供OpenGL使用glBindBuffer(GL_ARRAY_BUFFER, VBO);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);// 位置屬性glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);glEnableVertexAttribArray(0);// 顏色屬性glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));glEnableVertexAttribArray(1);glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));glEnableVertexAttribArray(2);glBindBuffer(GL_ARRAY_BUFFER, 0);// 這個(gè)方法將頂點(diǎn)屬性指針注冊(cè)到VBO作為當(dāng)前綁定頂點(diǎn)對(duì)象,然后我們就可以安全的解綁glBindVertexArray(0);// 解綁 VAO (這通常是一個(gè)很好的用來解綁任何緩存/數(shù)組并防止奇怪錯(cuò)誤的方法) }int main() {//初始化GLFWglfwInit();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);//創(chuàng)建窗口對(duì)象GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);if (window == nullptr){std::cout << "Failed to create GLFW window" << std::endl;glfwTerminate();return -1;}glfwMakeContextCurrent(window);//注冊(cè)鍵盤回調(diào)glfwSetKeyCallback(window, key_callback);//注冊(cè)鼠標(biāo)回調(diào)glfwSetCursorPosCallback(window, mouse_callback);//注冊(cè)鼠標(biāo)滾輪回到glfwSetScrollCallback(window, scroll_callback);//設(shè)置光標(biāo)隱藏并捕獲glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);//初始化GLEWglewExperimental = GL_TRUE;if (glewInit() != GLEW_OK){std::cout << "Failed to initialize GLEW" << std::endl;return -1;}//告訴OpenGL渲染窗口尺寸大小int width, height;glfwGetFramebufferSize(window, &width, &height);glViewport(0, 0, width, height);glEnable(GL_DEPTH_TEST);//初始化并綁定shadersshaderInit();//初始化texturestextureInit();//初始化頂點(diǎn)對(duì)象數(shù)據(jù)vertexObjectInit();mainCamera = Camera();//讓窗口接受輸入并保持運(yùn)行while (!glfwWindowShouldClose(window)){GLfloat currentFrame = glfwGetTime();deltaTime = currentFrame - lastFrame;lastFrame = currentFrame;//檢查事件glfwPollEvents();do_movement();//渲染指令glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//設(shè)置根據(jù)時(shí)間變換的x,y偏移值,最終效果為圓周運(yùn)動(dòng)GLfloat timeValue = glfwGetTime();GLfloat offsetx = (sin(timeValue) / 2) + 0.5;GLfloat offsety = (cos(timeValue) / 2) + 0.5;//繪制長方形 shader.Use();//綁定兩張貼圖glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, texContainer);glUniform1i(glGetUniformLocation(shader.Program, "ourTexture1"), 0);glActiveTexture(GL_TEXTURE1);glBindTexture(GL_TEXTURE_2D, texAwesomeface);glUniform1i(glGetUniformLocation(shader.Program, "ourTexture2"), 1);// 更新uniform值//設(shè)置運(yùn)動(dòng)軌跡//GLint vertexorangeLocation = glGetUniformLocation(shader.Program, "offset");//glUniform4f(vertexorangeLocation, offsetx, offsety, 0.0f, 1.0f);//設(shè)置混合比例GLint mixPar = glGetUniformLocation(shader.Program, "mixPar");glUniform1f(mixPar, key_UD);glm::mat4 model;model = glm::rotate(model, (GLfloat)glfwGetTime() * 5.0f, glm::vec3(0.5f, 1.0f, 0.0f));glm::mat4 view;view = mainCamera.GetViewMatrix();glm::mat4 projection;projection = glm::perspective(mainCamera.Zoom*scrollSpeed, (float)(WIDTH / HEIGHT), 0.1f, 100.0f);GLint modelLoc = glGetUniformLocation(shader.Program, "model");glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));GLint viewLoc = glGetUniformLocation(shader.Program, "view");glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));GLint projectionLoc = glGetUniformLocation(shader.Program, "projection");glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));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)};glBindVertexArray(VAO);for (GLuint i = 0; i < 10; i++){glm::mat4 model;model = glm::translate(model, cubePositions[i]);if (i < 4) { GLfloat angle = (GLfloat)glfwGetTime()*5.0f * i;model = glm::rotate(model, angle, glm::vec3(1.0f, 0.3f, 0.5f));glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));}else{glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));}glDrawArrays(GL_TRIANGLES, 0, 36);}glBindVertexArray(0);//交換緩沖glfwSwapBuffers(window);}glDeleteVertexArrays(1, &VAO);glDeleteBuffers(1, &VBO);//釋放資源glfwTerminate();return 0; } void do_movement() {// 攝像機(jī)控制GLfloat cameraSpeed = 5.0f* deltaTime;if (keys[GLFW_KEY_W])mainCamera.ProcessKeyboard(FORWARD, deltaTime);if (keys[GLFW_KEY_S])mainCamera.ProcessKeyboard(BACKWARD, deltaTime);if (keys[GLFW_KEY_A])mainCamera.ProcessKeyboard(LEFT, deltaTime);if (keys[GLFW_KEY_D])mainCamera.ProcessKeyboard(RIGHT, deltaTime); } void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) {// 當(dāng)用戶按下ESC鍵,我們?cè)O(shè)置window窗口的WindowShouldClose屬性為true// 關(guān)閉應(yīng)用程序if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)glfwSetWindowShouldClose(window, GL_TRUE);if (key == GLFW_KEY_UP&& action == GLFW_PRESS)//按下UP鍵增加混合比例key_UD = key_UD + 0.1f;if (key == GLFW_KEY_DOWN&& action == GLFW_PRESS)//按下DOWN減小混合比例key_UD = key_UD - 0.1f;if (action == GLFW_PRESS)keys[key] = true;else if (action == GLFW_RELEASE)keys[key] = false; } void mouse_callback(GLFWwindow* window, double xpos, double ypos) {if (firstMouse){lastX = xpos;lastY = ypos;firstMouse = false;}GLfloat xoffset = xpos - lastX;GLfloat yoffset = lastY - ypos; // Reversed since y-coordinates go from bottom to left lastX = xpos;lastY = ypos;mainCamera.ProcessMouseMovement(xoffset, yoffset); }void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) {cout << yoffset << endl;mainCamera.ProcessMouseScroll(yoffset); }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
- 254
- 255
- 256
- 257
- 258
- 259
- 260
- 261
- 262
- 263
- 264
- 265
- 266
- 267
- 268
- 269
- 270
- 271
- 272
- 273
- 274
- 275
- 276
- 277
- 278
- 279
- 280
- 281
- 282
- 283
- 284
- 285
- 286
- 287
- 288
- 289
- 290
- 291
- 292
- 293
- 294
- 295
- 296
- 297
- 298
- 299
- 300
- 301
- 302
- 303
- 304
- 305
- 306
- 307
- 308
- 309
- 310
- 311
- 312
- 313
- 314
- 315
- 316
- 317
- 318
- 319
- 320
- 321
- 322
- 323
- 324
- 325
- 326
- 327
- 328
- 329
- 330
- 331
- 332
- 333
- 334
- 335
- 336
- 337
- 338
- 339
- 340
- 341
- 342
- 343
- 344
- 345
- 346
- 347
- 348
- 349
- 350
- 351
- 352
- 353
- 354
- 355
- 356
- 357
- 358
- 359
- 360
- 361
- 362
- 363
- 364
- 365
- 366
- 367
- 368
- 369
- 370
- 371
- 372
- 373
- 374
- 375
- 376
- 377
- 378
- 379
- 380
- 381
- 382
- 383
- 384
結(jié)果:
wsad可以控制上下左右,鼠標(biāo)控制攝像頭方向,滾輪可以拉伸:?
總結(jié)
以上是生活随笔為你收集整理的OpenGL--摄像机的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 零知识证明(zero-knowledge
- 下一篇: 硬盘克隆大师从入门到精通