最近,馬三買了兩本有關於「計算機圖形學」的書籍,準備在工做之餘鼓搗鼓搗圖形學和OpenGL編程,提高本身的價值(奔着學完能漲一波工資去的)。俗話說得好,「工欲善其事,必先利其器」。想學習圖形學和OpenGL編程必須先把開發環境搭建好,而馬三隻是在上學的時候稍稍作了一些基於Android平臺的OpenGL開發學習,並無搭建過OpenGL開發環境。所以在搭建過程當中頗廢了一番周折,也查閱了很多資料纔算搭建成功,特此記錄一下搭建過程,以備不時之需。html
這個沒必要多說了,基本作過開發的都會安裝這個「宇宙最強IDE」了。直接去官網下載安裝助手,而後安裝便可。ios
正常來講開發進行OpenGL開發的話,glut庫是必不可少的,可是馬三在網上一搜啊,發現glut這個庫過期了,如今比較新版的GLFW徹底能夠替代它。關於這些名詞相關的具體介紹,咱們會在稍後仔細介紹一下,咱們仍是先去 GLFW官網 把庫下載下來。編程
圖1:GLFW官網下載示意圖微信
接着咱們還須要下載GLEW庫,衆所周知,OpenGL只是一個標準,不一樣的顯卡公司在不一樣的平臺下對其有不一樣的實現,同時也是發佈一些只支持自家顯卡的拓展函數。經過引入glew庫,咱們徹底能夠不用理睬這些細節,安心寫代碼就行了。框架
一樣仍是去 GLEW的官網 下載咱們所須要的內容:ide
圖2:GLEW官網下載示意圖函數
對於以上的這兩個庫和源代碼,馬三已經下載了寫博客時的最新版本,並打成了壓縮包,方便各位下載。下載請移步。工具
解壓咱們下載的兩個庫,並在VS2017裏面新建一個C++空項目。若是建立的是控制檯或者其餘項目的話,vs工具會自動幫你添加一個stdafx.h的預編譯頭,你必須在源文件的開頭寫上#include 「stdafx.h」相關語句,並且以後引入glew,glfw包會有莫名其妙的錯誤。因此建立一個空項目。以下如所示:學習
圖3:解壓後的庫測試
圖4:建立新的空項目
而後,點擊「解決方案資源管理器」,右鍵點擊源文件,添加新項,建立.cpp源文件,能夠隨便命個名,好比main.cpp:
圖5:新建源文件
接着,右鍵點擊項目,在彈出的選項中,單擊 「屬性」,點擊「VC++目錄」,而後選擇「包含目錄」選項,單擊下拉菜單中的「編輯」:
圖五、6項目屬性編輯
接着咱們在新打開的窗口中添加頭文件。分別添加下載的glew和glfw文件夾下的include文件夾(include文件夾下是咱們須要的頭文件),並點擊「肯定」:
圖7:include頭文件
以後,再繼續添加庫文件到項目中,頭文件一般是函數的聲明,而函數的實現通常都放在了庫中,兩者相輔相成,只有都正確的引入了,才能正常工做。其對應的路徑就是glew和glfw文件夾下的lib文件夾:
有兩點須要咱們特別注意一下:
圖8:lib庫文件
只包含了庫文件還不行,咱們須要手動指定一下。配置連接器:
圖9:連接器配置
在裏面手動加入以下選項,行與行之間請按回車,opengl32.lib是系統自帶的。glfw3.lib,glew32s.lib 是咱們下載的庫中的,其實就是以前包含的lib文件夾下的文件名(去掉glew32.lib):
opengl32.lib
glfw3.lib
glew32s.lib
圖10:編輯連接器配置
通過上面一系列的繁瑣的操做,咱們的OpenGL開發環境基本也算搭建完成了,下面讓咱們在main.cpp中添加一些代碼測試一下,環境是否搭建成功,咱們的程序是否可以跑起來。在main.cpp中加入以下測試代碼:
1 #include<iostream> 2 #define GLEW_STATIC 3 #include <GL/glew.h> 4 #include <GLFW\glfw3.h> 5 6 using namespace std; 7 8 int main(int argc, char** argv[]) 9 { 10 /*glewExperimental = GL_TRUE; 11 if (glewInit()!=GLEW_OK) 12 { 13 cout << "failed to initalize GLEW" << endl; 14 return -1; 15 }*/ 16 17 glfwInit();//初始化 18 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);//配置GLFW 19 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);//配置GLFW 20 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);// 21 glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); 22 23 GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", nullptr, nullptr); 24 if (window == nullptr) 25 { 26 cout << "Failed to create GLFW window" << endl; 27 glfwTerminate(); 28 return -1; 29 } 30 glfwMakeContextCurrent(window); 31 while (!glfwWindowShouldClose(window)) 32 { 33 glfwPollEvents(); 34 glfwSwapBuffers(window); 35 } 36 glfwTerminate(); 37 return 0; 38 39 40 }
而後,點擊調試,若是成功了的話能夠看到相似於下面的這種窗口,實際上是初始化了一個空的OpenGL窗口:
圖11:初始化OpenGL窗口
可是咱們會發如今vs的錯誤列表窗口中出現了一條警告:「警告 LNK4098 默認庫「MSVCRT」與其餘庫的使用衝突;請使用 /NODEFAULTLIB:library BuildEnv F:\xxxx」
這個警告也是比較好解決的,打開咱們以前配置連接器的那個頁面,而後選擇忽略特定庫選項,並編輯。在其中加入 "MSVCRT.lib",而後而後點擊肯定,以後就會發現警告消失不見了。若是之後還有其餘的相似的庫衝突,咱們可使用一樣的方法解決。
圖12:解決庫衝突
儘管咱們已經成功的搭建了OpenGL開發環境,可是相信此時必定有很多小夥伴和馬三同樣對OpenGL開發中的一些庫和名詞處於矇蔽狀態。馬三也是蒐集了這些名詞的資料和你們一塊兒分享一下。
OpenGL函數庫相關的API有核心庫(gl),實用庫(glu),輔助庫(aux)、實用工具庫(glut),窗口庫(glx、agl、wgl)和擴展函數庫等。gl是核心,glu是對gl的部分封裝。glx、agl、wgl 是針對不一樣窗口系統的函數。glut是爲跨平臺的OpenGL程序的工具包,比aux功能強大(aux很大程度上已經被glut庫取代。)。擴展函數庫是硬件廠商爲實現硬件更新利用OpenGL的擴展機制開發的函數。
這部分函數以glut開頭,主要包括窗口操做函數,窗口初始化、窗口大小、窗口位置等函數;回調函數:響應刷新消息、鍵盤消息、鼠標消息、定時器函數等;建立複雜的三維物體;菜單函數;程序運行函數。gult對應的開源實現是freegult,freegult官網請移步。
GLUT或者FREEGLUT主要是1.0的基本函數功能;GLEW是使用OPENGL2.0以後的一個工具函數。不一樣的顯卡公司,也會發布一些只有自家顯卡才支持的擴展函數,你要想用這數函數,不得不去尋找最新的glext.h,有了GLEW擴展庫,你就不再用爲找不到函數的接口而煩惱,由於GLEW能自動識別你的平臺所支持的所有OpenGL高級擴展函數。也就是說,只要包含一個glew.h頭文件,你就能使用gl,glu,glext,wgl,glx的所有函數。glew庫提供高版本 gl 函數的支持。若是不嫌麻煩的話,也能夠手寫函數指針,來判斷各個 opengl 高版本函數是否支持,可是 glew 庫 作了大大的簡化,使得 opengl 各個版本的函數像原生函數同樣,能夠隨意調用。
GLFW無愧於其號稱的lightweight的OpenGL框架,的確是除了跨平臺必要作的事情都沒有作,因此一個頭文件,不多量的API,就完成了任務。GLFW的開發目的是用於替代glut的,從代碼和功能上來看,我想它已經徹底的完成了任務。一個輕量級的,開源的,跨平臺的library。支持OpenGL及OpenGL ES,用來管理窗口,讀取輸入,處理事件等。由於OpenGL沒有窗口管理的功能,因此不少熱心的人寫了工具來支持這些功能,好比早期的glut,如今的freeglut等。
那麼GLFW有何優點呢?glut太老了,最後一個版本仍是90年代的。freeglut徹底兼容glut,算是glut的代替品,功能齊全,可是bug太多。所以,GLFW應運而生。
綜上所述:
1.glfw是glut的升級和改進
2.glew包含了OpenGL所需的核心
目前網上的一些教程還有使用glad庫的,glad與glew有什麼區別呢?簡單說glad是glew的升級版。用哪一個都行。glew比較老,glad比較新。下面簡單介紹一些glad如何使用:
glad有一個在線服務,直接下下來就能夠用了(編譯好的),將語言(Language)設置爲C/C++,在API選項中,選擇3.3以上的OpenGL版本(3.3是可編程管線版本,但更新的版本也能正常工做)。以後將模式(Profile)設置爲Core,而且保證生成加載器(Generate a loader)的選項是選中的。如今能夠先(暫時)忽略拓展(Extensions)中的內容。都選擇完以後,點擊生成(Generate)按鈕來生成庫文件。
下載到本地是個壓縮文件,解壓完成後會有這樣的文件夾結構:
圖13:glad文件目錄
包含兩個頭文件目錄(內有頭文件glad.h和khrplatform.h),和一個src文件夾下的glad.c文件。只須要將原來的第五步的 VC++目錄 -> 包含目錄 中的glew的include文件夾改爲glad的include文件夾便可。後面的步驟glad都不須要。
而後將glad.c文件複製到源文件夾下:
圖14:glad複製到源文件夾
注意glad.c文件這時候或者編譯的時候會出錯,首先看看glad.c的include的路徑是否是對的,有時候包含目錄文件夾路徑不同,你要改爲你本身配置的glad路徑(就是以前VC++目錄配置的路徑)。
而後須要將咱們的測試代碼換成以下這段:
1 #include <glad/glad.h> 2 #include <GLFW/glfw3.h> 3 4 #include <iostream> 5 6 const unsigned int SCR_WIDTH = 800; 7 const unsigned int SCR_HEIGHT = 600; 8 9 int main() 10 { 11 glfwInit(); 12 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 13 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 14 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 15 16 GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL); 17 if (window == NULL) 18 { 19 std::cout << "Failed to create GLFW window" << std::endl; 20 glfwTerminate(); 21 return -1; 22 } 23 glfwMakeContextCurrent(window); 24 25 if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) 26 { 27 std::cout << "Failed to initialize GLAD" << std::endl; 28 return -1; 29 } 30 31 while (!glfwWindowShouldClose(window)) 32 { 33 34 glClearColor(0.2f, 0.3f, 0.3f, 1.0f); 35 glClear(GL_COLOR_BUFFER_BIT); 36 37 glfwSwapBuffers(window); 38 glfwPollEvents(); 39 } 40 41 glfwTerminate(); 42 return 0;
在本篇博客中,馬三和你們一塊兒從頭開始搭建了一個OpenGL開發環境,而且瞭解了一些OpenGL的概念與名詞。接下來馬三將會一邊學習計算機圖形學和OpenGL,一邊隨時隨地的把想法記錄下來與你們分享~
參考資料:
若是以爲本篇博客對您有幫助,能夠掃碼小小地鼓勵下馬三,馬三會寫出更多的好文章,支持微信和支付寶喲!
做者:馬三小夥兒
出處:http://www.javashuo.com/article/p-szumdrsi-v.html 請尊重別人的勞動成果,讓分享成爲一種美德,歡迎轉載。另外,文章在表述和代碼方面若有不妥之處,歡迎批評指正。留下你的腳印,歡迎評論!