天天看點

OpenGL程式設計輕松入門(一)

OpenGL程式設計輕松入門(一)

(由同僚黃燕創作)

本文介紹了有關OpenGL的基本知識,主要涉及顔色、繪制幾何體、坐标變換、堆棧操作、顯示清單、光照和材質、紋理映射、特殊效果、曲面和曲線的繪制、二次幾何體繪制、像素操作、如何繪制動畫物體及菜單管理。通過對本文及本文中例子的了解消化,你可以較容易地進入OpenGL的世界。相信,再通過一段時間的學習,你将很快成為OpenGL高手。

1.         OpenGL背景簡介

OpenGL(Open Graphics Library)是圖形硬體的一個軟體接口,也是該領域的工業标準。圖形程式員利用這些指令可以建立高品質的互動式的三維應用。OpenGL的前身是SGI(Silicon Graphics)公司為其圖形工作站開發的IRIS GL。IRIS GL雖然功能強大但是移植性不好,于是SGI公司便在IRIS GL的基礎上開發了OpenGL。

OpenGL是一個與硬體無關的軟體接口。可以在不同的平台如Windows 95、Windows NT、Unix、Linux、MacOS、OS/2之間進行移植。是以,支援OpenGL的軟體具有很好的移植性,可以獲得非常廣泛的應用。

OpenGL是網絡透明的,具有網絡功能。即便客戶機和伺服器是不同類型的計算機OpenGL程式也可以在網絡上運作。這一點對于制作大型3D圖形、動畫非常有用。例如,《玩具總動員》、《泰坦尼克》等電影的電腦特技畫面就是通過應用OpenGL的網絡功能,使用120多台圖形工作站共同工作來完成的。

OpenGL的發展一直處于一種較為遲緩的态勢,每次版本的提高新增的技術很少,大多隻是對其中部分做出修改和完善。随着DirectX的不斷發展和完善,OpenGL的優勢逐漸喪失,至今雖然已有3Dlabs提倡開發的2.0版本面世,在其中加入了很多類似于DirectX中可程式設計單元的設計,但廠商的使用者認知程度并不高,未來的OpenGL發展前景迷茫。

但是OpenGL具有許多優勢,這些優勢可以為硬體及軟體研發人員提供很多便利。首先,它是行業标準,得到廣泛的技術支援,是唯一的真正開放、穩定、和銷售商無關的、多平台的圖形标準。第二,可靠性和可移植性。第三,允許新功能的加入。第四,可在從PC機到超級計算機不同級别的機器上運作。第四,容易使用,一般的應用程式幾行代碼就可以完成,并且無需考慮硬體。第五,具有大量文檔,例子可供參考。

注意,在不同的平台如何安裝OpenGL,如何設定運作環境會有一些不同。為了力求講解的形象生動,本文舉了十多個例子,這些例子都是在Windows 2000平台,Microsoft Visual C++ 6.0環境下編譯運作的。

作者将盡量詳盡地解釋文中的例子,解釋每一行代碼在做什麼,即便你對OpenGL甚至Visual C++一無所知,你也可以基本上讀懂這些例子,并且可以模仿這些例子寫一些自己的程式。是以如果你是一個初學者,我想本文會對你有很大幫助,但是如果你已經是一個OpenGL程式設計高手,這篇文章對你來說就太簡單了。

2.         一個簡單的例子

先編譯運作一個簡單的例子,這樣我們可以有一個直覺的印象。從這個例子我們可以看到OpenGL可以做什麼,當然這個例子隻做了很簡單的一件事——繪制一個彩色的三角形。除此以外,我們還可以看到典型的OpenGL程式結構及openGL的運作順序。

例1:本例在黑色的背景下繪制一個彩色的三角形。

#include <stdlib.h>

#include <GL/glut.h>

void background(void)

{

    glClearColor(0.0,0.0,0.0,0.0);//設定背景顔色為黑色

}

