創建GLFW窗口,開啟OpenGL之路

前言:本系列文章主要是一個學習筆記和總結,具體學習過程參考https://learnopengl-cn.github.io/這個網站的是學習OpenGL的一個很完美的新手教程。在這個部分系列中,我會以自己的理解詳細描述每個函數、方法的使用,以及關鍵參數的解釋。

注意!!!本系列屬于C/C++系列的OpenGL學習,不是python。但是學習明白原理后,使用其他語言應用也是大同小異。

使用軟件為Visual Studio 2022。

廢話少說,開始學習!

GLFW和GLAD

OpenGL并不為我們提供一個用于繪制圖像的窗口,它將這些操作抽象(Abstract)出去,交給其他組件完成。所以我們需要自己創建用于顯示繪制圖形的窗口,這就使用到了GLFW。當然可以使用其他的類似的庫,在不同平臺上你可以使用的庫也不同。

OpenGL驅動版本很多,其內部的多數函數位置都無法在編譯的時候確定下來,需要在運行的時候查詢,過程復雜,但是使用GLAD庫就可以簡化這個過程。

?GLFW、GLAD配置參考https://blog.csdn.net/qq_41777179/article/details/138134059

下面我們來下載GLFW和GLAD,下載網址為:
GLAD下載地址:https://glad.dav1d.de/
GLFW下載地址:https://www.glfw.org/download.html

我們先來下載GLFW和GLAD:

下載完成后可以得到兩個壓縮包,解壓得到:

這兩個先放在一邊,讓我來使用Visual Studio 2022創建一個C++的控制臺空項目

創建完成后,打開項目路徑,在如下位置創建一個Linking文件夾,并在Linking文件夾內創建lib和include文件夾:

然后找到剛才解壓的GLAD和glfw-3.4.bin.WIN64文件:
1、進入glfw-3.4.bin.WIN64文件夾內,選擇合適的vc版本Visual Studio 2022就選lib-vc2022,然后將其復制到Linking/lib下,并改名為GLFW;
2、進入glfw-3.4.bin.WIN64文件夾內,將include下的GLFW復制到Linking/include下
3、進入GLAD文件夾內,將include下的glad和KHR復制到Linking/include下
4、進入GLAD文件夾內,將res復制到Linking/include下

用Visual Studio 2022打開剛才生成的空項目。

有兩種簡單的打開方法:
1、拖動項目文件下的.xln文件到Visual Studio 2022桌面圖標上
2、打開VS2022后選擇項目(曾經打開過)

打開后,找到左側資源管理器中的文件項目,右擊項目文件,點擊屬性:

選擇VC++目錄,修改包含目錄,編輯為Linking/include文件夾所在位置:

同樣修改庫目錄,將其改為Linking/lib文件夾所在位置,同上述一樣。

隨后選擇鏈接器 -> 輸入,添加兩個附加依賴項:
1、GLFW\glfw3.lib
2、opengl32.lib(windows系統自帶opengl庫,x64也是opengl32.lib)

設置完后,選擇兩個位置為x64

然后需要添加現有項到項目:
1、項目路徑\Linking\include\src\glad.c
2、項目路徑\Linging\include\KHR\khrplatform.h

這樣就配置完成了

程↗序↘,啟→動↗!

