剛?cè)腴T(mén)opengl的時(shí)候最煩的就是各種庫(kù)的配置,glut, freeglut, glfw, glew, glad, gl3w 等等,簡(jiǎn)直要暈了. 最后查閱網(wǎng)上的資料大概得出了這樣的結(jié)論:
opengl僅僅是一個(gè)標(biāo)準(zhǔn)/規(guī)范,但是具體利用opengl開(kāi)發(fā)對(duì)應(yīng)的應(yīng)用則需要依賴具體的開(kāi)發(fā)環(huán)境例如windows, linux等, 而最常見(jiàn)的就是窗口, IO控制等交互邏輯,因此glut, freeglut, glfw這類(lèi)的庫(kù)便產(chǎn)生了
-
glut (Opengl Utility Tool)
- 定義以及控制視窗
- 偵測(cè)并處理鍵盤(pán)和鼠標(biāo)事件
- 以一個(gè)函數(shù)呼叫繪制某些常用立體圖形,如長(zhǎng)方體,球,猶他茶壺
- 提供了簡(jiǎn)單選單列的實(shí)現(xiàn)
所有g(shù)lut的庫(kù)函數(shù)均已glut開(kāi)頭, 例如glutPostRedisplay(). 后來(lái)以及停止維護(hù)了
-
freeglut
glut的替代品,最新穩(wěn)定的版本是Freeglut3.0.0 (2015年3月7日)
-
glfw (Graphics Library Framework)
- 創(chuàng)建管理窗口和opengl的上下文
- 處理手柄,鍵盤(pán),鼠標(biāo)輸入
目前glfw還在維護(hù),可以說(shuō)glfw庫(kù)可以是代替glut和freeglut的庫(kù)的
opengl是一個(gè)標(biāo)準(zhǔn)/規(guī)范, 具體的實(shí)現(xiàn)是由驅(qū)動(dòng)開(kāi)發(fā)商針對(duì)特定的顯卡而實(shí)現(xiàn).支持opengl的驅(qū)動(dòng)版本眾多,大多數(shù)函數(shù)的地址(內(nèi)存地址)無(wú)法在編譯時(shí)候確定下來(lái),需要運(yùn)行的時(shí)候查詢.所以在運(yùn)行的時(shí)候獲取函數(shù)的內(nèi)存地址并把其保存在一個(gè)函數(shù)指針中供后續(xù)使用. glew, glad, gl3w基本都是實(shí)現(xiàn)類(lèi)似的功能
-
glad
//glad.h /////////////////////////////////////////////////////////////////// /*#55 定義一個(gè)函數(shù)指針,為GLADloadproc類(lèi)型,這種函數(shù)是以一個(gè)const char*為參數(shù)并返回void*的類(lèi)型,在glad.c中便用GLADloadproc load來(lái)聲明了一個(gè)GLADloadproc 類(lèi)型的函數(shù)load, 所以load函數(shù)的參數(shù)為(const char *name)返回值為void* */ typedef void* (* GLADloadproc)(const char *name); //////////////////////////////////////////////////////////////////////// //這里的APIENTRYP(API_entry_pointer即api條目指針) 表示 APIENTRY *, 而APIENTRY表示 __stdcall #define GLAPI extern #define APIENTRY __stdcall #define APIENTRYP APIENTRY * /////////////////////////////////////////////////////////////////////// /*#1806, 定義函數(shù)指針,為PFNGLGENBUFFERSPROC類(lèi)型,參數(shù)為(GLsizei n, GLuint *buffers), 返回值為void的類(lèi)型*/ typedef void (APIENTRYP PFNGLGENBUFFERSPROC)(GLsizei n, GLuint *buffers); /*用為PFNGLGENBUFFERSPROC類(lèi)型來(lái)定義一個(gè)函數(shù)指針名字為glad_glGenBuffers, 類(lèi)型是extern*/ GLAPI PFNGLGENBUFFERSPROC glad_glGenBuffers; #define glGenBuffers glad_glGenBuffers // glGenBuffers的宏定義,使用glGenBuffers函數(shù)時(shí)候其實(shí)就是調(diào)用的glad_glGenBuffers //////////////////////////////////////////////////////////////////////// //glad.c PFNGLGENBUFFERSPROC glad_glGenBuffers = NULL;//#452 聲明和定義glad_glGenBuffers這個(gè)函數(shù)指針為NULL glad_glGenBuffers = (PFNGLGENBUFFERSPROC)load("glGenBuffers");//#1086, 使用glad_glGenBuffers函數(shù)的時(shí)候就去load名字為glGenBuffers的函數(shù)具體怎么找函數(shù)的流程:
openg工程中main函數(shù)里面有g(shù)ladLoadGLLoader, gladLoadGLLoader里面把從opengl1.0到目前最高opengl4.6的函數(shù)都讀入
-
在glad.c中有一個(gè)函數(shù)
static int open_gl(void) { #ifndef IS_UWP libGL = LoadLibraryW(L"opengl32.dll"); if(libGL != NULL) { void (* tmp)(void); tmp = (void(*)(void)) GetProcAddress(libGL, "wglGetProcAddress"); gladGetProcAddressPtr = (PFNWGLGETPROCADDRESSPROC_PRIVATE) tmp; return gladGetProcAddressPtr != NULL; } #endif去系統(tǒng)中加載opengl32.dll這個(gè)庫(kù),然后GetProcAddress檢索指定的動(dòng)態(tài)鏈接庫(kù)(DLL)中的輸出庫(kù)函數(shù)地址.
而[根據(jù)某位知乎網(wǎng)友的解答][https://www.zhihu.com/question/30130562/answer/46983748] ,opengl32.dll僅僅為用戶提供了統(tǒng)一API的接口以及擴(kuò)展這些接口的可能, opengl32.dll被加載后嘗試調(diào)用更底層的ICD驅(qū)動(dòng)程序,從而完成具體的圖形操作. 而GLEW這些庫(kù),根據(jù)opengl的接口說(shuō)明,從動(dòng)態(tài)庫(kù)(opengl32.dll)中請(qǐng)求對(duì)應(yīng)的函數(shù)接口,如果能得到有效地址,那么這個(gè)函數(shù)是被當(dāng)前驅(qū)動(dòng)所支持的,就可以用,否則就無(wú)法支持.實(shí)際上,你也可以根據(jù)你當(dāng)前應(yīng)用中使用到的函數(shù)(通常一個(gè)小的演示demo,如顯示一個(gè)三角形,并沒(méi)有使用到很多的gl函數(shù))而獲取函數(shù)接口也是完全可行的. glew,glad,gl3w這些庫(kù)幫助用戶完成了所有接口的查詢和獲取.
glad, gl3w的作用類(lèi)似不做更多敘述.
但是gl3w是利用python開(kāi)發(fā)的, 因此需要安裝python庫(kù)進(jìn)行編譯生成相關(guān)的文件,具體的流程可以參考基于GLFW和GL3W庫(kù)的OPEN GL環(huán)境配置
結(jié)論: 可以用上面兩類(lèi)的庫(kù)進(jìn)行組合,例如我自己常用的是glfw + glad來(lái)進(jìn)行opengl的開(kāi)發(fā), 也有很多開(kāi)發(fā)者使用的是glfw + gl3w, 或者 glfw + glew