文章目錄
- 【OpenGL學習】(一)創建窗口
【OpenGL學習】(一)創建窗口
GLFW
OpenGL 本身只是一套圖形渲染 API,不提供窗口創建、上下文管理或輸入處理的功能。
GLFW 是一個支持創建窗口、處理鍵盤鼠標輸入和管理 OpenGL 上下文的跨平臺庫。因此,可以將OpenGL 和GLFW結合使用。
注:除了 GLFW,OpenGL 也可以與其他 GUI 框架如 Qt、MFC、SDL 等結合使用,實現更復雜或平臺特定的圖形界面程序。
GLAD
OpenGL 是一個跨平臺的圖形 API,其函數并非直接由操作系統或編譯器提供,而是通過顯卡驅動動態加載。這些函數的地址需要你在程序運行時手動獲取,例如:
// 定義一個函數指針類型 GLGENBUFFERSPROC,用于指向 glGenBuffers 函數。
typedef void (*GLGENBUFFERSPROC)(GLsizei, GLuint*);
// 使用 wglGetProcAddress 函數動態加載 OpenGL 的 glGenBuffers 函數。
GLGENBUFFERSPROC glGenBuffers = (GLGENBUFFERSPROC)wglGetProcAddress("glGenBuffers");
每一個函數你都得這么寫,非常繁瑣。
GLAD是一個OpenGL函數加載庫,可以自動加載與指定OpenGL版本相關的所有函數指針,避免了繁瑣的手動獲取,讓我們可以像普通函數一樣直接調用它們。
示例:創建窗口
#include <glad/glad.h> // 用于加載 OpenGL 函數指針
#include <GLFW/glfw3.h> // 用于創建窗口和處理用戶輸入
#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;int main()
{// 初始化 GLFW 庫,并配置 OpenGL 版本glfwInit(); // 初始化 GLFWglfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // 要 OpenGL 3.xglfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // 精確到 3.3 版本glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 使用現代核心功能,不兼容舊版#ifdef __APPLE__// 兼容 Mac OS 系統glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#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); // 注冊窗口尺寸改變的回調函數,告訴GLFW當窗口調整大小的時調用這個函數// 初始化 GLAD,加載所有 OpenGL 函數指針if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){std::cout << "Failed to initialize GLAD" << std::endl;return -1;}// 渲染循環while (!glfwWindowShouldClose(window)) // 如果窗口沒有被關閉{// 處理輸入processInput(window);// 設置清屏顏色(RGBA格式,紅、綠、藍、透明度),用于清除顏色緩沖區glClearColor(0.2f, 0.3f, 0.3f, 1.0f);// 清除顏色緩沖區,使用上面設置的清屏顏色glClear(GL_COLOR_BUFFER_BIT);glfwSwapBuffers(window); // 交換顏色緩沖區:把畫好的圖像展示到屏幕上glfwPollEvents(); // 從操作系統獲取事件(鍵盤、鼠標、窗口變化等),并更新 GLFW 內部狀態,或者觸發用戶注冊的回調函數。}// 釋放資源并退出glfwTerminate();return 0;
}// 處理輸入
void processInput(GLFWwindow* window)
{// 當按下 ESC 鍵時關閉窗口if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)glfwSetWindowShouldClose(window, true); // 設置窗口應關閉標志
}// 窗口尺寸改變時調用的回調函數
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{// 設置視口大小,使其匹配新窗口尺寸// 注意:在高 DPI 顯示屏上,實際像素尺寸可能比指定尺寸更大glViewport(0, 0, width, height);
}
顏色緩沖區
顏色緩沖區是幀緩沖區(Frame Buffer) 的一部分,它保存了當前窗口中每一個像素的顏色值。
當你在屏幕上繪制圖形時,你的所有繪制操作(畫三角形、貼紋理、光照等)其實都是先寫入顏色緩沖區,最后才一次性展示在屏幕上。
OpenGL 中的默認幀緩沖區包括:
緩沖區 | 作用 |
---|---|
顏色緩沖區(Color Buffer) | 存儲每個像素的顏色值(RGB 或 RGBA)。 |
深度緩沖區(Depth Buffer) | 存儲每個像素的深度值(Z 值),用于深度測試。 |
模板緩沖區(Stencil Buffer) | 用于進行復雜的遮罩、裁剪操作。 |
OpenGL 默認使用雙緩沖機制(Double Buffering),也就是有兩個顏色緩沖區:
緩沖區 | 用途 |
---|---|
前緩沖區(Front Buffer) | 當前正在顯示在屏幕上的圖像 |
后緩沖區(Back Buffer) | 當前正在繪制的圖像內容(你所有的渲染操作都寫在這里) |
渲染流程大致如下:
- 你通過 OpenGL API 畫東西 → 寫入后緩沖區。
- 繪制完成后,調用
glfwSwapBuffers(window);
→ 前后緩沖區交換。 - 后緩沖區的圖像變成可見,前緩沖區變成新的繪制目標。
這樣就可以避免畫面撕裂或閃爍,保證畫面平滑流暢。
processInput()和glfwPollEvents()的關系
glfwPollEvents() | processInput() | |
---|---|---|
誰寫的 | GLFW 提供的函數 | 你自己寫的函數 |
屬于哪一層 | 系統層(事件驅動層) | 應用層(行為控制層) |
作用 | 從操作系統獲取輸入事件(鍵盤、鼠標、窗口)并更新內部狀態 | 基于 GLFW 狀態判斷執行邏輯,比如關閉窗口、移動物體 |
必須調用嗎 | 是的,否則無法接收到新輸入 | 可選,但你不寫就不會響應用戶行為 |
通常調用順序 | 一般在主循環每幀末尾調用 | 一般在主循環每幀開始調用 |
是否處理輸入行為 | 不處理輸入邏輯,只更新狀態 | 你寫的行為處理代碼(比如 ESC 退出)就在這里 |
參考:
https://learnopengl-cn.github.io/01%20Getting%20started/03%20Hello%20Window/