#include <iostream>
#include <glad/glad.h>
#include <GLFW/glfw3.h>static float vertices[] = {-0.5f, -0.5f, 0.0f,0.5f, -0.5f, 0.0f,0.0f, 0.5f, 0.0f
};// 當用戶改變窗口的大小的時候,視口也應該被調整。
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {glViewport(0, 0, width, height);
}void registerFunction(GLFWwindow* window) {glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
}// 讀取用戶輸入,當程序運行時,按下ESC時退出進程
void processInput(GLFWwindow* window) {if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {glfwSetWindowShouldClose(window, true);}
}GLFWwindow* windowInit() {// 實例化窗口// 初始化GLFWglfwInit();glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);// 創建一個窗口對象,參數:寬、高、名稱、*、*,函數返回一個GLFWwindow對象GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL Window", NULL, NULL);if (window == NULL){std::cout << "Failed to create GLFW window" << std::endl;glfwTerminate();}// 通知GLFW將創建的窗口的上下文設置為當前線程的主上下文glfwMakeContextCurrent(window);// GLAD傳入了用來加載系統相關的OpenGL函數指針地址的函數if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {std::cout << "Failed to initialize GLAD" << std::endl;}// 通知OpenGL渲染窗口的尺寸大小——視口(Viewport)glViewport(0, 0, 800, 600);return window;
}unsigned int VAOInit() {unsigned int VAO;glGenVertexArrays(1, &VAO);glBindVertexArray(VAO);return VAO;
}unsigned int VBOInit() {unsigned int VBO;glGenBuffers(1, &VBO);glBindBuffer(GL_ARRAY_BUFFER, 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);return VBO;
}unsigned int vertexShaderInit() {// 頂點著色器源文件const char* vertexShaderSource ="#version 330 core\n""layout(location = 0) in vec3 aPos;\n""void main(){gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0f);}\n";// 創建頂點著色器并編譯unsigned int vertexShader;vertexShader = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);glCompileShader(vertexShader);// 返回頂點著色器對象return vertexShader;
}unsigned int fragmentShaderInit() {// 頂點著色器源文件const char* fragmentShaderSource ="#version 330 core\n""out vec4 FragColor;\n""void main(){FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);}\n";// 創建頂點著色器并編譯unsigned int fragmentShader;fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);glCompileShader(fragmentShader);// 返回頂點著色器對象return fragmentShader;
}unsigned int shaderProgramInit() {// 初始化著色器和著色器程序unsigned int vertexShader = vertexShaderInit();unsigned int fragmentShader = fragmentShaderInit();unsigned int shaderProgram = glCreateProgram();// 將著色器附加到著色器程序上glAttachShader(shaderProgram, vertexShader);glAttachShader(shaderProgram, fragmentShader);// 鏈接到著色器程序glLinkProgram(shaderProgram);// 激活著色器程序glUseProgram(shaderProgram);// 鏈接完刪除著色器對象glDeleteShader(vertexShader);glDeleteShader(fragmentShader);return shaderProgram;
}void render(unsigned int shaderProgram, unsigned int VAO) {// 設置清空顏色(重要!)glClearColor(0.2f, 0.3f, 0.3f, 1.0f);// 清空顏色緩沖區和深度緩沖區glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glUseProgram(shaderProgram);glBindVertexArray(VAO);glDrawArrays(GL_TRIANGLES, 0, 3);
}int main()
{GLFWwindow* window = windowInit();// 注冊函數framebuffer_size_callback,告知GLFW當窗口調整大小時調用這個函數registerFunction(window);unsigned int VAO = VAOInit();unsigned int VBO = VBOInit();unsigned int shaderProgram = shaderProgramInit();// glfwWindowShouldClose函數在我們每次循環的開始前檢查一次GLFW是否被要求退出while (!glfwWindowShouldClose(window)) {// 輸入processInput(window);// 渲染指令render(shaderProgram, VAO);// 檢查并調用事件,交換緩沖// glfwSwapBuffers函數會交換顏色緩沖glfwSwapBuffers(window);// glfwPollEvents函數檢查有沒有觸發什么事件(比如鍵盤輸入、鼠標移動等)、更新窗口狀并調用對應的回調函數glfwPollEvents();}// 渲染循環結束后我們需要正確釋放/刪除之前的分配的所有資源。glfwTerminate();return 0;
}

后面章節會一一介紹其中的函數,及其作用,運行結果如下:

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

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

相關文章

es通過分片遷移遷移解決磁盤不均勻問題

