前言
- OpenGL是一個圖形庫規範,它定義了一組用於創建和渲染圖片的接口,嚴格規定了每個函數該如何執行,以及它們的輸出值。但內部具體每個函數是如何實現的,將由OpenGL庫的開發者自行決定,這通常都是顯卡廠商。每個OpenGL的驅動都是針對特定廠商的顯卡,開發者利用自己顯卡的特有功能,可以高效的實現某些OpenGL接口。
- 總結一句話,OpenGL是規範,實現由各個顯卡廠商提供,每個顯卡廠商實現的驅動各有不同。因爲這種情況,OpenGL的很多函數在編譯時地址不能確定,上層應用需要用動態加載的方式使用OpenGL提供的圖形庫。通常的做法是,開發應用程序時如果要使用OpenGL庫提供的函數,首先動態加載OpenGL庫,然後檢查庫中是否包含自己想要調用的函數的符號,如果包含,就調用該函數,過程類似下面這樣:
- 打開一個OpenGL動態庫,返回一個庫的句柄
handle = dlopen(file, flags)
- 檢查動態庫中是否有自己想調用的函數
regsym = dlsym(handle, funcname)
- 返回值regsym不小於0表示動態庫中存在這個函數,調用它
funcname( )
- 使用完之後關閉這個動態庫的句柄
dlclose(handle)
- 上面這個流程是C語言的接口動態解決一個so庫並調用其包含函數的過程,OpenGL提供的so庫使用方式類似。由於OpenGL各個版本提供的API有所差異,因此應用程序需要了解自己使用的OpenGL庫包含哪些接口,對於每個接口,保險的方法是用以上的方式來調用,但這樣太複雜了,並且應用程序也可能不知道自己使用的OpenGL庫包含的接口。有一個開源的庫專門解決這個問題,它針對每一個OpenGL版本的接口實現了上述的判斷,這就是GLAD庫。我們的環境搭建中需要依賴這個庫。
- OpenGL是一個實現3D圖像渲染的圖形庫,它自身是一個巨大的狀態機,通過一系列的輸入變量描述OpenGL此刻該如何運行,OpenGL的狀態通常被稱爲上下文(context),context上下文的創建涉及到顯卡緩衝區等與具體系統相關的細節,因爲每個平臺上的實現不一樣。爲了讓OpenGL具有可移植性,它特意將這些操作抽象出去。因此應用程序需要自己處理context的創建。同樣的,如果我們想要展示自己渲染的圖片,需要一個用於顯示的窗口,這個窗口也是平臺相關的。因此也需要應用程序自己處理。同樣地,當前也有一些庫是特別針對OpenGL這種需求的,它們爲OpenGL的渲染提供一個上下文和一個窗口。這些流行的庫有GLUT,SDL,SFML和GLFW等。這裏我們將使用GLFW,同時也會涉及到GLUT庫。
- 綜上所述,要基於OpenGL庫開發應用程序,不僅要安裝OpenGL庫,還依賴GLAD庫和GLFW庫。整個OpenGL開發環境的搭建就是介紹這個安裝過程。
安裝OpenGL
- 在centos上,我們配置了yum源之後,直接安裝libglvnd-glx包,就能將OpenGL和它依賴的庫全部安裝上
yum install -y libglvnd-glx
- 安裝OpenGL庫之後,我們還不知道它的API版本,freeglut是一個用於創建OpenGL窗口和上下文的庫,這裏我們使用這個庫來查詢OpenGL API版本。首先安裝這個庫的開發包
yum install -y freeglut-devel
,然後編譯一個C程序來確定版本。如下:
#include <stdio.h>
#include <GL/glut.h>
int main(int argc, char** argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH); /* 1 */
glutInitWindowSize(300,300); /* 2 */
glutInitWindowPosition(100,100); /* 3 */
glutCreateWindow("OpenGL Version");
const GLubyte* OpenGLVersion =glGetString(GL_VERSION); /* 4 */
printf("OpenGL實現的版本號:%s\n",OpenGLVersion);
return 0;
}
1. 顯示模式初始化
2. 定義窗口大小
3. 創建窗口
4. 返回當前OpenGL實現的版本號
- 編譯後運行結果如下:
- 從這裏可以看到只有加載OpenGL才能看到它的實現版本號,這裏是3.0
安裝GLAD
- GLAD是一個開源庫,但和普通庫不同,它是一個在線服務,用戶進入這個網頁輸入自己的OpenGL庫版本產生一個glad.c的文件和一個glad.h頭文件,我們將glad.c文件編譯成目標文件glad.o後與應用程序一起編譯,同時需要將glad提供的頭文件glad.h包含在我們自己的應用中,通過這種方式,應用程序就可以使用glad庫中定義的接口了。
- 從在線服務中下載下來的glad.zip內容如下:
- 我們將glad.c編譯成目標文件
gcc -c glad.c -o glad.o
- 將glad.h拷貝到系統的頭文件目錄下
cp -r glad/include/glad /usr/include/
安裝GLFW
- GLFW是個開源庫,我們從源碼編譯安裝,首先下載源碼
git clone [email protected]:glfw/glfw.git
- GLFW使用cmake編譯,linux平臺下源碼目錄下載後沒有Makefile文件,需要首先生成,使用cmake命令產生Makefile,編譯然後安裝,如下:
cd glfw
cmake .
make
make install
- 安裝完GLFW之後,應用程序所需要的所有連接庫都準備好了,可以開始編譯應用程序。
Hello OpenGL
- 我們的程序就是利用GLFW庫接口創建一個窗口,其源碼在這裏,然後編譯運行這個程序。
- 我們的源碼文件名爲hello.cpp,編譯這個文件:
g++ hello.cpp glad.o -o hello -lglut -lGL -lGLU -lglfw3 -lGL -lX11 -lpthread -lXrandr -lXi -ldl
- 運行hello程序,界面上就會彈出一個窗口,窗口大小有hello中的源碼設置,我將它調成了200 * 200大小,效果如下: