【OpenGL學習】(二)OpenGL渲染簡單圖形

文章目錄

  • 【OpenGL學習】(二)OpenGL渲染簡單圖形
    • OpenGL渲染圖形流程
    • 頂點,圖元和片元
    • VAO,VBO ,EBO
    • 著色器
    • 示例:使用OpenGL渲染三角形

【OpenGL學習】(二)OpenGL渲染簡單圖形

OpenGL渲染圖形流程

CPU(中央處理器)↓
初始化窗口與OpenGL上下文↓
編譯并鏈接著色器程序 ↓
準備頂點數據(頂點位置、顏色、法線、紋理坐標等)↓
創建并綁定:- VAO(頂點數組對象)← 用于記錄 VBO/EBO 的綁定狀態和頂點屬性配置↓創建并綁定:- VBO(頂點緩沖對象)← 存儲所有頂點屬性數據(位置信息、顏色、紋理坐標等)- EBO(索引緩沖對象,可選)← 存儲索引數據,減少冗余頂點設置頂點屬性指針(glVertexAttribPointer)← 告訴 OpenGL 如何解析 VBO 中的頂點數據啟用頂點屬性數組(glEnableVertexAttribArray)↑(這些設置會被 VAO 記錄下來)調用:- glBufferData → 將頂點數據或索引數據從 CPU 傳輸到 GPU 顯存中(顯卡緩沖區)↓
====================  GPU 開始接管渲染流程 ====================
頂點著色器(Vertex Shader)- 每個頂點執行一次- 坐標變換:模型矩陣 × 視圖矩陣 × 投影矩陣- 傳出數據供后續階段使用(如顏色、紋理坐標)↓
圖元裝配(Primitive Assembly)- 將一組頂點組裝為圖元(如三角形、線段)↓
(可選)幾何著色器(Geometry Shader)- 每個圖元執行一次- 可動態生成新的頂點或圖元↓
光柵化(Rasterization)- 將圖元轉換為片元(像素候選)- 生成每個片元的屏幕位置↓
片段著色器(Fragment Shader)- 每個片元執行一次- 計算顏色值(光照、紋理采樣、顏色混合等)↓
測試與混合階段(由固定功能單元執行)- 深度測試、模板測試- α混合、遮擋判斷↓
幀緩沖(Framebuffer)- 最終圖像寫入幀緩沖 → 顯示在屏幕

在這里插入圖片描述
圖片來源:https://geekdaxue.co/read/Learn-OpenGL-CN/01-Getting-Started-04-Hello-Triangle.md

頂點,圖元和片元

頂點(Vertex)是圖形的基本構建單位,表示圖形的一個頂點,通常包括:

  • 位置坐標(Position):如三維空間中的 (x, y, z)
  • 顏色信息(Color)
  • 紋理坐標(UV)
  • 法向量(Normal)
  • 其他自定義屬性(如切線、位移等)

圖元(Primitive)是由多個頂點組成的幾何形狀單元,比如:

  • 點(GL_POINTS)→ 每個頂點單獨成圖元
  • 線段(GL_LINES)→ 每兩個頂點組成一條線
  • 三角形(GL_TRIANGLES)→ 每三個頂點組成一個三角形
  • 更多復合圖元(如 GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN)

片元(Fragment)是每個圖元經過光柵化后生成的像素候選者,這些片元會傳入片段著色器進行著色計算(顏色、紋理、光照等)。在經過深度測試、模板測試、混合等處理之后,部分片元會變成屏幕上的像素。

VAO,VBO ,EBO

VAO(頂點數組對象,Vertex Array Object)用于 存儲頂點屬性配置狀態,如頂點屬性指針、VBO綁定狀態、EBO綁定狀態等。每次繪制時只需綁定一次 VAO,而不用重復設置頂點屬性。

VBO(頂點緩沖對象,Vertex Buffer Object)用于在 GPU 顯存中存儲頂點數據(如位置、顏色、法線、紋理坐標等),避免每次繪制時從 CPU 向 GPU 頻繁傳輸數據,提升效率。

EBO(元素緩沖對象,Element Buffer Object)用于在 繪制圖形時按照索引重用頂點數據。節省存儲空間,避免重復頂點。

著色器

著色器(Shader)是運行在 GPU 上的小程序,用于控制圖形渲染的每個階段。它是實現可編程渲染管線的核心。

著色器的主要類型:

著色器類型作用
頂點著色器 (Vertex Shader)處理每個頂點的位置變換、法線、紋理坐標等
片段著色器 (Fragment Shader)處理每個像素(片元)的顏色計算、紋理映射、光照等
幾何著色器(可選) (Geometry Shader)處理圖元(點、線、三角形),可生成新圖元
曲面細分控制/評估著色器(可選)用于對幾何細分
計算著色器(Compute Shader)用于并行計算任務,不用于圖形繪制

著色器使用的語言是GLSL(OpenGL Shading Language)。GLSL的語法類似于 C 語言,且可以運行于 GPU 上。我們需要在 C++ 中編寫 GLSL 代碼(字符串形式),然后使用 OpenGL API 編譯和鏈接著色器。

示例:使用OpenGL渲染三角形

#include <glad/glad.h>  // 加載 OpenGL 函數指針
#include <GLFW/glfw3.h> // GLFW 用于創建窗口和處理輸入#include <iostream>   // 回調函數聲明:當窗口大小發生改變時調用
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
// 處理輸入的函數聲明
void processInput(GLFWwindow* window);// 設置窗口寬高
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;// 頂點著色器GLSL源碼
const char* vertexShaderSource = "#version 330 core\n" // 使用 OpenGL 3.3 對應的 GLSL 版本(即 GLSL 3.30)
"layout (location = 0) in vec3 aPos;\n"  // 頂點位置屬性,位置值為0
"void main()\n"
"{\n"
"   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"  // 設置頂點位置
"}\0";// 片段著色器GLSL源碼
const char* fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"  // 片段輸出顏色
"void main()\n"
"{\n"
"   FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"  // 設置輸出顏色為橙色
"}\n\0";int main()
{// 初始化并配置 GLFWglfwInit();glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // OpenGL 主版本號glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // OpenGL 次版本號glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 使用核心模式#ifdef __APPLE__glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // MacOS 需要加這句
#endif// 創建 GLFW 窗口GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);if (window == NULL){std::cout << "Failed to create GLFW window" << std::endl;glfwTerminate(); // 初始化失敗,退出程序return -1;}glfwMakeContextCurrent(window); // 將窗口上下文設為當前線程上下文glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); // 設置窗口大小改變時的回調// 初始化 GLAD,用于加載 OpenGL 函數if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){std::cout << "Failed to initialize GLAD" << std::endl;return -1;}// ------------------構建并編譯著色器程序------------------// 頂點著色器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);std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;}// 片段著色器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);std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;}// 著色器程序unsigned int shaderProgram = glCreateProgram();           // 創建程序對象glAttachShader(shaderProgram, vertexShader);              // 附加著色器glAttachShader(shaderProgram, fragmentShader);glLinkProgram(shaderProgram);                             // 鏈接程序// 檢查鏈接錯誤glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);if (!success) {glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;}// 刪除已編譯的著色器對象,已鏈接到程序中不再需要glDeleteShader(vertexShader);glDeleteShader(fragmentShader);// --------------------------------------------------------// 設置頂點數據和緩沖,并配置頂點屬性float vertices[] = {-0.5f, -0.5f, 0.0f, // 左下角0.5f, -0.5f, 0.0f, // 右下角0.0f,  0.5f, 0.0f  // 頂部};// unsigned int VBO, VAO;glGenVertexArrays(1, &VAO); // 創建頂點數組對象glGenBuffers(1, &VBO);      // 創建頂點緩沖對象glBindVertexArray(VAO);     // 綁定 VAOglBindBuffer(GL_ARRAY_BUFFER, VBO); // 綁定 VBO glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);// 傳入數據// 設置頂點屬性指針glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);glEnableVertexAttribArray(0); // 啟用頂點屬性glBindBuffer(GL_ARRAY_BUFFER, 0); // 解綁 VBO,為了安全,非必須glBindVertexArray(0);            // 解綁 VAO// 可以取消注釋以使用線框模式繪制:也就是不填充圖形,只畫出邊框線// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);// 渲染循環while (!glfwWindowShouldClose(window)){// 處理輸入processInput(window);// 清屏并設置背景顏色glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);// 繪制三角形glUseProgram(shaderProgram); // 使用著色器程序glBindVertexArray(VAO);      // 綁定 VAOglDrawArrays(GL_TRIANGLES, 0, 3); // 從第0個頂點繪制3個頂點構成的三角形// 交換緩沖區并查詢IO事件glfwSwapBuffers(window);glfwPollEvents();}// 可選:釋放所有資源glDeleteVertexArrays(1, &VAO);glDeleteBuffers(1, &VBO);glDeleteProgram(shaderProgram);// 釋放 GLFW 資源glfwTerminate();return 0;
}// 處理輸入:如果按下 ESC 鍵,則關閉窗口
void processInput(GLFWwindow* window)
{if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)glfwSetWindowShouldClose(window, true);
}// 當窗口大小發生改變時,自動調整視口大小
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{glViewport(0, 0, width, height); // 設置 OpenGL 視口大小
}