POST _cluster/reroute {"commands": [{"move": {"index": "xxx_detail","shard": 2,"from_node": "el8P9Ul","to_node": "4sDv-RD"}}] }查看遷移進程 GET _cat/shards?v查看磁盤…

c++打包pyd文件給Python使用調用函數

c打包pyd文件給Python使用調用函數C語言源碼&#xff1a;simplemath.cpp代碼&#xff1a;// // Created by ASFOR on 2025/9/11. // #include <pybind11/pybind11.h>namespace py pybind11;// 一個簡單的加法函數 int add(int a, int b) {return a b; }// 一個簡單的乘…

hadoop的api操作對象存儲

一、獲取文件或目錄1. 獲取某個目錄下的文件// 必須的依賴 import org.apache.hadoop.conf.Configuration import org.apache.hadoop.fs.{FileSystem, LocatedFileStatus, Path, RemoteIterator}// 獲取某個目錄下的文件路徑 def list_file(conf: Configuration, dir_path: Str…

《UE5_C++多人TPS完整教程》學習筆記52 ——《P53 FABRIK 算法(FABRIK IK)》

本文為B站系列教學視頻 《UE5_C多人TPS完整教程》 —— 《P53 FABRIK 算法&#xff08;FABRIK IK&#xff09; 的學習筆記&#xff0c;該系列教學視頻為計算機工程師、程序員、游戲開發者、作家&#xff08;Engineer, Programmer, Game Developer, Author&#xff09; Stephen …

HttpServletRequest vs ServletContext 全面解析

HttpServletRequest vs ServletContext 全面解析 一、 核心區別概覽特性HttpServletRequest (請求對象)ServletContext (Servlet上下文/應用對象)作用域請求范圍應用范圍生命周期從客戶端發出請求開始&#xff0c;到服務器返回響應結束。從Web應用啟動&#xff08;部署&#xf…

Java后端工程師如何學AI

Java后端工程師如何學AI 目錄 前言為什么Java后端工程師要學習AIAI學習路徑規劃基礎知識體系實踐項目建議學習資源推薦學習時間規劃常見問題與解決方案職業發展建議總結 前言 隨著人工智能技術的快速發展&#xff0c;AI已經不再是計算機科學專業的專屬領域。作為Java后端工…

Django REST Framework 中 @action 裝飾器詳解

概述 action 裝飾器是 Django REST Framework (DRF) 中 ViewSet 的一個核心功能&#xff0c;用于定義自定義路由方法。它允許開發者在標準的 CRUD 操作&#xff08;list、create、retrieve、update、destroy&#xff09;之外&#xff0c;創建符合特定業務需求的接口&#xff0c…

【重磅更新】RetroBoard 全面升級,讓敏捷回顧更高效、更安全、更貼心!

??????? ??????? ??????? ??????? ??????? ??????? ??????? ??????? ??????? ??????? ??????? ???????…

中州養老:華為云設備管理接口開發全流程

需求分析點擊同步數據時,要把華為云的數據拉取到我們的系統中對于新增設備操作,實際上這些參數與華為云產品我們添加設備時的參數是一樣的表結構設計E-R圖數據庫字段接口分析對于設備中的數據,我們既要再IOT平臺存儲,又要在數據庫中存儲.之所以保存兩份數據的原因:IOT平臺中只是…

Llama-Factory微調Qwen2.5-VL從數據集制作到部署記錄

Llama-Factory微調Qwen2.5-VL從數據集制作到部署記錄 電腦環境配置&#xff1a; 1.ubuntu24 2.3090(24G) 3.Cuda12.9 一、數據集制作 我的數據集主要是對圖像內容進行描述 1.Label-studio制作數據集 這是最原始的從零開始制作數據集的方法&#xff0c;不建議這樣做&#xff01;…

【藍橋杯真題67】C++數位和為偶數的數 第十五屆藍橋杯青少年創意編程大賽 算法思維 C++編程選拔賽真題解

