seo網(wǎng)站首頁優(yōu)化排名怎么做免費(fèi)友鏈互換
文章目錄
- 一些概念
- 坐標(biāo)轉(zhuǎn)換階段
- 頂點(diǎn)著色器
- 片段著色器
- VBO
- VAO
- 實(shí)戰(zhàn)
- 簡介
- main.cpp
- CMakeLists.txt
- 最終效果
一些概念
坐標(biāo)轉(zhuǎn)換階段
概述: 模型空間、世界空間、視圖空間和裁剪空間是對象在3D場景中經(jīng)歷的不同坐標(biāo)變換階段。每個(gè)空間對應(yīng)渲染管道的一個(gè)步驟,逐步將模型從其初始位置轉(zhuǎn)換到最終屏幕上的位置
模型空間:
- 定義:這是對象的本地坐標(biāo)系,是模型創(chuàng)建時(shí)的坐標(biāo)
- 作用:模型空間定義了物體的基本形狀和幾何信息,不受場景中其他物體位置的影響。每個(gè)模型都有自己的模型空間坐標(biāo)
- 轉(zhuǎn)換:通過模型矩陣,可以將模型空間的坐標(biāo)轉(zhuǎn)換為世界空間
世界空間:
- 定義:這是整個(gè)場景的坐標(biāo)系,所有模型在世界空間中都有唯一的位置和方向,可以視為“全局坐標(biāo)系”
- 作用:將所有對象放置在同一個(gè)坐標(biāo)系統(tǒng)中,確保它們相對位置正確
- 轉(zhuǎn)換:通過應(yīng)用視圖矩陣,將世界空間的坐標(biāo)轉(zhuǎn)換為視圖空間,視圖矩陣通?;跀z像機(jī)的位置和方向
視圖空間:
- 定義:又稱為“攝像機(jī)空間“,是以攝像機(jī)位置為原點(diǎn)的坐標(biāo)系,此時(shí)場景中的所有對象都以攝像機(jī)為參考重新定位
- 作用:使得所有對象相對于攝像機(jī)的位置和方向變得更直觀,便于確定哪些對象可見、如何投影到屏幕
- 轉(zhuǎn)換:使用投影矩陣將視圖空間轉(zhuǎn)換為裁剪空間,這一步?jīng)Q定了圖像的投影類型(如透視投影或正交投影)
裁剪空間:
- 定義:應(yīng)用投影變換后的空間,此時(shí)3D場景的坐標(biāo)被轉(zhuǎn)換為一個(gè)標(biāo)準(zhǔn)化的3D盒子,所有可見的坐標(biāo)x,y,z值均被限制在-1到1之間
- 作用:裁剪空間便于對視錐外部的物體進(jìn)行裁剪,只保留可見部分。裁剪后的坐標(biāo)將進(jìn)行透視除法,映射到2D屏幕上的坐標(biāo),即歸一化設(shè)備坐標(biāo)
- 轉(zhuǎn)換:裁剪空間進(jìn)一步轉(zhuǎn)換為屏幕空間,經(jīng)過視口變換,使坐標(biāo)適配屏幕的分辨率和比例
頂點(diǎn)著色器
概述: 頂點(diǎn)著色器(Vertex Shader)是對輸入的頂點(diǎn)進(jìn)行處理,頂點(diǎn)是組成幾何體的基本元素,比如三角形的每個(gè)角都是一個(gè)頂點(diǎn)
作用:
- 頂點(diǎn)位置變換:頂點(diǎn)著色器通常會將頂點(diǎn)從模型空間(即對象的局部坐標(biāo)系)轉(zhuǎn)換到世界空間、視圖空間,最后轉(zhuǎn)換到裁剪空間,以便在屏幕上正確顯示
- 頂點(diǎn)屬性處理:除了位置,頂點(diǎn)著色器還可以處理其他與頂點(diǎn)相關(guān)的屬性,比如法線、紋理坐標(biāo)、顏色等
- 光照計(jì)算:在某些情況下,頂點(diǎn)著色器可以進(jìn)行基礎(chǔ)的光照計(jì)算,如使用法線來計(jì)算頂點(diǎn)的光照效果
輸入: 頂點(diǎn)的坐標(biāo)、法線、紋理坐標(biāo)等數(shù)據(jù)
輸出: 處理后的頂點(diǎn)坐標(biāo),如變換后的頂點(diǎn)位置和其他頂點(diǎn)屬性,供后續(xù)的圖形流水線使用
片段著色器
概述: 片段著色器(Framgment Shader)是屏幕上每個(gè)像素的潛在顏色值,在光柵化階段之后,每個(gè)幾何體被轉(zhuǎn)換為一系列像素片段,片段著色器負(fù)責(zé)確定這些片段的最終顏色
作用:
- 顏色計(jì)算:片段著色器通過對紋理、光照、材質(zhì)等信息的處理,確定每個(gè)像素的顏色,它通常會結(jié)合插值后的頂點(diǎn)屬性(如紋理坐標(biāo)或顏色)進(jìn)行復(fù)雜的顏色計(jì)算
- 光照效果:片段著色器可以進(jìn)行精確的光照計(jì)算,以便生成更逼真的陰影和高光效果
- 紋理映射:片段著色器可以從紋理中采樣,根據(jù)紋理坐標(biāo)獲取紋理顏色,并應(yīng)用到片段上
輸入: 每個(gè)片段的插值屬性(如紋理坐標(biāo)、顏色、發(fā)現(xiàn)等)
輸出: 每個(gè)片段的最終顏色值,傳遞給屏幕或幀緩沖區(qū)
VBO
概述: VBO(Vertex Buffer Object)是一個(gè)存儲在GPU內(nèi)存中的緩沖區(qū),用于存放頂點(diǎn)數(shù)據(jù)。通常,頂點(diǎn)數(shù)據(jù)包含頂點(diǎn)的坐標(biāo)、顏色、法線、紋理坐標(biāo)等信息。通過使用VBO,程序可以將這些頂點(diǎn)數(shù)據(jù)傳輸?shù)紾PU,這樣GPU可以在渲染時(shí)快速訪問它們,而不需要每幀都從CPU傳輸數(shù)據(jù)
關(guān)鍵步驟:
- 創(chuàng)建VBO:使用glGenBuffers()創(chuàng)建一個(gè)VBO
- 綁定VBO:使用glBindBuffer()綁定VBO,指定將要存儲的緩沖數(shù)據(jù)類型(如頂點(diǎn)數(shù)據(jù)GL_ARRY_BUFFER)
- 填充VBO:使用glBufferData()將頂點(diǎn)數(shù)據(jù)傳輸?shù)絍BO中
VAO
概述: VAO(Vertex Array Object)是一個(gè)用于保存VBO配置的對象,它記錄了與繪制頂點(diǎn)相關(guān)的所有狀態(tài)信息。VAO不僅僅是VBO的一個(gè)包裝器,它還保存了頂點(diǎn)屬性指針和啟用狀態(tài)。例如:每個(gè)頂點(diǎn)的布局、數(shù)據(jù)的解釋方式(如步幅、偏移量),以及使用的VBO。使用VAO可以簡化渲染過程,因?yàn)楫?dāng)VAO被綁定時(shí),所有與其關(guān)聯(lián)的VBO和頂點(diǎn)屬性信息都會自動(dòng)生效。
關(guān)鍵步驟:
- 創(chuàng)建VAO:使用glGenVertexArrays()創(chuàng)建一個(gè)VAO
- 綁定VAO:使用glBindVertexArray()綁定VAO
- 設(shè)置頂點(diǎn)屬性指針:使用glVertexAttribPointer()設(shè)置頂點(diǎn)屬性指針(告訴OpenGL如何解釋頂點(diǎn)數(shù)據(jù))
- 啟用頂點(diǎn)屬性:使用glEnableVertexAttribArray()啟用頂點(diǎn)屬性
實(shí)戰(zhàn)
簡介
怎么在vscode上使用cmake構(gòu)建項(xiàng)目,具體可以看這篇Windows上如何使用CMake構(gòu)建項(xiàng)目 - 凌云行者的博客
目的: 繪制一個(gè)三角形
環(huán)境:
- 編譯工具鏈:使用msys2安裝的mingw-gcc
- 依賴項(xiàng):glfw3:x64-mingw-static,glad:x64-mingw-static(通過vcpkg安裝)
main.cpp
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>using std::cout;
using std::endl;// 屏幕寬度
const unsigned int SCR_WIDTH = 800;
// 屏幕高度
const unsigned int SCR_HEIGHT = 600;// 窗口大小改變的回調(diào)函數(shù)
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {// 確保視口與新窗口尺寸匹配,注意在視網(wǎng)膜顯示器上,寬度和高度會顯著大于指定值glViewport(0, 0, width, height);
}// 處理輸入
void process_input(GLFWwindow* window) {// 按下ESC鍵時(shí)進(jìn)入if塊if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)// 關(guān)閉窗口glfwSetWindowShouldClose(window, true);
}// 頂點(diǎn)著色器源碼
const char *vertexShaderSource = "#version 330 core\n" // 指定了GLSL(OpenGL著色器語言)的版本"layout (location = 0) in vec3 aPos;\n" // 定義了一個(gè)輸入變量aPos,它是一個(gè)vec3類型的變量, 并且指定了它的位置值為0, 這意味著頂點(diǎn)屬性數(shù)組的第一個(gè)屬性將被綁定到這個(gè)變量"void main()\n""{\n"" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n" // 將輸入的頂點(diǎn)位置aPos轉(zhuǎn)換為一個(gè)四維向量,gl_Postion是OpengGL固定功能管線中用于存儲頂點(diǎn)位置的變量"}\0";// 片段著色器源碼
const char *fragmentShaderSource = "#version 330 core\n" // 指定了GLSL(OpenGL著色器語言)的版本"out vec4 FragColor;\n" // 定義了一個(gè)輸出變量FragColor,它是一個(gè)vec4類型的變量,表示片段顏色,out關(guān)鍵字表示這個(gè)變量將輸出到渲染管線的下一個(gè)階段"void main()\n""{\n"" FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n" // 將輸出顏色設(shè)置為橙色"}\n\0";int main() {// 初始化glfwglfwInit();// 設(shè)置opengl版本glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);// 使用核心模式:確保不使用任何被棄用的功能glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);// 創(chuàng)建glfw窗口GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "I am window title", NULL, NULL);if (window == NULL) {cout << "Failed to create glfw window" << endl;// 終止GLFWglfwTerminate();return -1;}// 設(shè)置當(dāng)前窗口的上下文glfwMakeContextCurrent(window);// 設(shè)置窗口大小改變的回調(diào)函數(shù)glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);// 加載opengl函數(shù)指針if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {cout << "Failed to initialize GLAD" << endl;return -1;}// 構(gòu)建并編譯頂點(diǎn)著色程序// 創(chuàng)建一個(gè)著色器對象,GL_VERTEX_SHADER表示頂點(diǎn)著色器unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);// 將著色器源碼附加到著色器對象上glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);// 編譯著色器glCompileShader(vertexShader);// 檢查著色器是否編譯成功int success;char infoLog[512];glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);if (!success) {glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n"<< infoLog << endl;}// 構(gòu)建并編譯片段著色器// 創(chuàng)建一個(gè)著色器對象,GL_FRAGMENT_SHADER表示片段著色器unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);// 將著色器源碼附加到著色器對象上glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);// 編譯著色器glCompileShader(fragmentShader);// 檢查著色器是否編譯成功glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);if (!success) {glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n"<< infoLog << endl;}// 創(chuàng)建著色器程序?qū)ο?/span>unsigned int shaderProgram = glCreateProgram();// 將著色器對象附加到著色器程序上glAttachShader(shaderProgram, vertexShader);glAttachShader(shaderProgram, fragmentShader);// 鏈接程序?qū)ο?/span>glLinkProgram(shaderProgram);// 檢查鏈接是否成功glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);if (!success) {glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n"<< infoLog << endl; }// 刪除著色器對象glDeleteShader(vertexShader);glDeleteShader(fragmentShader);// 設(shè)置三角形的頂點(diǎn)數(shù)據(jù)float vertices[] = {-0.5f, -0.5f, 0.0f, // 左下角0.5f, -0.5f, 0.0f, // 右下角0.0f, 0.5f, 0.0f // 頂部};// 生成一個(gè)VAOunsigned int VAO;glGenVertexArrays(1, &VAO);// 綁定VAO,使其成為當(dāng)前操作的VAOglBindVertexArray(VAO);// 生成一個(gè)VBOunsigned int VBO;glGenBuffers(1, &VBO);// 綁定VBO, 使其成為當(dāng)前操作的VBO,GL_ARRAY_BUFFER表示頂點(diǎn)緩沖區(qū)glBindBuffer(GL_ARRAY_BUFFER, VBO);// 為當(dāng)前綁定的VBO創(chuàng)建并初始化數(shù)據(jù)存儲,GL_STATIC_DRAW表示數(shù)據(jù)將一次性提供給緩沖區(qū),并且在之后的繪制過程中不會頻繁更改glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);// 定義頂點(diǎn)屬性的布局// - index:頂點(diǎn)屬性的索引// - size:每個(gè)頂點(diǎn)屬性的數(shù)量,每個(gè)頂點(diǎn)有三個(gè)分享// - type:數(shù)據(jù)類型// - normalized:是否將非浮點(diǎn)數(shù)值歸一化// - stride:連續(xù)頂點(diǎn)屬性之間的間隔// - pointer:數(shù)據(jù)在緩沖區(qū)中的偏移量glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (void*)0);// 啟用頂點(diǎn)屬性數(shù)組glEnableVertexAttribArray(0);// 解綁VBOglBindBuffer(GL_ARRAY_BUFFER, 0);// 解綁VAOglBindVertexArray(0);// 循環(huán)渲染while (!glfwWindowShouldClose(window)) { // 檢查是否應(yīng)該關(guān)閉窗口// 處理輸入process_input(window);// 清空屏幕所用的顏色glClearColor(0.2f, 0.3f, 0.3f, 1.0f);// 清空顏色緩沖,主要目的是為每一幀的渲染準(zhǔn)備一個(gè)干凈的畫布glClear(GL_COLOR_BUFFER_BIT);// 使用著色器程序glUseProgram(shaderProgram);// 綁定VAOglBindVertexArray(VAO);// 繪制三角形glDrawArrays(GL_TRIANGLES, 0 ,3);// 交換緩沖區(qū)glfwSwapBuffers(window);// 處理所有待處理事件,去poll所有事件,看看哪個(gè)沒處理的glfwPollEvents();}// 刪除VAOglDeleteVertexArrays(1, &VAO);// 刪除VBOglDeleteBuffers(1, &VBO);// 刪除著色器程序glDeleteProgram(shaderProgram);// 終止GLFW,清理GLFW分配的資源glfwTerminate();return 0;
}
CMakeLists.txt
# 設(shè)置CMake的最低版本要求
cmake_minimum_required(VERSION 3.10)
# 設(shè)置項(xiàng)目名稱
project(HelloTriangle)# vcpkg集成, 這里要換成你自己的vcpkg工具鏈文件和共享庫路徑
set(VCPKG_ROOT D:/software6/vcpkg/)
set(CMAKE_TOOLCHAIN_FILE ${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake)
set(CMAKE_PREFIX_PATH ${VCPKG_ROOT}/installed/x64-mingw-static/share)# 查找所需的包
find_package(glad CONFIG REQUIRED)
find_package(glfw3 CONFIG REQUIRED)# 添加可執(zhí)行文件
add_executable(HelloTriangle main.cpp)# 鏈接所需的庫
target_link_libraries(HelloTriangle PRIVATE glad::glad glfw)