在這里插入圖片描述
只畫邊框線:

參考:
https://learnopengl-cn.github.io/01%20Getting%20started/04%20Hello%20Triangle/

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/81273.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/81273.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/81273.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于STM32的INA226電壓電流檢測儀

系統總體框圖 功率檢測裝置原理圖功能及模塊連接說明 一、系統功能概述 該裝置以STM32F103C8T6微控制器為核心&#xff0c;集成功率檢測、數據交互、狀態顯示和用戶提示功能&#xff0c;通過模塊化設計實現穩定運行。 二、各模塊功能及連接方式 按鍵模塊 功能&#xff1a…

YOLOv2目標檢測算法:速度與精度的平衡之道

一、YOLOv2的核心改進&#xff1a;從V1到V2的蛻變 YOLOv2作為YOLO系列的第二代算法&#xff0c;在繼承V1端到端、單階段檢測的基礎上&#xff0c;針對V1存在的小目標檢測弱、定位精度低等問題進行了全方位升級&#xff0c;成為目標檢測領域的重要里程碑。 &#xff08;一&am…

將嵌入映射到 Elasticsearch 字段類型:semantic_text、dense_vector、sparse_vector

作者&#xff1a; Andre Luiz 討論如何以及何時使用 semantic_text、dense_vector 或 sparse_vector&#xff0c;以及它們與嵌入生成的關系。 通過這個自定進度的 Search AI 實踐學習親自體驗向量搜索。你可以開始免費云試用&#xff0c;或者在本地機器上嘗試 Elastic。 多年來…

uniapp取消瀏覽自動填充

為了防止瀏覽器自動將記住的密碼回填進type"password"輸入框&#xff0c;所以在type"password"輸入框上面加了兩行代碼&#xff0c;使瀏覽器將密碼填充到新加的輸入框里&#xff0c;并將這兩個input隱藏掉 <input type"password" autocomple…

從數據包到可靠性:UDP/TCP協議的工作原理分析

之前我們已經使用udp/tcp的相關接口寫了一些簡單的客戶端與服務端代碼。也了解了協議是什么&#xff0c;包括自定義協議和知名協議比如http/https和ssh等。現在我們再回到傳輸層&#xff0c;對udp和tcp這兩傳輸層巨頭協議做更深一步的分析。 一.UDP UDP相關內容很簡單&#xf…

顯卡、Cuda和pytorch兼容問題

這里寫目錄標題 驅動與CUDA版本兼容性問題1. **驅動與CUDA版本兼容性問題**2. **任務特性與硬件適配差異**3. **優化策略與框架配置差異**4. **散熱與功耗限制**5. **數據傳輸與CPU瓶頸**排查建議總結 查詢PyTorch中實際使用的CUDA版本**1. 查詢PyTorch中實際使用的CUDA版本***…

DeepSeek 大模型部署全指南:常見問題、優化策略與實戰解決方案

DeepSeek 作為當前最熱門的開源大模型之一&#xff0c;其強大的語義理解和生成能力吸引了大量開發者和企業關注。然而在實際部署過程中&#xff0c;無論是本地運行還是云端服務&#xff0c;用戶往往會遇到各種技術挑戰。本文將全面剖析 DeepSeek 部署中的常見問題&#xff0c;提…

Hadoop的目錄結構和組成

Hadoop 目錄結構 bin 目錄&#xff1a;包含了 Hadoop 的各種命令行工具&#xff0c;如hadoop、hdfs等&#xff0c;用于啟動和管理 Hadoop 集群&#xff0c;以及執行各種數據處理任務。etc 目錄&#xff1a;存放 Hadoop 的配置文件&#xff0c;包括core-site.xml、hdfs-site.xm…

Python Matplotlib 庫【繪圖基礎庫】全面解析

讓AI成為我們的得力助手&#xff1a;《用Cursor玩轉AI輔助編程——不寫代碼也能做軟件開發》 一、發展歷程 Matplotlib 由 John D. Hunter 于 2003 年創建&#xff0c;靈感來源于 MATLAB 的繪圖系統。作為 Python 生態中最早的可視化工具之一&#xff0c;它逐漸成為科學計算領…