C++數位和為偶數的數 第十五屆藍橋杯青少年創意編程大賽C++選拔賽真題 博主推薦 所有考級比賽學習相關資料合集【推薦收藏】 1、C++專欄 電子學會C++一級歷年真題解析 電子學會C++二級歷年真題解析

【計算機網絡 | 第11篇】寬帶接入技術及其發展歷程

文章目錄寬帶接入技術詳解數字傳輸系統技術演進早期電話網的傳輸技術演變數字傳輸系統技術演進&#xff1a;從碎片到統一寬帶接入技術 ADSLADSL的基本原理與非對稱特性DMT調制技術&#xff1a;多子信道并行傳輸ADSL接入網組成電話分離器的設計原理與優勢ADSL的升級&#xff1a;…

(論文速讀)SCSegamba:用于結構裂紋分割的輕量級結構感知視覺曼巴

論文題目&#xff1a;SCSegamba: Lightweight Structure-Aware Vision Mamba for Crack Segmentation in Structures&#xff08;用于結構裂紋分割的輕量級結構感知視覺曼巴&#xff09;會議&#xff1a;CVPR2025摘要&#xff1a;不同場景下的結構裂縫像素級分割仍然是一個相當…

《蘇超風云》亮相時尚大賞,成短劇行業發展新風向

當男頻短劇憑借《一品布衣》五天橫掃10億播放的數據宣告逆襲&#xff0c;短劇市場格局正經歷深刻洗牌。風口之下&#xff0c;頭條視聽、中皋文旅、國內時尚視覺與短視頻創作領域的頭部廠牌“大灣視頻”攜手下場&#xff0c;打造精品男頻短劇《蘇超風云》&#xff0c;劍指2025年…

HTML5新年元旦網站源碼

新年主題網站開發概述 本項目基于HTML5、CSS3與JavaScript技術棧&#xff0c;打造了一個功能豐富、交互體驗流暢的新年主題網站&#xff0c;涵蓋文化展示、互動娛樂與社交分享三大核心模塊&#xff0c;通過現代化前端技術實現沉浸式節日氛圍營造。 1.1、核心功能架構 網站采…

CentOS 7 下iscsi存儲服務配置驗證

一、環境說明 centos7服務器*2服務器ip&#xff1a;服務端10.10.10.186 客戶端10.10.10.184服務端存儲卷sda1提前關閉防火墻&#xff0c;或開放默認 iSCSI 使用 3260 端口 二、服務端&#xff08;Target&#xff09;配置 安裝 iSCSI target 服務 yum install -y targetcli syst…

立即數、棧、匯編與C函數的調用

一、立即數在 ARM 架構中&#xff0c;立即數是指在指令中直接編碼的常量值&#xff0c;而不是通過寄存器或內存引用的值立即數的特點編碼限制&#xff1a;ARM指令是固定長度的&#xff08;32位&#xff09;&#xff0c;因此立即數不能占用太多位數。典型的算術和邏輯指令通常只…

貪心算法與動態規劃:數學原理、實現與優化

貪心算法與動態規劃&#xff1a;數學原理、實現與優化 引言&#xff1a;算法選擇的本質 在計算機科學領域&#xff0c;算法選擇的本質是對問題特征的數學建模與求解策略的匹配。貪心算法與動態規劃作為兩種經典的優化算法&#xff0c;分別在不同問題域展現出獨特優勢。本文將從…

Leetcode 刷題記錄 21 —— 技巧

Leetcode 刷題記錄 21 —— 技巧 本系列為筆者的 Leetcode 刷題記錄&#xff0c;順序為 Hot 100 題官方順序&#xff0c;根據標簽命名&#xff0c;記錄筆者總結的做題思路&#xff0c;附部分代碼解釋和疑問解答&#xff0c;01~07為C語言&#xff0c;08及以后為Java語言&#xf…

Android Studio Meerkat | 2024.3.1 Gradle Tasks不展示

把這兩個開關打開&#xff0c;然后刷新gradle文件