【寫在前面】
首先,要說明的是:這個系列將使用 glfw + glad 作爲基本的窗口系統和 opengl 擴展,編譯器則爲 VS2013。
其次,本篇從獲取、編譯、鏈接 glfw + glad 庫講起,然後建立 glfw 環境,並保證它能夠正確地創建 OpenGL 上下文並顯示窗口,所以已經搭建好環境的可以直接跳過本篇。
【正文開始】
1. 配置GLFW,從官網上下載:https://www.glfw.org/download.html,我這裏建議直接下載二進制版本:
解壓後得到:
接下來打開你的 VS目錄下的VC文件夾,將 glfw-3.2.1.bin.WIN32\include\ 下的 GLFW 文件夾拷貝至 VC\include\ 下,然後根據你的 VS 版本選擇相應的 lib-vc2013 (我的是2013),將其中的 glfw3.lib 和 glfw3dll.lib 拷貝至 VC\lib\ 下,而 glfw3.dll 放到C:\Windows\System32\ 下,至此,glfw 已經配置完成。
2. 配置 GLAD,glad 是運行時獲取 OpenGL 函數地址的一個擴展庫(類似於 glew ),首先還是從官網下載:https://glad.dav1d.de/,然後選擇 gl 版本爲 3.3 (後面可能爲4.x),模式選擇爲核心模式:
點擊最下方的生成按鈕,得到:
點擊 glad.zip,下載壓縮文件,然後解壓得到:
和 glfw 一樣,將 include\ 下的 glad 文件夾和 KHR文件夾 拷貝至 VC\include\ 下,將 src\glad.c 拷貝至你的工程目錄下,至此,glad 已經配置完成。
3. 新建一個項目,並鏈接 opengl 和 glfw 庫,在屬性->配置屬性->鏈接器->輸入->附加依賴項中加入 opengl32.lib 和glfw3.lib:
4. 開始創建第一個OpenGL窗口:
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
這裏直接上代碼了,首先 #include <glad/glad.h> 和 #include <GLFW/glfw3.h>,注意:glad.h 必須在 glfw.h 之前包含(否則會重複包含),#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"") 這一行不是必要的,我只是爲了關閉 Consolas 窗口。
接下來是 main 函數:
int main(int argc, char **argv)
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(600, 500, "OpenGL-Start", nullptr, nullptr);
if (window == nullptr)
{
std::cerr << "Failed to Create GLFW Window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader(GLADloadproc(glfwGetProcAddress)))
{
std::cerr << "Failed to Initliaze GLAD";
glfwTerminate();
return -1;
}
glfwSetWindowSizeCallback(window, [](GLFWwindow *window, int width, int height)
{
glViewport(0, 0, width, height);
});
glfwSetKeyCallback(window, [](GLFWwindow *window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwTerminate();
});
while (!glfwWindowShouldClose(window))
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
首先,我們在 main 函數中調用 glfwInit() 函數來初始化 glfw ,然後通過 glfwWindowHint() 函數來設置我們需要的OpenGL 版本爲 3.3,以及使用核心模式( Core )。
接下來我們使用 glfwCreateWindow() 創建一個窗口指針,(噢忘了說,glfw 所有的函數都有註釋,在其聲明的上方可以看到),創建完窗口我們就可以使用 glfwMakeContextCurrent() 通知 glfw 將我們窗口的上下文設置爲當前線程的主上下文了。
然後我們開始載入 OpenGL 的函數地址,通過 gladLoadGLLoader() 函數,它需要傳入一個函數指針,glfw 提供的函數爲glfwGetProcAddress(),這裏直接把它傳入。
再就是設置一些回調函數,glfwSetWindowSizeCallback() 和 glfwSetKeyCallback() ,它們在窗口大小改變和有按鍵事件時調用相應的函數,我這裏在窗口大小改變時重置 OpenGL 視口,在按下 Esc 鍵時結束程序。
- glfwWindowShouldClose() 函數在我們每次循環的開始前檢查一次GLFW是否被要求退出,如果是的話該函數返回
true
然後渲染循環便結束了,之後爲我們就可以關閉應用程序了。- glfwPollEvents() 函數檢查有沒有觸發什麼事件(比如鍵盤輸入、鼠標移動等)、更新窗口狀態,並調用對應的回調函數(可以通過回調方法手動設置)。
- glfwSwapBuffers() 函數會交換顏色緩衝(它是一個儲存着GLFW窗口每一個像素顏色值的大緩衝),它在這一迭代中被用來繪製,並且將會作爲輸出顯示在屏幕上。
最後,銷燬窗口並結束程序,看一下效果圖(只是一個灰綠色的空窗口而已):
【結語】
其實 glfw + glad 還是稍微有點繁瑣的,所以使用起來難免有很多不方便的地方,後面我將會進行一些簡單的封裝,這樣就能減少很多不必要的工作,然後接下來還是要把注意力轉移到 render 中,畢竟那纔是真正的核心。
整個系列教程的源碼在我的 Github 上可以找到,地址是:https://github.com/mengps/OpenGL-Totural,會不定時進行更新~~