車載以太網驅動智能化:域控架構設計與開發實踐

title: 車載以太網驅動專用車智能化&#xff1a;域控架構設計與開發實踐 date: 2023-12-01 categories: 新能源汽車 tags: [車載以太網, 電子電氣架構, 域控架構, 專用車智能化, SOME/IP, AUTOSAR] 引言&#xff1a;專用車智能化轉型的挑戰與機遇 專用車作為城市建設與工業運輸…

圖論模板(部分)

圖論模板&#xff08;部分&#xff09; maincpp #include <iostream> #include <climits> #include <limits>typedef unsigned long long ull; typedef long long ll; typedef long double ld; typedef std::pair<int, int> PII;#define rep(i, n) f…

2025年【道路運輸企業安全生產管理人員】考試題庫及道路運輸企業安全生產管理人員考試內容

一、考試概述 2025年道路運輸企業安全生產管理人員考試題庫由【安全生產模擬考試一點通】平臺發布&#xff0c;涵蓋安全生產法律法規、車輛技術管理、從業人員管理、應急預案編制等核心領域。考試重點考察考生對安全生產主體責任、風險管控、隱患排查等實務操作的掌握程度&…

分貝計在噪音污染源識別中的用途

分貝計在噪音污染源識別中的作用 噪音污染是現代社會面臨的一個普遍問題&#xff0c;尤其在城市化進程加快的背景下&#xff0c;交通、工業、建筑和娛樂活動等產生的噪音對人們的生活質量和健康造成了嚴重影響。為了有效管理和控制噪音污染&#xff0c;首先需要準確識別噪音的…

deepin v23.1 搜狗輸入法next配置中文輸入法下默認用英文標點

deepin23.1下, fcitx5的 deepin next搜狗輸入法的屬性頁無法配置中文狀態下默認用英文標點, 但是可以改以下配置來實現這一點. 搜狗輸入法運行期間&#xff0c;用戶修改的配置被存儲在以下位置&#xff1a; ~/.config/cpis/module/im/fcitx5/com.sogou.ime.ng.fcitx5.deepin/k…

C語言:在 Win 10 上,g++ 如何編譯 gtk 應用程序

在 Windows 10 上使用 g&#xff08;或 gcc&#xff09;編譯基于 GTK 的 C 語言程序是完全可行的&#xff0c;且相比 Tcc 更為推薦&#xff0c;因為 g&#xff08;GNU 編譯器套件&#xff09;對 GTK 的支持更加完善&#xff0c;配置也更簡單。以下是詳細步驟和注意事項&#xf…

84.評論日記

原鏈接 這個視頻我發了四五條評論。評論內容甚至和下面這個視頻內的其他評論一樣。 找了另外的賬號也發了。 發現&#xff0c;無論是我這個賬號&#xff0c;還是其他的賬號&#xff0c;評論都無法看到。 我大膽猜測有一種機制&#xff0c;某些官號會被設置成一種高檢測的等…

【RabbitMQ】整合 SpringBoot,實現工作隊列、發布/訂閱、路由和通配符模式

文章目錄 工作隊列模式引入依賴配置聲明生產者代碼消費者代碼 發布/訂閱模式引入依賴聲明生產者代碼發送消息 消費者代碼運行程序 路由模式聲明生產者代碼消費者代碼運行程序 通配符模式聲明生產者代碼消費者代碼運行程序 工作隊列模式 引入依賴 我們在創建 SpringBoot 項目的…

Python-92:最大乘積區間問題

問題描述 小R手上有一個長度為 n 的數組 (n > 0)&#xff0c;數組中的元素分別來自集合 [0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]。小R想從這個數組中選取一段連續的區間&#xff0c;得到可能的最大乘積。 你需要幫助小R找到最大乘積的區間&#xff0c;并輸出這…

windows觸摸板快捷指南

以下是結構化整理后的觸控手勢說明&#xff0c;采用清晰的層級劃分和標準化表述&#xff1a; **觸控手勢操作規范****1. 單指操作****2. 雙指操作****3. 三指操作****4. 四指操作** **優化說明&#xff1a;** 觸控手勢操作規范 1. 單指操作 手勢功能描述等效操作單擊滑動選擇…

VSCode launch.json 配置參數詳解

使用 launch.json 配置調試環境時&#xff0c;會涉及到多個參數&#xff0c;用于定義調試器的行為和目標執行環境。以下是一些常用的配置參數&#xff1a; 1、"type" &#xff1a;指定調試器的類型&#xff0c;例如 "node" 表示 Node.js 調試器&#xff0…