OpenGL
Before you can actually use OpenGL in a program, you must first initialize it. Because OpenGL is platform-independent, there is not a standard way to initialize OpenGL; each platform handles it differently. Non-C/C++ language bindings can also handle these differently.There are two phases of OpenGL initialization.
- The first phase is the creation of an OpenGL context
- the second phase is to load all of the necessary functions to use OpenGL. Some non-C/C++ language bindings merge these into one.
簡而言之,openGL是一個獨立於平台的繪制圖形的標准。在你真正能夠在程序中使用OpenGL之前,你需要對他進行初始化,但是由於OpenGL是跨平台的,所以也沒有一個標准的方式進行初始化。但是OpenGL初始化必經兩個階段:
- 第一個階段,你需要創建一個OpenGL上下文環境,這個上下文環境存儲了所有與OpenGL相關的狀態(OpenGL是一個狀態機),上下文位於操作系統中某個進程中,一個進程可以創建多個上下文,每一個上下文都可以描繪一個不同的可視界面,就像應用程序中的窗口,簡單來理解就是為了創建一個窗口
- 第二個階段,你需要定位所有需要在OpenGL中使用的函數
freeglut/glut 和glew就是用來解決這兩個問題的。
OpenGL函數庫相關的API有核心庫(gl)、實用庫(glu)、輔助庫(aux)、實用工具庫(glut)、窗口庫(glx、agl、wgl)和擴展函數庫等。gl是核心,glu是對gl的部分封裝。glx、agl、wgl 是針對不同窗口系統的函數。glut是為跨平台的OpenGL程序的工具包,比aux功能強大。擴展函數庫是硬件廠商為實現硬件更新利用OpenGL的擴展機制開發的函數。下面逐一對這些庫進行詳細介紹。
Tips
glut是基本的窗口界面,是獨立於gl和glu的,如果不喜歡用glut可以用MFC和Win32窗口等代替,但是glut是跨平台的,這就保證了我們編出的程序是跨平台的,如果用MFC或者Win32只能在windows操作系統上使用。選擇OpenGL的一個很大原因就是因為它的跨平台性,所以我們可以盡量的使用glut庫.
OpenGL核心庫
核心庫包含有115個函數,函數名的前綴為gl
這部分函數用於常規的、核心的圖形處理。此函數由gl.dll來負責解釋執行。由於許多函數可以接收不同參數,根據參數的類型,可以派生出來的函數原形多達300多個。核心庫中的函數主要可以分為以下幾類函數。
- 繪制基本幾何圖元的函數。如繪制圖元的函數glBegain()、glEnd()、glNormal*()、glVertex*()
- 矩陣操作、幾何變換和投影變換的函數。如矩陣入棧函數glPushMatrix()、矩陣出棧 函數glPopMatrix()、裝載矩陣函數glLoadMatrix()、矩陣相乘函數glMultMatrix(),當前矩陣函數glMatrixMode()和矩陣標准化函數glLoadIdentity(),幾何變換函數glTranslate*()、glRotate*()和glScale*(),投影變換函數glOrtho()、glFrustum()和視口變換函數glViewport()等
- 顏色、光照和材質的函數。如設置顏色模式函數glColor*()、glIndex*(),設置光照效果的函數glLight*() 、glLightModel*()和設置材質效果函數glMaterial()等
- 顯示列表函數、主要有創建、結束、生成、刪除和調用顯示列表的函數glNewList()、 glEndList()、glGenLists()、glCallList()和glDeleteLists()
- 紋理映射函數,主要有一維紋理函數glTexImage1D()、二維紋理函數glTexImage2D()、 設置紋理參數、紋理環境和紋理坐標的函數glTexParameter*()、glTexEnv*()和glTetCoord*()等
- 特殊效果函數。融合函數glBlendFunc()、反走樣函數glHint()和霧化效果glFog*()
- 光柵化、象素操作函數。如象素位置glRasterPos*()、線型寬度glLineWidth()、多邊形繪制模式glPolygonMode(),讀取象素glReadPixel()、復制象素glCopyPixel()等
- 選擇與反饋函數。主要有渲染模式glRenderMode()、選擇緩沖區glSelectBuffer()和反饋緩沖區glFeedbackBuffer()等
- 曲線與曲面的繪制函數。生成曲線或曲面的函數glMap*()、glMapGrid*(),求值器的函數glEvalCoord*() glEvalMesh*()
- 狀態設置與查詢函數。主要有glGet*()、glEnable()、glGetError()等
OpenGL實用庫The OpenGL Utility Library (GLU)
包含有43個函數,函數名的前綴為glu
OpenGL提供了強大的但是為數不多的繪圖命令,所有較復雜的繪圖都必須從點。線、面開始。Glu 為了減輕繁重的編程工作,封裝了OpenGL函數,Glu函數通過調用核心庫的函數,為開發者提供相對簡單的用法,實現一些較為復雜的操作。此函數由glu.dll來負責解釋執行。OpenGL中的核心庫和實用庫可以在所有的OpenGL平台上運行。主要包括了以下幾種。
- 輔助紋理貼圖函數,有gluScaleImage() 、gluBuild1Dmipmaps()、gluBuild2Dmipmaps()
- 坐標轉換和投影變換函數,定義投影方式函數gluPerspective()、gluOrtho2D() 、gluLookAt(),拾取投影視景體函數gluPickMatrix(),投影矩陣計算gluProject()和 gluUnProject()等
- 多邊形鑲嵌工具,有gluNewTess()、 gluDeleteTess()、gluTessCallback()、gluBeginPolygon() gluTessVertex()、gluNextContour()、gluEndPolygon()等
- 二次曲面繪制工具,主要有繪制球面、錐面、柱面、圓環面gluNewQuadric()、gluSphere()、gluCylinder()、gluDisk()、gluPartialDisk()、gluDeleteQuadric()等
- 非均勻有理B樣條繪制工具,主要用來定義和繪制Nurbs曲線和曲面,包括gluNewNurbsRenderer()、gluNurbsCurve()、gluBeginSurface()、gluEndSurface()、gluBeginCurve()、gluNurbsProperty()等函數
- 錯誤反饋工具,獲取出錯信息的字符串gluErrorString()
OpenGL輔助庫
包含有31個函數,函數名前綴為aux
這部分函數提供窗口管理、輸入輸出處理以及繪制一些簡單三維物體。此函數由glaux.dll來負責解釋執行。創建aux庫是為了學習和編寫OpenGL程序,它更像是一個用於測試創意的預備基礎接管。Aux庫在windows實現有很多錯誤,因此很容易導致頻繁的崩潰。在跨平台的編程實例和演示中,aux很大程度上已經被glut庫取代。OpenGL中的輔助庫不能在所有的OpenGL平台上運行。
輔助庫函數主要包括以下幾類
- 窗口初始化和退出函數,auxInitDisplayMode()和auxInitPosition()
- 窗口處理和時間輸入函數,auxReshapeFunc()、auxKeyFunc()和auxMouseFunc()
- 顏色索引裝入函數,auxSetOneColor()
- 三維物體繪制函數。包括了兩種形式網狀體和實心體,如繪制立方體auxWireCube()和 auxSolidCube()。這里以網狀體為例,長方體auxWireBox()、環形圓紋面auxWireTorus()、圓柱auxWireCylinder()、二十面體auxWireIcosahedron()、八面體auxWireOctahedron()、四面體auxWireTetrahedron()、十二面體auxWireDodecahedron()、圓錐體auxWireCone()和茶壺auxWireTeapot()
- 背景過程管理函數auxIdleFunc()
- 程序運行函數auxMainLoop()
OpenGL工具庫 OpenGL Utility Toolkit
包含大約30多個函數,函數名前綴為glut
glut是不依賴於窗口平台的OpenGL工具包,由Mark KLilgrad在SGI編寫(現在在Nvidia),目的是隱藏不同窗口平台API的復雜度。 函數以glut開頭,它們作為aux庫功能更強的替代品,提供更為復雜的繪制功能,此函數由glut.dll來負責解釋執行。由於glut中的窗口管理函數是不依賴於運行環境的,因此OpenGL中的工具庫可以在X-Window, Windows NT, OS/2等系統下運行,特別適合於開發不需要復雜界面的OpenGL示例程序。對於有經驗的程序員來說,一般先用glut理順3D圖形代碼,然后再集成為完整的應用程序。
這部分函數主要包括
- 窗口操作函數,窗口初始化、窗口大小、窗口位置等函數glutInit() glutInitDisplayMode() glutInitWindowSize() glutInitWindowPosition()等
- 回調函數。響應刷新消息、鍵盤消息、鼠標消息、定時器函數等,GlutDisplayFunc() glutPostRedisplay() glutReshapeFunc() glutTimerFunc() glutKeyboardFunc() glutMouseFunc()
- 創建復雜的三維物體。這些和aux庫的函數功能相同。創建網狀體和實心體。如glutSolidSphere()、glutWireSphere()等
- 菜單函數。創建添加菜單的函數GlutCreateMenu()、glutSetMenu()、glutAddMenuEntry()、glutAddSubMenu() 和glutAttachMenu()
- 程序運行函數,glutMainLoop()
GLUT工具箱提供幾種圖形3維圖形的函數
void glutWireSphere(GLdouble radius, GLint slices, GLint stacks); 絲狀球 void glutSolidSphere(GLdouble radius, GLint slices, GLint stacks); 實心球 void glutWireCube(GLdouble size); 絲狀立方體 void glutSolidCube(GLdouble size); 實心立方體 v oid glutWireTorus(GLdouble innerRadius, GLdouble outerRadius,GLint nsides, GLint rings); 絲狀花環 void glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius, GLint nsides, GLint rings); 實心花環 void glutWireIcosahedron(void); 絲狀20面體 void glutSolidIcosahedron(void); 實心20面體 void glutWireOctahedron(void); 絲狀8面體 void glutSolidOctahedron(void); 實心8面體 void glutWireTetrahedron(void); 絲狀4面體 void glutSolidTetrahedron(void); 實心4面體 void glutWireDodecahedron(GLdouble radius); 絲狀12面體 void glutSolidDodecahedron(GLdouble radius); 實心12面體 void glutWireCone(GLdouble radius, GLdouble height, GLint slices,GLint stacks); 絲狀圓錐體 void glutSolidCone(GLdouble radius, GLdouble height, GLint slices, GLint stacks); 實心圓錐體 void glutWireTeapot(GLdouble size); 絲狀茶壺 void glutSolidTeapot(GLdouble size); 實心茶壺
freeglut
freeglut is an open-source alternative to the OpenGL Utility Toolkit (GLUT) library.
因為OpenGL是跨平台的,這給開發者帶來了方便,但是在創建上下文時這也是一個麻煩的地方,因為不同平台的窗口系統和API都是不一樣的,freeglut就是一個openGL的工具庫,封裝了各個平台初始化窗口的過程,開發者只需要調用這個庫中的初始化函數即可創建一個上下文,是GLUT的替代品。
glew
The OpenGL Extension Wrangler Library (GLEW) is a cross-platform open-source C/C++ extension loading library. GLEW provides efficient run-time mechanisms for determining which OpenGL extensions are supported on the target platform.
因為OpenGL只是一個標准/規范,具體的實現是由驅動開發商針對特定顯卡實現的。由於OpenGL驅動版本眾多,它大多數函數的位置都無法在編譯時確定下來,需要在運行時查詢。任務就落在了開發者身上,開發者需要在運行時獲取函數地址並將其保存在一個函數指針中供以后使用。取得地址的方法因平台而異,在Windows上會是類似這樣:
// 定義函數原型 typedef void (*GL_GENBUFFERS) (GLsizei, GLuint*); // 找到正確的函數並賦值給函數指針 GL_GENBUFFERS glGenBuffers = (GL_GENBUFFERS)wglGetProcAddress("glGenBuffers"); // 現在函數可以被正常調用了 GLuint buffer; glGenBuffers(1, &buffer);
你可以看到代碼非常復雜,而且很繁瑣,我們需要對每個可能使用的函數都要重復這個過程。幸運的是,有些庫能簡化此過程,其中GLEW是目前最新,也是最流行的庫。
glfw
GLFW is a free, Open Source, multi-platform library for opening a window, creating an OpenGL context and managing input. It is easy to integrate into existing applications and does not lay claim to the main loop. GLFW is written in C and has native support for Windows, Mac OS X and many Unix-like systems using the X Window System, such as Linux and FreeBSD. GLFW is licensed under the zlib/libpng license.
管理跨平台情況下的窗口創建,openGL的上下文創建和管理輸入等。
測試環境配置:利用freeglut 創建窗口
#include <gl/glut.h> void renderScene(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glBegin(GL_TRIANGLES); glVertex3f(-0.5, -0.5, 0.0); glVertex3f(0.5, 0.0, 0.0); glVertex3f(0.0, 0.5, 0.0); glEnd(); glutSwapBuffers(); } int main(int argc, char** argv) { glutInit(&argc, (char**)argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); glutInitWindowPosition(100, 100); glutInitWindowSize(800, 480); glutCreateWindow("openGL"); glutDisplayFunc(renderScene); glutMainLoop();//enters the GLUT event processing loop. return 0; }
顯示效果如下
博客參考:https://blog.csdn.net/z_dmsd/article/details/70949102 && https://blog.csdn.net/airbigboy/article/details/8903504