前言 隨著計算機多媒體技術、可視化技術及圖形學技術的發展,我們可以使用計算機來精確地再現現實世界中的絢麗多彩的三維物體,並充分發揮自身的創造性思維,通過人機交互來模擬、改造現實世界,這就是目前最為時髦的虛擬現實技術。通過這種技術,建築工程師可以直接設計出美觀的樓房模型;軍事指揮員可以模擬戰場進行軍事推演,網民可以足不出戶游覽故宮博物館等名勝古跡等。而虛擬現實技術最重要的一部分內容就是三維圖形編程。當前,三維圖形編程工具中最為突出的是SGI公司的OpenGL(Open Graphics Language,開放式的圖形語言),它已經成為一個工業標准的計算機三維圖形軟件開發接口,並廣泛應用於游戲開發、建築、產品設計、醫學、地球科學、流體力學等領域。值得一提的是,雖然微軟有自己的三維編程開發工具DirectX,但它也提供OpenGL圖形標准,因此,OpenGL可以在微機中廣泛應用。
目前,OpenGL在國內外都掀起了熱潮,但國內對這一領域介紹的資料並不是很多,非凡是有志於在圖形圖像方面進行深入研究的讀者朋友,經常苦於不把握OpenGL編程接口技術,無法向縱深領域擴展。為了開啟三維圖形編程這扇神秘大門,本講座在結合OpenGL有關理論知識的基礎上,著重介紹Visual C++6.0開發環境中的編程實現,由於水平有限,本講座可能無法面面俱到,存在一些疏漏,但相信它可以將開啟"神秘大門"的鑰匙交給讀者朋友們。
一、OpenGL的特點及功能
OpenGL是用於開發簡捷的交互式二維和三維圖形應用程序的最佳環境,任何高性能的圖形應用程序,從3D動畫、CAD輔助設計到可視化訪真,都可以利用OpenGL高質量、高性能的特點。OpenGL自1992年出現以來,逐漸發展完善,已成為一個唯一開放的,獨立於應用平台的圖形標准,一個典型的OpenGL應用程序可以在任何平台上運行--只需要使用目標系統的OpenGL庫重新編譯一下。
OpenGL非常接近硬件,是一個圖形與硬件的接口,包括了100多個圖形函數用來建立三維模型和進行三維實時交互。OpenGL強有力的圖形函數不要求開發人員把三維物體模型的數據寫成固定的數據格式,也不要求開發人員編寫矩陣變換、外部設備訪問等函數,大大地簡化了編寫三維圖形的程序。例如:
1) OpenGL提供一系列的三維圖形單元(圖元)供開發者調用。
2) OpenGL提供一系列的圖形變換函數。
3) OpenGL提供一系列的外部設備訪問函數,使開發者可以方便地訪問鼠標、鍵盤、空間球、數據手套等外部設備。
由於微軟在Windows中包含了OpenGL,所以OpenGL可以與Visual C++緊密接合,簡單快捷地實現有關計算和圖形算法,並保證算法的正確性和可靠性。簡單地說,OpenGL具有建模、變換、色彩處理、光線處理、紋理影射、圖像處理、動畫及物體運動模糊等功能:
1、建模
OpenGL圖形庫除了提供基本的點、線、多邊形的繪制函數外,還提供了復雜的三維物體,如球、錐、多面體、茶壺以及復雜曲線和曲面(例如Bezier、Nurbs等曲線或曲面)的繪制函數。
2、變換
OpenGL圖形庫的變換包括基本變換和投影變換。基本變換有平移、旋轉、變比、鏡像四種變換,投影變換有平行投影(又稱正射投影)和透視投影兩種變換。
3、顏色模式設置
OpenGL顏色模式有兩種,即RGBA模式和顏色索引(Color Index)。
4、光照和材質設置
OpenGL光有輻射光(Emitted Light)、環境光(Ambient Light)、漫反射光(Diffuse Light)和鏡面光(Specular Light)。材質是用光反射率來表示。客觀世界中的物體最終反映到人眼的顏色是光的紅綠藍分量與材質紅綠藍分量的反射率相乘後形成的顏色。
5、紋理映射(Texture Mapping)
利用OpenGL紋理映射功能可以十分逼真地表達物體表面細節。
6、位圖顯示和圖象增強
OpenGL的圖象功能除了基本的拷貝和像素讀寫外,還提供融合(Blending)、反走樣(Antialiasing)和霧(fog)的非凡圖象效果處理。以上三條可是被仿真物更具真實感,增強圖形顯示的效果。
7、雙緩存動畫(Double Buffering)
OpenGL使用了前台緩存和後台緩存交替顯示場景(Scene)技術,簡而言之,後台緩存計算場景、生成畫面,前台緩存顯示後台緩存已畫好的畫面。
8、非凡效果
利用OpenGL還能實現深度暗示(Depth Cue)、運動模糊(Motion Blur)等非凡效果。運動模糊的繪圖方式(motion-blured),模擬物體運動時人眼觀察所感覺的動感現象。深度域效果(depth-of-effects),類似於照相機鏡頭效果,模型在聚焦點處清楚,反之則模糊。
這些三維物體繪圖和非凡效果處理方式,說明OpenGL能夠模擬比較復雜的三維物體或自然景觀。
二、OpenGL工作流程
OpenGL的基本工作流程如下圖:
圖一、OpenGL工作流程
如上圖所示,幾何頂點數據包括模型的頂點集、線集、多邊形集,這些數據經過流程圖的上部,包括運算器、逐個頂點操作等;圖像數據包括象素集、影像集、位圖集等,圖像象素數據的處理方式與幾何頂點數據的處理方式是不同的,但它們都經過光柵化、逐個片元(Fragment)處理直至把最後的光柵數據寫入幀緩沖器。
在OpenGL中的所有數據包括幾何頂點數據和象素數據都可以被存儲在顯示列表中或者立即可以得到處理。OpenGL中,顯示列表技術是一項重要的技術。
OpenGL要求把所有的幾何圖形單元都用頂點來描述,這樣運算器和逐個頂點計算操作都可以針對每個頂點進行計算和操作,然後進行光柵化形成圖形碎片;對於象素數據,象素操作結果被存儲在紋理組裝用的內存中,再象幾何頂點操作一樣光柵化形成圖形片元。整個流程操作的最後,圖形片元都要進行一系列的逐個片元操作,這樣最後的象素值送入幀緩沖器實現圖形的顯示。
根據這個流程,我們可以歸納出在OpenGL中進行主要的圖形操作直至在計算機屏幕上渲染繪制出三維圖形景觀的基本步驟:
1)根據基本圖形單元建立景物模型,並且對所建立的模型進行數學描述(OpenGL中把:點、線、多邊形、圖像和位圖都作為基本圖形單元)。
2)把景物模型放在三維空間中的合適的位置,並且設置視點(viewpoint)以觀察所感愛好的景觀。
3)計算模型中所有物體的色彩,其中的色彩根據應用要求來確定,同時確定光照條件、紋理粘貼方式等。
4)把景物模型的數學描述及其色彩信息轉換至計算機屏幕上的象素,這個過程也就是光柵化(rasterization)。
在這些步驟的執行過程中,OpenGL可能執行其他的一些操作,例如自動消隱處理等。另外,景物光柵化之後被送入幀緩沖器之前還可以根據需要對像素數據進行操作。 三層交換技術 交換機與路由器密碼恢復 交換機的選購 路由器設置專題 路由故障處理手冊 數字化校園網解決方案 三、Windows 中OpenGL庫函數及數據類型
(一)庫函數
開發基於OpenGL的應用程序,必須先了解OpenGL的庫函數。它采用C語言風格,提供大量的函數來進行圖形的處理和顯示。OpenGL圖形庫一共有100多個函數,它們分別屬於OpenGL的基本庫、實用庫、輔助庫等不同的庫。
1、核心庫,包含的函數有115個,它們是最基本的函數,其前綴是gl;這部分函數用於常規的、核心的圖形處理,由gl.dll來負責解釋執行。核心庫中的函數可以進一步分為以下幾類函數。
(1)繪制基本幾何圖元的函數。
glBegain()、glEnd()、glNormal*()、glVertex*()。
(2)矩陣操作、幾何變換和投影變換的函數。
矩陣入棧函數glPushMatrix(),矩陣出棧函數glPopMatrix(),裝載矩陣函數glLoadMatrix(),矩陣相乘函數glMultMatrix(),當前矩陣函數glMatrixMode()和矩陣標准化函數glLoadIdentity(),幾何變換函數glTranslate*()、glRotate*()和glScale*(),投影變換函數glOrtho()、glFrustum()和視口變換函數glViewport()等等。
(3)顏色、光照和材質的函數。
如設置顏色模式函數glColor*()、glIndex*(),設置光照效果的函數glLight*() 、glLightModel*()和設置材質效果函數glMaterial()等等。
(4)顯示列表函數。
主要有創建、結束、生成、刪除和調用顯示列表的函數glNewList()、 glEndList()、glGenLists()、glCallList()和glDeleteLists()等。
(5)紋理映射函數。
主要有一維紋理函數glTexImage1D()、二維紋理函數glTexImage2D()、 設置紋理參數、紋理環境和紋理坐標的函數glTeXParameter*()、glTexEnv*()和glTetCoord*()等。
(6)非凡效果函數。
融合函數glBlendFunc()、反走樣函數glHint()和霧化效果glFog*()。
(7)光柵化、象素操作函數。
像素位置glRasterPos*()、線型寬度glLineWidth()、多邊形繪制模式glPolygonMode(),讀取象素glReadPixel()、復制象素glCopyPixel()等。
(8)選擇與反饋函數。
主要有渲染模式glRenderMode()、選擇緩沖區glSelectBuffer()和反饋緩沖區glFeedbackBuffer()等。
(9)曲線與曲面的繪制函數。
生成曲線或曲面的函數glMap*()、glMapGrid*(),求值器的函數glEvalCoord*() glEvalMesh*()。
(10)狀態設置與查詢函數。主要有glGet*()、glEnable()、glGetError()等。
2、實用庫(OpenGL utility library,GLU),包含的函數功能更高一些,如繪制復雜的曲線曲面、高級坐標變換、多邊形分割等,共有43個,前綴為glu。Glu函數通過調用核心庫的函數,為開發者提供相對簡單的用法,實現一些較為復雜的操作。此類函數由glu.dll來負責解釋執行。主要包括了以下幾種:
(1)輔助紋理貼圖函數。
有gluScaleImage() 、gluBuild1Dmipmaps()、gluBuild2Dmipmaps()等。
(2)坐標轉換和投影變換函數。
定義投影方式函數gluPerspective()、gluOrtho2D() 、gluLookAt(),拾取投影視景體函數gluPickMatrix(),投影矩陣計算gluProject()和 gluUnProject()等。
(3)多邊形鑲嵌工具。
有gluNewTess()、 gluDeleteTess()、gluTessCallback()、gluBeginPolygon() gluTessVertex()、gluNextContour()、gluEndPolygon()等。
(4)二次曲面繪制工具。
主要有繪制球面、錐面、柱面、圓環面gluNewQuadric()、gluSphere()、glUCylinder()、gluDisk()、gluPartialDisk()、gluDeleteQuadric()等等。
(5)非均勻有理B樣條繪制工具。
主要用來定義和繪制Nurbs曲線和曲面,包括gluNewNurbsRenderer()、gluNurbsCurve()、gluBeginSurface()、gluEndSurface()、gluBeginCurve()、gluNurbsProperty()等函數。
(6)錯誤反饋工具。
獲取出錯信息的字符串gluErrorString()等。
3、OpenGL輔助庫(OpenGL auxiliarylibrary,GLAUX),包括簡單的窗口治理、輸入事件處理、某些復雜三維物體繪制等函數,共有31個,前綴為aux。此類函數由glaux.dll來負責解釋執行。輔助庫函數主要包括以下幾類。
(1)窗口初始化和退出函數。
auxInitDisplayMode()和auxInitPosition()。
(2)窗口處理和時間輸入函數。
auxReshapeFunc()、auxKeyFunc()和auxMouseFunc()。
(3)顏色索引裝入函數。
auxSetOneColor()。
(4)三維物體繪制函數。
包括了兩種形式網狀體和實心體,如繪制立方體auxWireCube()和 auxSolidCube()。這裡以網狀體為例,長方體auxWireBox()、環形圓紋面auxWireTorus()、圓柱auxWireCylinder()、二十面體auxWireIcosahedron()、八面體auxWireOctahedron()、四面體auxWireTetrahedron()、十二面體auxWireDodecahedron()、圓錐體auxWireCone()和茶壺auxWireTeapot()。繪制實心體只要將上述函數中的確"Wire"更換成"Solid"就可以了。
(5)其他。
背景過程治理函數auxIdleFunc();程序運行函數auxMainLoop()。
4、OpenGL工具庫(penGL Utility Toolkit)
包含大約30多個函數,函數名前綴為glut,此函數由glut.dll來負責解釋執行。這部分函數主要包括:
(1)窗口操作函數
窗口初始化、窗口大小、窗口位置等函數glutInit() glutInitDisplayMode()、glutInitWindowSize() glutInitWindowPosition()等。
(2)回調函數。
響應刷新消息、鍵盤消息、鼠標消息、定時器函數等,GlutDisplayFunc()、glutPostRedisplay()、 glutReshapeFunc()、glutTimerFunc()、glutKeyboardFunc()、 glutMouseFunc()。
(3)創建復雜的三維物體。這些和aux庫的函數功能相同。創建網狀體和實心體。如glutSolidSphere()、glutWireSphere()等。
(4)菜單函數
創建添加菜單的函數GlutCreateMenu()、glutSetMenu()、glutAddMenuEntry()、glutAddSubMenu() 和glutAttachMenu()。
(5)程序運行函數。
glutMainLoop()。
5、16個WGL函數,專門用於OpenGL和Windows窗口系統的聯接,其前綴為wgl,主要用於創建和選擇圖形操作描述表(renderingcontexts)以及在窗口內任一位置顯示字符位圖。這類函數主要包括以下幾類
(1)繪圖上下文相關函數。
wglCreateContext()、wglDeleteContext()、wglGetCurrentContent()、wglGetCurrentDC() wglDeleteContent()等。
(2)文字和文本處理函數。
wglUseFontBitmaps()、wglUseFontOutlines()。
(3)覆蓋層、地層和主平面層處理函數。
wglCopyContext()、wglCreateLayerPlane()、 wglDescribeLayerPlane()、wglReakizeLayerPlatte()等。
(4)其他函數。
wglShareLists()、wglGetProcAddress()等。
6、另外,還有五個Win32函數用來處理像素格式(pixel formats)和雙緩存。由於它們是對Win32系統的擴展,因此不能應用在其它OpenGL平台上。
(二)OpenGL數據類型
與C語言相對應,OpenGL中也有整數、字節、浮點數等數據類型,為了說明兩者的對應關系,下表將OpenGL的數據類型與相應的C類型進行了對比:
前綴 數據類型 相應C語言類型 OpenGL類型 b 8-bit integer signed char GLbyte s 16-bit integer short GLshort i 32-bit integer long GLint,GLsizei f 32-bit floating-point float GLfloat,GLclampf d 64-bit floating-point double GLdouble,GLclampd ub 8-bit unsigned integer unsigned char GLubyte,GLboolean us 16-bit unsigned integer unsigned short GLushort ui 32-bit unsigned integer unsigned long GLuint,GLenum,GLbitfield 表一、OpenGL數據類型表
此外,OpenGL也定義GLvoid類型,假如用C語言編寫,可以用它替代void類型。
(三)OpenGL庫函數的命名規律
了解了OpenGL的數據類型,讓我們再回過頭來看看OpenGL庫函數的命名規律。所有OpenGL函數采用了以下格式:
<庫前綴><根命令><可選的參數個數><可選的參數類型>
庫前綴有gl、glu、aux、glut、wgl、glx等等,分別表示該函數屬於OpenGL某開發庫等,從函數名後面中還可以看出需要多少個參數以及參數的類型。I代表int型,f代表float型,d代表double型,u代表無符號整型。注重,有的函數參數類型後綴前帶有數字2、3、4。2代表二維,3代表三維,4代表alpha值(以後介紹)。有些OpenGL函數最後帶一個字母v,表示函數參數可用一個指針指向一個向量(或數組)來替代一系列單個參數值。下面兩種格式都表示設置當前顏色為紅色,二者等價。
glColor3f(1.0,0.0,0.0);等價於:
float color_array[]={1.0,0.0,0.0};
glColor3fv(color_array);
除了以上基本命名方式外,還有一種帶"*"星號的表示方法,例如glColor*(),它表示可以用函數的各種方式來設置當前顏色。同理,glVertex*v()表示用一個指針指向所有類型的向量來定義一系列頂點坐標值。