void myDisplay(void)

    glClear(GL_COLOR_BUFFER_BIT);//buffer設定為顔色可寫

    glBegin(GL_TRIANGLES);//開始畫三角形

        glShadeModel(GL_SMOOTH);//設定為光滑明暗模式

        glColor3f(1.0,0.0,0.0);//設定第一個頂點點為紅色

        glVertex2f(-1.0,-1.0);//設定第一個頂點的坐标為(-1.0,-1.0)

        glColor3f(0.0,1.0,0.0);//設定第二個頂點點為綠色

        glVertex2f(0.0,-1.0);//設定第二個頂點的坐标為(0.0,-1.0)

        glColor3f(0.0,0.0,1.0);//設定第三個頂點點為藍色

        glVertex2f(-0.5,1.0);//設定第三個頂點的坐标為(-0.5,1.0)

    glEnd();//三角形結束

    glFlush();//強制OpenGL函數在有限時間内運作

void myReshape(GLsizei w,GLsizei h)

    glViewport(0,0,w,h);//設定視口

    glMatrixMode(GL_PROJECTION);//指明目前矩陣為GL_PROJECTION

    glLoadIdentity();//将目前矩陣置換為機關陣

    if(w <= h)

        gluOrtho2D(-1.0,1.5,-1.5,1.5*(GLfloat)h/(GLfloat)w);//定義二維正視投影矩陣

    else

        gluOrtho2D(-1.0,1.5*(GLfloat)w/(GLfloat)h,-1.5,1.5);

    glMatrixMode(GL_MODELVIEW);//指明目前矩陣為GL_MODELVIEW

int main(int argc,char ** argv)

    /*初始化*/

    glutInit(&argc,argv);

    glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);

    glutInitWindowSize(400,400);

    glutInitWindowPosition(200,200);

    /*建立視窗*/

    glutCreateWindow("Triangle");

    /*繪制與顯示*/

    background();

    glutReshapeFunc(myReshape);

    glutDisplayFunc(myDisplay);

    /*進入GLUT事件處理循環*/

    glutMainLoop();

    return(0);

首先建立工程,其步驟如下:

1)建立一個Win32 Console Application。

2)連結OpenGL libraries。在Visual C++中先單擊Project,再單擊Settings,再找到Link單擊,最後在Object/library modules 的最前面加上OpenGL32.lib GLu32.lib GLaux.lib

3)單擊Project Settings中的C/C++标簽,将Preprocessor definitions 中的_CONSOLE改為__WINDOWS。最後單擊OK。

現在你可以把下面的例子拷貝到工程中去,編譯運作。你可以看到一個彩色的三角形。

我們先看看main函數。函數中以glut開頭的函數都包含在glut.h中。GLUT庫的函數主要執行如處理多視窗繪制、處理回調驅動事件、生成層疊式彈出菜單、繪制位圖字型和筆畫字型,以及各種視窗管理等任務。

l         glutInit用來初始化GLUT庫并同視窗系統對話協商。

l         glutInitDisplayMode用來确定所建立視窗的顯示模式。本例中的參數GLUT_SINGLE 指定單緩存視窗,這也是預設模式,對應的模式為GLUT_DOUBLE 雙緩存視窗。參數GLUT_RGB指定顔色RGBA模式,這也是預設模式,對應的模式為GLUT_INDEX 顔色索引模式視窗。

l         glutInitWindowSize 初始化視窗的大小,第一個參數為視窗的寬度,第二個參數為視窗的高度,以像素為機關。

l         glutInitWindowPosition 設定初始視窗的位置,第一個參數為視窗左上角x的坐标,第二個參數為視窗左上角y的坐标,以像素為機關。螢幕的左上角的坐标為(0,0),橫坐标向右逐漸增加,縱坐标向下逐漸增加。

l         glutCreateWindow 建立頂層視窗,視窗的名字為擴号中的參數。

l         background() 這是自己寫的函數,設定背景。其實這個函數中的語句可以寫在display函數中,但為了使功能塊更加清晰,是以把背景這一部分單獨提出來。

l         glutReshapeFunc 注冊目前視窗的形狀變化回調函數。當改變視窗大小時,該視窗的形狀改變回調函數将被調用。在此例中就是myReshape指定形狀變化函數。

l         glutDisplayFunc 注冊目前視窗的顯示回調函數。當一個視窗的圖像層需要重新繪制時,GLUT将調用該視窗的的顯示回調函數。在此例中的mydisplay就是顯示回調函數,顯示回調函數不帶任何參數,它負責整個圖像層的繪制。我們的大部分工作将集中在這個函數中。

