大家好,歡迎來到聽風(fēng)的OpenGL日常。本文代碼
寫在之前
GLEW(OpenGL Extension Wrangler Library);
在編寫OpenGL代碼時,如果希望靜態(tài)鏈接 必須包含該預(yù)處理宏
#define GLEW_STATIC
而如果用GCC編譯glew和glfw動態(tài)庫,則可以用命令行:
-lGLEW -lgfw3 -lGL -lX11 -lpthread -lXrandr -lXi
SOIL(Simple OpenGL Image Library),下載;
在Demo開始前,我們今天要引一下glad庫,這個庫的作用跟glew相同,glad與glew相比,簡單說glad是glew的升級版,它是2018.09月發(fā)布的,我們之后的例子要基于glad庫。
在demo中我們會將glad的源碼也包含在內(nèi),我們可以看清所有g(shù)lad集成的功能,其實就是對opengl api的封裝,但由于某些函數(shù)需要不停的調(diào)用,就產(chǎn)生了許多封裝好的工具庫,像之前的glut,到glew,再到我們將到使用的glad。這些工具包是為了跨平臺而出現(xiàn)的,它隱藏了不同平臺下調(diào)用opengl api的細節(jié)。
添加glad庫
將glad兩個文件添加到工程中:

當然對于glad引用到的其他庫,想辦法自己解決這個問題,否則遲早會遇到相同的問題;需要庫的到這里去找你會發(fā)現(xiàn)大寶藏的!?。?/a>
首先引入我們的庫文件,配置header search path:

代碼中添加:
#include <glad/glad.h>
#include <GLFW/glfw3.h>
這里我們忘記一項,就是下面的動態(tài)庫鏈接,千萬別忘了,否則會給你報一堆的某個函數(shù)沒這個符號云云;

Command + B驗證通過!
構(gòu)建我們的窗口
在這里與glfwWindow有關(guān)的內(nèi)容不作詳細解釋,直接進入opengl,至于glfwWindowHint參數(shù)中的枚舉值表示的意義,可見https://www.glfw.org/docs/latest/window.html#window_hints
在這里需要注意的一點是,如果是蘋果系統(tǒng),需要添加如下一行:
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfw初始化
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
創(chuàng)建窗口對象
GLFWwindow* window = glfwCreateWindow(width, height, "Triangle", NULL, NULL);
if(window == NULL) {
std::cout << "failed to create glfw window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
判斷是否創(chuàng)建成功,并將上下文最終保存起來;
這個時候我們已經(jīng)可以創(chuàng)建窗口了,不信你可以運行一下;
窗口變化回調(diào)
在進行OpenGL渲染之前我們必須定義視口,所以這里要區(qū)別于窗口,因為在OpenGL里是根本沒有窗口的概念的,在OpenGL里渲染必須要定義視口(如果不定義,你猜會發(fā)生什么);
//glViewport(0, 0, width, height);
glad_glViewport(0, 0, width, height);
glfw可以為窗口設(shè)置不同的回調(diào)函數(shù),具體我們遇到一個個說明,這里先說一個窗口變化回調(diào):
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
我們在main函數(shù)里監(jiān)控窗口變化,當glfw窗口發(fā)生變化回調(diào)到我們自己寫的framebuffer_size_callback,在這里我們讓視口跟隨窗口大小變化;
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glad_glViewport(0, 0, width, height);
}
GLAD pointer
接下來這段不是很懂,我之前一直想繞過glut/glew/glad之類的庫,但是貌似OpenGL內(nèi)部需要在外部保存指針才能對OpenGL作修改,所以這里這些庫是必要的,具體為什么在后面學(xué)習(xí)過程中再作討論吧,現(xiàn)在的重點是先打通渲染主道路;
// glad: load all OpenGL function pointers
// ---------------------------------------
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
Render loop
// render loop
// -----------
while (!glfwWindowShouldClose(window))
{
// input
// -----
process_input(window);
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// -------------------------------------------------------------------------------
glfwSwapBuffers(window);
glfwPollEvents();
}
// glfw: terminate, clearing all previously allocated GLFW resources.
// ------------------------------------------------------------------
glfwTerminate();
接下來到了渲染主循環(huán)中,逐個解釋:
glfwWindowShouldClose
每次循環(huán)glfw是否退出,如果返回0則直接關(guān)閉應(yīng)用程序:
glfwTerminate
下面這個函數(shù)會在每次循環(huán)中檢查觸發(fā)事件,根據(jù)平臺的某些硬件有關(guān)的,具體有哪些回調(diào)以后討論;
glfwPollEvents
這里要說下雙緩沖的概念,自己理解:

glfwSwapBuffers
我們的process_input是一個主動調(diào)用的函數(shù),在每次循環(huán)中我們會獲取鍵盤的按鍵,當按下ESC時直接關(guān)閉窗口;
void process_input(GLFWwindow *window)
{
if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
渲染一下
最后我們要做一個最原始的渲染動作,也就是邁進OpenGL的第一步,改變一下視口內(nèi)的顏色,在循環(huán)中不停地改變視口顏色:
static float count = 1;
if (count == 255) {
count = 1;
}
glClearColor(1.0f/255*count++, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
恭喜你,來到GLAD的世界?。?!