自從工做後,老是或多或少的會接觸到客戶端3d圖形渲染,正好本身對於3d圖形的渲染也很感興趣,因此最近打算從學習OpenGL的圖形API出發,進而瞭解3d圖形的渲染技術。到網上查了一些資料,OpenGL的入門學習一般是用《OpenGL開發指南》和《OpenGL超級寶典》這兩本書。博主最近在看《OpenGL超級寶典》,在這裏分享一些本身的理解,但願和園子裏的人一塊兒學習和探討。html
一、 建立工程git
《OpenGL超級寶典》的做者爲了不每一個例子都重複寫一些窗口建立,捕獲消息,專門寫了一個應用程序的框架。程序框架的代碼在github上,先把裏面的sb7code代碼下載下來,而後解壓縮,能夠看到有下面這些文件:github
從上面的CMakeLists.txt能夠發現,這個工程是用cmake來生成的。因此須要下載cmake,至於怎樣使用cmake,能夠參考使用cmake自動構建工程。除了cmake外,工程中使用了glfw庫來建立窗口和捕獲鍵盤和鼠標的消息。爲了使用glfw,須要先把它編譯成庫文件,glfw的源文件在extern目錄中,它的工程也是經過cmake來創建的,因此若是會使用cmake的話就能夠先經過cmake創建一個vs工程,而後編譯工程就能夠生成對應的庫文件了。把在debug模式下生成的glfw3.lib(重命名爲glfw3_d.lib)和release模式下生成的庫文件glfw3.lib拷貝到lib目錄中。最後運行cmake生成vs工程,生成的工程能夠在build中找到,打開build下面的superbible7.sln工程文件,就能夠發現不少書本上介紹的例子項目了。其中sb7就是整個工程的框架,在sb7裏面實現了類application,新的程序只須要繼承這個類,而後根據須要重寫裏面的一些方法,最後用DECLARE_MAIN宏建立這個程序就能夠了。建立程序的大體代碼以下:app
#include <sb7.h> class simpleclear_app : public sb7::application { //重載一些方法 virtual void render(double currentTime) { static const GLfloat white[] = { 1.0f, 0.0f, 0.0f, 1.0f }; glClearBufferfv(GL_COLOR, 0, white); } }; DECLARE_MAIN(test_app)
而後編譯就能夠直接運行了,這樣咱們就能夠徹底不用關心窗口的建立,只須要關心怎樣用opengl進行渲染就好了。框架
二、application函數
如今來看下類application和宏DECLARE_MAIN怎樣爲咱們建立應用程序的。application類中有個run方法,主要的代碼以下:post
1 virtual void run(sb7::application* the_app) 2 { 3 bool running = true; 4 app = the_app; 5 6 glfwInit() 7 init(); 8 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, info.majorVersion); 9 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, info.minorVersion); 10 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 11 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); 12 glfwWindowHint(GLFW_SAMPLES, info.samples); 13 glfwWindowHint(GLFW_STEREO, info.flags.stereo ? GL_TRUE : GL_FALSE); 14 15 window = glfwCreateWindow(info.windowWidth, info.windowHeight, info.title, NULL, NULL); 16 glfwMakeContextCurrent(window); 17 glfwSetWindowSizeCallback(window, glfw_onResize); 18 glfwSetKeyCallback(window, glfw_onKey); 19 glfwSetMouseButtonCallback(window, glfw_onMouseButton); 20 glfwSetCursorPosCallback(window, glfw_onMouseMove); 21 glfwSetScrollCallback(window, glfw_onMouseWheel); 22 gl3wInit(); 23 startup(); 24 25 do 26 { 27 render(glfwGetTime()); 28 glfwSwapBuffers(window); 29 glfwPollEvents(); 30 running &= (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_RELEASE); 31 running &= (glfwWindowShouldClose(window) != GL_TRUE); 32 } while (running); 33 34 shutdown(); 35 glfwDestroyWindow(window); 36 glfwTerminate(); 37 }
run方法先調用glfwInit來初始化glfw,而後調用glfwCreateWindow來建立窗口,隨後調用glfwSetXXXCallback來設置消息處理的回調函數,最後經過while循環來執行render函數,獲取消息等。run中還有init和setup函數,這些函數只有是用來給子類設置一些本身的參數。學習
DECLARE_MAIN宏的定義以下:ui
1 #define DECLARE_MAIN(a) \ 2 sb7::application *app = 0; \ 3 int CALLBACK WinMain(HINSTANCE hInstance, \ 4 HINSTANCE hPrevInstance, \ 5 LPSTR lpCmdLine, \ 6 int nCmdShow) \ 7 { \ 8 a *app = new a; \ 9 app->run(app); \ 10 delete app; \ 11 return 0; \ 12 }
這個宏定義了WinMain函數,它是win32窗口程序的入口,至關於控制檯程序的main函數。而後在這個函數裏面new了咱們本身定義的application子類對象,最後調用對象的run方法來建立窗口和調用render函數。url
有了這個框架,基本上咱們只須要繼承下application類,重寫下render函數就能夠跑咱們的opengl程序了,很是的方便。