視圖變換
代碼實驗
#include <glad/glad.h>//glad必須在glfw頭文件之前包含
#include <GLFW/glfw3.h>
#include <iostream>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"//GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/string_cast.hpp>void frameBufferSizeCallbakc(GLFWwindow* window, int width, int height)
{glViewport(0, 0, width, height);
}
void glfwKeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
}GLuint program = 0;
GLuint vao = 0;
GLuint texture = 0;
glm::mat4 transform(1.0f);//4×4單位矩陣
glm::mat4 viewMatrix(1.0f);void prepareCamera()
{//lookat:生成一個viewMatrix//eye:當前攝像機所在的位置//center:當前攝像機看向的那個點//up:穹頂向量viewMatrix = glm::lookAt(glm::vec3(0.5f, 0.0f, 0.5f), glm::vec3(0.5f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
}
void prepareVAO()
{//positionsfloat positions[] = {-0.5f, -0.5f, 0.0f,0.5f, -0.5f, 0.0f,0.0f, 0.5f, 0.0f,};//顏色float colors[] = {1.0f, 0.0f,0.0f,0.0f, 1.0f,0.0f,0.0f, 0.0f,1.0f};//索引unsigned int indices[] = {0, 1, 2,};//uv坐標float uvs[] = {0.0f, 0.0f,1.0f, 0.0f,0.5f, 1.0f,};//2 VBO創建GLuint posVbo = 0;GLuint colorVbo = 0;GLuint uvVbo = 0;glGenBuffers(1, &posVbo);glBindBuffer(GL_ARRAY_BUFFER, posVbo);glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);glGenBuffers(1, &colorVbo);glBindBuffer(GL_ARRAY_BUFFER, colorVbo);glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);glGenBuffers(1, &uvVbo);glBindBuffer(GL_ARRAY_BUFFER, uvVbo);glBufferData(GL_ARRAY_BUFFER, sizeof(uvs), uvs, GL_STATIC_DRAW);//3 EBO創建GLuint ebo = 0;glGenBuffers(1, &ebo);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);//4 VAO創建vao = 0;glGenVertexArrays(1, &vao);glBindVertexArray(vao);//5 綁定vbo ebo 加入屬性描述信息//5.1 加入位置屬性描述信息glBindBuffer(GL_ARRAY_BUFFER, posVbo);glEnableVertexAttribArray(0);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);//5.2 加入顏色屬性描述信息glBindBuffer(GL_ARRAY_BUFFER, colorVbo);glEnableVertexAttribArray(1);glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);//5.3 加入uv屬性描述數據glBindBuffer(GL_ARRAY_BUFFER, uvVbo);glEnableVertexAttribArray(2);glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);//5.2 加入ebo到當前的vaoglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);glBindVertexArray(0);
}
void prepareShader() {//1 完成vs與fs的源代碼,并且裝入字符串//aPos作為attribute(屬性)傳入shader不允許更改的const char* vertexShaderSource ="#version 330 core\n""layout (location = 0) in vec3 aPos;\n""layout (location = 1) in vec3 aColor;\n""layout (location = 2) in vec2 aUV;\n""out vec3 color;\n""out vec2 uv;\n""uniform mat4 transform;\n""uniform mat4 viewMatrix;\n""void main()\n""{\n"" vec4 position = vec4(aPos, 1.0);\n"" position = viewMatrix * transform * position;\n"" gl_Position = position;\n"" color = aColor;\n"" uv = aUV;\n""}\0";const char* fragmentShaderSource ="#version 330 core\n""out vec4 FragColor;\n""in vec3 color;\n""in vec2 uv;\n""uniform sampler2D sampler;\n""void main()\n""{\n"" FragColor = texture(sampler, uv);\n""}\n\0";//2 創建Shader程序(vs、fs)GLuint vertex, fragment;vertex = glCreateShader(GL_VERTEX_SHADER);fragment = glCreateShader(GL_FRAGMENT_SHADER);//3 為shader程序輸入shader代碼glShaderSource(vertex, 1, &vertexShaderSource, NULL);glShaderSource(fragment, 1, &fragmentShaderSource, NULL);int success = 0;char infoLog[1024];//4 執行shader代碼編譯 glCompileShader(vertex);//檢查vertex編譯結果glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);if (!success) {glGetShaderInfoLog(vertex, 1024, NULL, infoLog);std::cout << "Error: SHADER COMPILE ERROR --VERTEX" << "\n" << infoLog << std::endl;}glCompileShader(fragment);//檢查fragment編譯結果glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);if (!success) {glGetShaderInfoLog(fragment, 1024, NULL, infoLog);std::cout << "Error: SHADER COMPILE ERROR --FRAGMENT" << "\n" << infoLog << std::endl;}//5 創建一個Program殼子program = glCreateProgram();//6 將vs與fs編譯好的結果放到program這個殼子里glAttachShader(program, vertex);glAttachShader(program, fragment);//7 執行program的鏈接操作,形成最終可執行shader程序glLinkProgram(program);//檢查鏈接錯誤glGetProgramiv(program, GL_LINK_STATUS, &success);if (!success) {glGetProgramInfoLog(program, 1024, NULL, infoLog);std::cout << "Error: SHADER LINK ERROR " << "\n" << infoLog << std::endl;}//清理glDeleteShader(vertex);glDeleteShader(fragment);
}void prepareTextrue()
{//1 stbImage 讀取圖片int width, height, channels;//--反轉y軸stbi_set_flip_vertically_on_load(true);unsigned char* data = stbi_load("goku.jpg", &width, &height, &channels, STBI_rgb_alpha);//2 生成紋理并且激活單元綁定glGenTextures(1, &texture);//--激活紋理單元--glActiveTexture(GL_TEXTURE0);//--綁定紋理對象--glBindTexture(GL_TEXTURE_2D, texture);//3 傳輸紋理數據,開辟顯存glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);//***釋放數據stbi_image_free(data);//4 設置紋理的過濾方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);//5 設置紋理的包裹方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);//uglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);//v
}void render()
{//執行opengl畫布清理操作glClear(GL_COLOR_BUFFER_BIT);//1.綁定當前的programglUseProgram(program);//2 更新Uniform的時候,一定要先UserProgram//2.1 通過名稱拿到Uniform變量的位置LocationGLint location = glGetUniformLocation(program, "sampler");//2.2 通過Location更新Uniform變量的值glUniform1f(location, 0);GLint locationTransform = glGetUniformLocation(program, "transform");//transpose參數:表示是否對傳輸進去的矩陣數據進行轉置glUniformMatrix4fv(locationTransform, 1, GL_FALSE, glm::value_ptr(transform));GLint locationviewMatrix = glGetUniformLocation(program, "viewMatrix");//transpose參數:表示是否對傳輸進去的矩陣數據進行轉置glUniformMatrix4fv(locationviewMatrix, 1, GL_FALSE, glm::value_ptr(viewMatrix));//3 綁定當前的vaoglBindVertexArray(vao);//4 發出繪制指令//glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
}int main()
{//初始化glfw環境glfwInit();//設置opengl主版本號glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);//設置opengl次版本號glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);//設置opengl啟用核心模式glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);//創建窗體對象GLFWwindow* window = glfwCreateWindow(800, 600, "lenarnOpenGL", nullptr, nullptr);//設置當前窗體對象為opengl的繪制舞臺glfwMakeContextCurrent(window);//窗體大小回調glfwSetFramebufferSizeCallback(window, frameBufferSizeCallbakc);//鍵盤相應回調glfwSetKeyCallback(window, glfwKeyCallback);//使用glad加載所有當前版本opengl的函數if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){std::cout << "初始化glad失敗" << std::endl;return -1;};//設置opengl視口大小和清理顏色glViewport(0, 0, 800, 600);glClearColor(0.2f, 0.3f, 0.3f, 1.0f);//shaderprepareShader();//vaoprepareVAO();//textureprepareTextrue();prepareCamera();//執行窗體循環while (!glfwWindowShouldClose(window)){//接受并分發窗體消息//檢查消息隊列是否有需要處理的鼠標、鍵盤等消息//如果有的話就將消息批量處理,清空隊列glfwPollEvents();//渲染操作render();//切換雙緩存glfwSwapBuffers(window);}//推出程序前做相關清理glfwTerminate();return 0;
}
glm中的lookat參數可以生成視圖變換矩陣,設置給VS即可。
正交投影
總結
案例分析
#include <glad/glad.h>//glad必須在glfw頭文件之前包含
#include <GLFW/glfw3.h>
#include <iostream>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"//GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/string_cast.hpp>void frameBufferSizeCallbakc(GLFWwindow* window, int width, int height)
{glViewport(0, 0, width, height);
}
void glfwKeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
}GLuint program = 0;
GLuint vao = 0;
GLuint texture = 0;
glm::mat4 transform(1.0f);//4×4單位矩陣
glm::mat4 viewMatrix(1.0f);
glm::mat4 orthoMatrix(1.0f);
void prepareCamera()
{//lookat:生成一個viewMatrix//eye:當前攝像機所在的位置//center:當前攝像機看向的那個點//up:穹頂向量viewMatrix = glm::lookAt(glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
}
void prepareOrtho()
{//參數為盒體上下左右遠近orthoMatrix = glm::ortho(-2.0f, 2.0f, -2.0f, 2.0f, 2.0f, -2.0f);
}
void prepareVAO()
{//positionsfloat positions[] = {-1.0f, 0.0f, 0.0f,1.0f, 0.0f, 0.0f,0.0f, 1.0f, 0.0f,};//顏色float colors[] = {1.0f, 0.0f,0.0f,0.0f, 1.0f,0.0f,0.0f, 0.0f,1.0f};//索引unsigned int indices[] = {0, 1, 2,};//uv坐標float uvs[] = {0.0f, 0.0f,1.0f, 0.0f,0.5f, 1.0f,};//2 VBO創建GLuint posVbo = 0;GLuint colorVbo = 0;GLuint uvVbo = 0;glGenBuffers(1, &posVbo);glBindBuffer(GL_ARRAY_BUFFER, posVbo);glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);glGenBuffers(1, &colorVbo);glBindBuffer(GL_ARRAY_BUFFER, colorVbo);glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);glGenBuffers(1, &uvVbo);glBindBuffer(GL_ARRAY_BUFFER, uvVbo);glBufferData(GL_ARRAY_BUFFER, sizeof(uvs), uvs, GL_STATIC_DRAW);//3 EBO創建GLuint ebo = 0;glGenBuffers(1, &ebo);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);//4 VAO創建vao = 0;glGenVertexArrays(1, &vao);glBindVertexArray(vao);//5 綁定vbo ebo 加入屬性描述信息//5.1 加入位置屬性描述信息glBindBuffer(GL_ARRAY_BUFFER, posVbo);glEnableVertexAttribArray(0);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);//5.2 加入顏色屬性描述信息glBindBuffer(GL_ARRAY_BUFFER, colorVbo);glEnableVertexAttribArray(1);glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);//5.3 加入uv屬性描述數據glBindBuffer(GL_ARRAY_BUFFER, uvVbo);glEnableVertexAttribArray(2);glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);//5.2 加入ebo到當前的vaoglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);glBindVertexArray(0);
}
void prepareShader() {//1 完成vs與fs的源代碼,并且裝入字符串//aPos作為attribute(屬性)傳入shader不允許更改的const char* vertexShaderSource ="#version 330 core\n""layout (location = 0) in vec3 aPos;\n""layout (location = 1) in vec3 aColor;\n""layout (location = 2) in vec2 aUV;\n""out vec3 color;\n""out vec2 uv;\n""uniform mat4 transform;\n""uniform mat4 viewMatrix;\n""uniform mat4 orthoMatrix;\n""void main()\n""{\n"" vec4 position = vec4(aPos, 1.0);\n"" position = orthoMatrix * viewMatrix * transform * position;\n"" gl_Position = position;\n"" color = aColor;\n"" uv = aUV;\n""}\0";const char* fragmentShaderSource ="#version 330 core\n""out vec4 FragColor;\n""in vec3 color;\n""in vec2 uv;\n""uniform sampler2D sampler;\n""void main()\n""{\n"" FragColor = texture(sampler, uv);\n""}\n\0";//2 創建Shader程序(vs、fs)GLuint vertex, fragment;vertex = glCreateShader(GL_VERTEX_SHADER);fragment = glCreateShader(GL_FRAGMENT_SHADER);//3 為shader程序輸入shader代碼glShaderSource(vertex, 1, &vertexShaderSource, NULL);glShaderSource(fragment, 1, &fragmentShaderSource, NULL);int success = 0;char infoLog[1024];//4 執行shader代碼編譯 glCompileShader(vertex);//檢查vertex編譯結果glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);if (!success) {glGetShaderInfoLog(vertex, 1024, NULL, infoLog);std::cout << "Error: SHADER COMPILE ERROR --VERTEX" << "\n" << infoLog << std::endl;}glCompileShader(fragment);//檢查fragment編譯結果glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);if (!success) {glGetShaderInfoLog(fragment, 1024, NULL, infoLog);std::cout << "Error: SHADER COMPILE ERROR --FRAGMENT" << "\n" << infoLog << std::endl;}//5 創建一個Program殼子program = glCreateProgram();//6 將vs與fs編譯好的結果放到program這個殼子里glAttachShader(program, vertex);glAttachShader(program, fragment);//7 執行program的鏈接操作,形成最終可執行shader程序glLinkProgram(program);//檢查鏈接錯誤glGetProgramiv(program, GL_LINK_STATUS, &success);if (!success) {glGetProgramInfoLog(program, 1024, NULL, infoLog);std::cout << "Error: SHADER LINK ERROR " << "\n" << infoLog << std::endl;}//清理glDeleteShader(vertex);glDeleteShader(fragment);
}void prepareTextrue()
{//1 stbImage 讀取圖片int width, height, channels;//--反轉y軸stbi_set_flip_vertically_on_load(true);unsigned char* data = stbi_load("goku.jpg", &width, &height, &channels, STBI_rgb_alpha);//2 生成紋理并且激活單元綁定glGenTextures(1, &texture);//--激活紋理單元--glActiveTexture(GL_TEXTURE0);//--綁定紋理對象--glBindTexture(GL_TEXTURE_2D, texture);//3 傳輸紋理數據,開辟顯存glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);//***釋放數據stbi_image_free(data);//4 設置紋理的過濾方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);//5 設置紋理的包裹方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);//uglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);//v
}void render()
{//執行opengl畫布清理操作glClear(GL_COLOR_BUFFER_BIT);//1.綁定當前的programglUseProgram(program);//2 更新Uniform的時候,一定要先UserProgram//2.1 通過名稱拿到Uniform變量的位置LocationGLint location = glGetUniformLocation(program, "sampler");//2.2 通過Location更新Uniform變量的值glUniform1f(location, 0);GLint locationTransform = glGetUniformLocation(program, "transform");//transpose參數:表示是否對傳輸進去的矩陣數據進行轉置glUniformMatrix4fv(locationTransform, 1, GL_FALSE, glm::value_ptr(transform));GLint locationviewMatrix = glGetUniformLocation(program, "viewMatrix");glUniformMatrix4fv(locationviewMatrix, 1, GL_FALSE, glm::value_ptr(viewMatrix));GLint locationorthoMatrix = glGetUniformLocation(program, "orthoMatrix");glUniformMatrix4fv(locationorthoMatrix, 1, GL_FALSE, glm::value_ptr(orthoMatrix));//3 綁定當前的vaoglBindVertexArray(vao);//4 發出繪制指令//glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
}int main()
{//初始化glfw環境glfwInit();//設置opengl主版本號glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);//設置opengl次版本號glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);//設置opengl啟用核心模式glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);//創建窗體對象GLFWwindow* window = glfwCreateWindow(800, 600, "lenarnOpenGL", nullptr, nullptr);//設置當前窗體對象為opengl的繪制舞臺glfwMakeContextCurrent(window);//窗體大小回調glfwSetFramebufferSizeCallback(window, frameBufferSizeCallbakc);//鍵盤相應回調glfwSetKeyCallback(window, glfwKeyCallback);//使用glad加載所有當前版本opengl的函數if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){std::cout << "初始化glad失敗" << std::endl;return -1;};//設置opengl視口大小和清理顏色glViewport(0, 0, 800, 600);glClearColor(0.2f, 0.3f, 0.3f, 1.0f);//shaderprepareShader();//vaoprepareVAO();//textureprepareTextrue();prepareCamera();prepareOrtho();//執行窗體循環while (!glfwWindowShouldClose(window)){//接受并分發窗體消息//檢查消息隊列是否有需要處理的鼠標、鍵盤等消息//如果有的話就將消息批量處理,清空隊列glfwPollEvents();//渲染操作render();//切換雙緩存glfwSwapBuffers(window);}//推出程序前做相關清理glfwTerminate();return 0;
}
在vao中給入模型坐標,模型坐標經過變換后轉換成世界坐標,世界坐標經過視圖變換矩陣變換為相機坐標,相機坐標經過正交投影變換為NDC坐標。
在構造正交投影矩陣過程中,傳入的參數為盒體的大小,只有在盒體范圍內的坐標點才會保留,范圍外的將會被裁剪。
透視投影
例子
#include <glad/glad.h>//glad必須在glfw頭文件之前包含
#include <GLFW/glfw3.h>
#include <iostream>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"//GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/string_cast.hpp>void frameBufferSizeCallbakc(GLFWwindow* window, int width, int height)
{glViewport(0, 0, width, height);
}
void glfwKeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
}GLuint program = 0;
GLuint vao = 0;
GLuint texture = 0;
glm::mat4 transform(1.0f);//4×4單位矩陣
glm::mat4 viewMatrix(1.0f);
glm::mat4 orthoMatrix(1.0f);
glm::mat4 perspectiveMatrix(1.0f);
void prepareCamera()
{//lookat:生成一個viewMatrix//eye:當前攝像機所在的位置//center:當前攝像機看向的那個點//up:穹頂向量viewMatrix = glm::lookAt(glm::vec3(0.0f, 0.0f, 5.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
}
void prepareOrtho()
{//參數為盒體上下左右遠近orthoMatrix = glm::ortho(-2.0f, 2.0f, -2.0f, 2.0f, 2.0f, -2.0f);
}
void preparePerspective()
{//fovy:y軸方向的視張角,弧度單位//aspect:近平面的橫縱百分比//near:近平面距離//far:遠平面距離perspectiveMatrix = glm::perspective(glm::radians(60.0f), 800.0f / 600, 0.1f, 1000.0f);
}
void prepareVAO()
{//positionsfloat positions[] = {-1.0f, 0.0f, 0.0f,1.0f, 0.0f, 0.0f,0.0f, 1.0f, 0.0f,};//顏色float colors[] = {-1.0f, 0.0f, 0.0f,1.0f, 0.0f, 0.0f,0.0f, 1.0f, 0.0f,};//索引unsigned int indices[] = {0, 1, 2,};//uv坐標float uvs[] = {0.0f, 0.0f,1.0f, 0.0f,0.5f, 1.0f,};//2 VBO創建GLuint posVbo = 0;GLuint colorVbo = 0;GLuint uvVbo = 0;glGenBuffers(1, &posVbo);glBindBuffer(GL_ARRAY_BUFFER, posVbo);glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);glGenBuffers(1, &colorVbo);glBindBuffer(GL_ARRAY_BUFFER, colorVbo);glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);glGenBuffers(1, &uvVbo);glBindBuffer(GL_ARRAY_BUFFER, uvVbo);glBufferData(GL_ARRAY_BUFFER, sizeof(uvs), uvs, GL_STATIC_DRAW);//3 EBO創建GLuint ebo = 0;glGenBuffers(1, &ebo);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);//4 VAO創建vao = 0;glGenVertexArrays(1, &vao);glBindVertexArray(vao);//5 綁定vbo ebo 加入屬性描述信息//5.1 加入位置屬性描述信息glBindBuffer(GL_ARRAY_BUFFER, posVbo);glEnableVertexAttribArray(0);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);//5.2 加入顏色屬性描述信息glBindBuffer(GL_ARRAY_BUFFER, colorVbo);glEnableVertexAttribArray(1);glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);//5.3 加入uv屬性描述數據glBindBuffer(GL_ARRAY_BUFFER, uvVbo);glEnableVertexAttribArray(2);glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);//5.2 加入ebo到當前的vaoglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);glBindVertexArray(0);
}
void prepareShader() {//1 完成vs與fs的源代碼,并且裝入字符串//aPos作為attribute(屬性)傳入shader不允許更改的const char* vertexShaderSource ="#version 330 core\n""layout (location = 0) in vec3 aPos;\n""layout (location = 1) in vec3 aColor;\n""layout (location = 2) in vec2 aUV;\n""out vec3 color;\n""out vec2 uv;\n""uniform mat4 transform;\n""uniform mat4 viewMatrix;\n""uniform mat4 perspectiveMatrix;\n""void main()\n""{\n"" vec4 position = vec4(aPos, 1.0);\n"" position = perspectiveMatrix * viewMatrix * transform * position;\n"" gl_Position = position;\n"" color = aColor;\n"" uv = aUV;\n""}\0";const char* fragmentShaderSource ="#version 330 core\n""out vec4 FragColor;\n""in vec3 color;\n""in vec2 uv;\n""uniform sampler2D sampler;\n""void main()\n""{\n"" FragColor = texture(sampler, uv);\n""}\n\0";//2 創建Shader程序(vs、fs)GLuint vertex, fragment;vertex = glCreateShader(GL_VERTEX_SHADER);fragment = glCreateShader(GL_FRAGMENT_SHADER);//3 為shader程序輸入shader代碼glShaderSource(vertex, 1, &vertexShaderSource, NULL);glShaderSource(fragment, 1, &fragmentShaderSource, NULL);int success = 0;char infoLog[1024];//4 執行shader代碼編譯 glCompileShader(vertex);//檢查vertex編譯結果glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);if (!success) {glGetShaderInfoLog(vertex, 1024, NULL, infoLog);std::cout << "Error: SHADER COMPILE ERROR --VERTEX" << "\n" << infoLog << std::endl;}glCompileShader(fragment);//檢查fragment編譯結果glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);if (!success) {glGetShaderInfoLog(fragment, 1024, NULL, infoLog);std::cout << "Error: SHADER COMPILE ERROR --FRAGMENT" << "\n" << infoLog << std::endl;}//5 創建一個Program殼子program = glCreateProgram();//6 將vs與fs編譯好的結果放到program這個殼子里glAttachShader(program, vertex);glAttachShader(program, fragment);//7 執行program的鏈接操作,形成最終可執行shader程序glLinkProgram(program);//檢查鏈接錯誤glGetProgramiv(program, GL_LINK_STATUS, &success);if (!success) {glGetProgramInfoLog(program, 1024, NULL, infoLog);std::cout << "Error: SHADER LINK ERROR " << "\n" << infoLog << std::endl;}//清理glDeleteShader(vertex);glDeleteShader(fragment);
}void prepareTextrue()
{//1 stbImage 讀取圖片int width, height, channels;//--反轉y軸stbi_set_flip_vertically_on_load(true);unsigned char* data = stbi_load("goku.jpg", &width, &height, &channels, STBI_rgb_alpha);//2 生成紋理并且激活單元綁定glGenTextures(1, &texture);//--激活紋理單元--glActiveTexture(GL_TEXTURE0);//--綁定紋理對象--glBindTexture(GL_TEXTURE_2D, texture);//3 傳輸紋理數據,開辟顯存glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);//***釋放數據stbi_image_free(data);//4 設置紋理的過濾方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);//5 設置紋理的包裹方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);//uglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);//v
}void render()
{//執行opengl畫布清理操作glClear(GL_COLOR_BUFFER_BIT);//1.綁定當前的programglUseProgram(program);//2 更新Uniform的時候,一定要先UserProgram//2.1 通過名稱拿到Uniform變量的位置LocationGLint location = glGetUniformLocation(program, "sampler");//2.2 通過Location更新Uniform變量的值glUniform1f(location, 0);GLint locationTransform = glGetUniformLocation(program, "transform");//transpose參數:表示是否對傳輸進去的矩陣數據進行轉置glUniformMatrix4fv(locationTransform, 1, GL_FALSE, glm::value_ptr(transform));GLint locationviewMatrix = glGetUniformLocation(program, "viewMatrix");glUniformMatrix4fv(locationviewMatrix, 1, GL_FALSE, glm::value_ptr(viewMatrix));GLint locationperspectiveMatrix = glGetUniformLocation(program, "perspectiveMatrix");glUniformMatrix4fv(locationperspectiveMatrix, 1, GL_FALSE, glm::value_ptr(perspectiveMatrix));//3 綁定當前的vaoglBindVertexArray(vao);//4 發出繪制指令//glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
}int main()
{//初始化glfw環境glfwInit();//設置opengl主版本號glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);//設置opengl次版本號glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);//設置opengl啟用核心模式glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);//創建窗體對象GLFWwindow* window = glfwCreateWindow(800, 600, "lenarnOpenGL", nullptr, nullptr);//設置當前窗體對象為opengl的繪制舞臺glfwMakeContextCurrent(window);//窗體大小回調glfwSetFramebufferSizeCallback(window, frameBufferSizeCallbakc);//鍵盤相應回調glfwSetKeyCallback(window, glfwKeyCallback);//使用glad加載所有當前版本opengl的函數if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){std::cout << "初始化glad失敗" << std::endl;return -1;};//設置opengl視口大小和清理顏色glViewport(0, 0, 800, 600);glClearColor(0.2f, 0.3f, 0.3f, 1.0f);//shaderprepareShader();//vaoprepareVAO();//textureprepareTextrue();prepareCamera();preparePerspective();//執行窗體循環while (!glfwWindowShouldClose(window)){//接受并分發窗體消息//檢查消息隊列是否有需要處理的鼠標、鍵盤等消息//如果有的話就將消息批量處理,清空隊列glfwPollEvents();//渲染操作render();//切換雙緩存glfwSwapBuffers(window);}//推出程序前做相關清理glfwTerminate();return 0;
}