l         glutMainLoop 進入GLUT事件處理循環。glutMainLoop函數在GLUT程式中最多隻能調用一次,它一旦被調用就不再傳回,并且調用注冊過的回調函數。是以這個函數必須放在注冊回調函數的後面,此例中為glutReshapeFunc, glutDisplayFunc。

現在我們對OpenGL程式的典型的程式結構有了一個了解。首先初始化,包括對GLUT庫的初始化和對視窗的設定及顯示模式的設定。第二,建立視窗。第三,自己創作的核心部分。第四,glutMainLoop 進入GLUT事件處理循環。

下面,我們轉到我們的創作核心。

background這個函數很簡單,隻有一行語句。glClearColor中的四個參數分别是紅、綠、藍和alpha值。這些值定義了視窗的顔色。這些值的範圍在[0,1]之間。預設值均為0。你可以改變這些值,觀察背景色彩的變化。

myDisplay畫了一個彩色的三角形。

l         glClear 将buffers設定為預先設定的值。參數GL_COLOR_BUFFER_BIT表明現在可以向buffer中寫入顔色值。

l         glBegin和glEnd是一一對應的。這兩個函數限制了一組或多組圖元的頂點定義。在這兩個函數中間就是你所繪制的由多個頂點組成的圖元。函數的參數表明了所繪制的圖元的類型。本例中的GL_TRIANGLES 表明所繪制的圖形為三角形。

l         glShadeModel選擇平坦或光滑漸變模式。GL_SMOOTH為預設值,為光滑漸變模式,GL_FLAT為平坦漸變模式。

l         glColor設定目前顔色。後面跟的數字為參數個數。3表明有三個參數,分别為紅、綠、藍,4則多一個參數alpha。緊跟數字後面的字母表示資料類型。本例中的glColor3f表示三個參數,資料類型為GLfloat。

l         glVertex指定頂點。同樣函數明中的數字表明參數個數。參數分别為x,y或x、y、z。緊跟數字後面的字母表示資料類型。本例中glVertex2f表明兩個參數,資料類型為GLfloat。視窗的中心為原心,坐标為(0,0,0)。橫坐标向左為負,向右為正;縱坐标向上為正,向下為負;z坐标向螢幕裡為負,螢幕外為正,坐标系符合右手定則。

現在你将main函數中的glutReshapeFunc(myReshape); 注釋掉,任意改變三角形頂點的坐标你會發現視窗的最左邊,最右邊的x值分别為-1和1,而視窗的最上端,最下端的y值分别為1和-1。由此可見glVertex中坐标的值實際上是和視窗的大小成倍數的關系。好了,現在恢複原來的程式。

l         glFlush迫使OpenGL函數在有限時間裡運作。glFlush清空所有buffer,使所有發出的指令能在規定的時間内運作。一定不能忘記這一條語句。隻有加了這一句,前面的指令才能執行。

myReshape 改變視窗的大小。

l         glViewport(Glint x,Glint y,GLsizei width,GLsizei height)設定視口。視口是一個矩形,x,y為視口左下角的坐标,以像素為機關,預設值為(0,0)。width和height分别為視口的寬和高。OpenGl  context第一次貼到視窗上時width和height分别設定成視窗的大小。

l         glMatrixMode 指明哪一個矩陣為目前矩陣。本例中GL_PROJECTION指明投影矩陣堆棧為随後的矩陣操作的目标。GL_MODELVIEW指明模型視景矩陣。

l         glLoadIdentity将目前矩陣置換為機關陣。

l         gluOrtho2D(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top)定義二維正視投影矩陣。left,right分别設定左右垂直切平面的坐标,bottom,top分别設定上下垂直切平面的坐标。

現在你可能對這幾個參數的意義還不是很清楚。我們現在将myReshape 函數glLoadIdentity();後面所有的語句注釋掉。加上gluOrtho2D(-1.5,1.5,-1.5,1.5);改變三角型的坐标及gluOrtho2D中的數值,你就可以清楚的了解gluOrtho2D中數值的含義。

現在,你應該大緻了解OpenGL到底是怎麼一回事。通過這一節的學習我們知道怎樣使用顔色及繪制幾何圖形及物體的最基本的函數,更多的函數你可以在網上或有關書中查到。下一節我們繼續講一下顔色的使用。

 本文轉自 21cnbao 51CTO部落格,原文連結:http://blog.51cto.com/21cnbao/120265,如需轉載請自行聯系原作者