OPENGL是什么?
OPENGL是什么?
OpenGL三逗猛明維圖形標(biāo)準(zhǔn)是由AT&T公司UNIX軟件實(shí)驗(yàn)室、IBM
、DEC、SUN、HP、Microsoft和SGI等多家公司在GL圖形庫標(biāo)準(zhǔn)的基礎(chǔ)
上聯(lián)合推出的開放式圖形庫,它使在微機(jī)上實(shí)現(xiàn)三維真實(shí)
感圖形的生成與顯示成為可能。由于OpenGL是開放的圖形標(biāo)
準(zhǔn),用戶原先在UNIX下開發(fā)的OpenGL圖形軟件很容易移植到微
機(jī)上的WindowsNT/95上。筆者在VisualC++4.1(以下簡稱VC)集
成環(huán)境下,開發(fā)了基于OpenGL的三維真實(shí)感圖形應(yīng)用程序,現(xiàn)
介紹如山告下。
微機(jī)上的OpenGL開發(fā)環(huán)境
基于OpenGL標(biāo)準(zhǔn)開發(fā)的應(yīng)用程序必須運(yùn)行于32位Windows
平臺(tái)下,如WindowsNT或Windows95環(huán)境;而且運(yùn)行時(shí)還需有動(dòng)態(tài)
鏈接庫OpenGL32.DLL、Glu32.DLL,這兩個(gè)文件在安裝WindowsNT時(shí)已
自動(dòng)裝載到C:WINNTSYSTEM32目錄下(這里假定用戶將WindowsNT
安裝在C盤上);而對(duì)于使用Windows95平臺(tái)的用戶,則需手工將
兩個(gè)動(dòng)態(tài)庫復(fù)制到Windows95目錄的SYSTEM子目錄中。安裝了
WindowsNT/95和VC4.1后,用戶就具備了基于OpenGL開發(fā)三維圖
形軟件的基本條件。
OpenGL程序設(shè)計(jì)的基本步驟
1.OpenGL在WindowsNT下的運(yùn)行機(jī)制
OpenGL工作在客戶機(jī)/服務(wù)器模式下,當(dāng)客戶方(即基
于OpenGL標(biāo)準(zhǔn)開發(fā)的應(yīng)用程序)向服務(wù)器(OpenGL核心機(jī)制)發(fā)出
命令時(shí),由服務(wù)器負(fù)責(zé)解釋這些命令。通常情況下,客戶方
和服務(wù)器是運(yùn)行在同一臺(tái)微機(jī)上的。由于OpenGL的運(yùn)行機(jī)制
是客戶機(jī)/服務(wù)器模式,這使得用戶能夠十分方便地在網(wǎng)
絡(luò)環(huán)境下使用OpenGL,OpenGL在WindowsNT上的這種實(shí)現(xiàn)方式通常
稱為網(wǎng)絡(luò)透明性。
OpenGL的圖形庫函數(shù)封裝在動(dòng)態(tài)鏈接庫OpenGL32.DLL中,
客戶機(jī)中的所有OpenGL函數(shù)調(diào)用,都被傳送到服務(wù)器上,由
WinSrv.DLL實(shí)現(xiàn)功能,再將經(jīng)過處理的指令發(fā)送到Win32設(shè)備驅(qū)
動(dòng)接口(DDI),從而實(shí)現(xiàn)在計(jì)算機(jī)屏幕上產(chǎn)生圖像。
若使用OpenGL圖形加速卡,則上述機(jī)制中將添加兩個(gè)
驅(qū)動(dòng)器:OpenGL可裝載客戶模塊(OpenGLICD)將安裝在客戶端;硬
件指定DDI將安裝在服務(wù)器端,與WinDDI同一級(jí)別。
2.OpenGL的庫函數(shù)
開發(fā)基于OpenGL的應(yīng)用程序,必須先了解OpenGL的庫函
數(shù)。OpenGL函數(shù)命令方式十分有規(guī)律,每個(gè)庫函數(shù)均有前綴gl
、glu、aux,分別表示該函數(shù)屬于OpenGL基本庫、實(shí)用庫或輔助
庫。WindowsNT下的OpenGL包含了100多個(gè)核心函數(shù),均以gl作為前
綴,同時(shí)還支持另外四類函數(shù):
OpenGL實(shí)用庫函數(shù):43個(gè),以glu作為前綴;
OpenGL輔助庫函數(shù):31個(gè),以aux作為前綴;
Windows專用庫函數(shù)(WGL):6個(gè),以wgl作為前綴;
Win32API函數(shù)(WGL):5個(gè),無前綴。
OpenGL的115個(gè)核心函數(shù)提供了最基本的功能,可以實(shí)
現(xiàn)三維建模、建立光照模型、反走樣、紋理映射等;OpenGL實(shí)
用庫函數(shù)在核心函數(shù)的上一層,這類函數(shù)提供了簡單的調(diào)
用方法,其實(shí)質(zhì)是調(diào)用核心函數(shù),目的是減輕開發(fā)者的編程
工作量;OpenGL輔助庫函數(shù)是一些特殊的函數(shù),可以供初學(xué)者
熟悉OpenGL的編程機(jī)知寬制,然而使用輔助庫函數(shù)的應(yīng)用程序只
能在Win32環(huán)境中使用,可移植性較差,所以開發(fā)者應(yīng)盡量避
免使用輔助庫函數(shù);Windows專用庫函數(shù)(WGL)主要針對(duì)WindowsNT
/95環(huán)境的OpenGL函數(shù)調(diào)用;Win32API函數(shù)用于處理像素存儲(chǔ)格
式、雙緩存等函數(shù)調(diào)用。
3.VC環(huán)境下基于OpenGL的編程步驟
下面介紹在VC環(huán)境中建立基于Opeetting菜單選項(xiàng),在Link欄的Lib輸入域中
添加openg132.lib、glu32.lib,若需使用OpenGL的輔助庫函數(shù),則還
需添加glaux.lib。
(3)選擇View/ClassWizard菜單選項(xiàng),打開MFC對(duì)話框,在
ClassName欄中選擇CMyTestView類,進(jìn)行以下操作:
選擇WM_CREATE消息,鼠標(biāo)單擊EditCode,將OpenGL初始化代碼
添加到OnCreate()函數(shù)中:
/*定義像素存儲(chǔ)格式*/
PIXELFORMATDESCRIPTORpfd=
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL,
PFD_TYPE_RGBA,
24,
0,0,0,0,0,0,
0,0,0,0,0,0,0
32,
0,0,
PFD_MAIN_PLANE,
0,
0,0,0,
}
CCLientdc(this);
intpixelFormat=ChoosePixelFormat(dc.m_hDC,&pfd);
BOOLsuccess=SetPixelFormat(dc.m_hDC,pixelFormat,&pfd);
m_hRC=wglCreateContext(dc.m_hDC);
選擇WM_DESTORY消息,在OnDestory()中添加以下代碼:
wglDeleteContext(m_hRC);
在MyTestView.cpp中,將以下代碼添加到PreCreateWindows()函數(shù)中:
cs.style|=WS_CLIPCHILDREN|WS_CLIPSIBLINGS;
OpenGL只對(duì)WS_CLIPCHILDREN|WS_CLIPSIBLINGS類型窗口有效;
在MyTestView.cpp中,將以下代碼添加到OnDraw()函數(shù)中:
wglMakeCurrent(pDC->m_hDC,m_hRC);
DrawScene();//用戶自定義函數(shù),用于繪制三維場景;
wglMakeCurrent(pDC->m_hDC,NULL);
在MyTestView.cpp中,添加成員函數(shù)DrawScene():
voidCMyTestView::DrawScene()
{/*繪制三維場景*/}
(4)在MyTestView.h中包含以下頭文件并添加類成員說明:
#include
#include
#include
在CTestView類中的protected:段中添加成員變量聲明:
HGLRCm_hRC;
同時(shí)添加成員函數(shù)聲明:
DrawScene();
這樣,一個(gè)基于OpenGL標(biāo)準(zhǔn)的程序框架已經(jīng)構(gòu)造好,用
戶只需在DrawScene()函數(shù)中添加程序代碼即可。
建立三維實(shí)體模型
三維實(shí)體建模是整個(gè)圖形學(xué)的基礎(chǔ),要生成高逼真
度的圖像,首先要生成高質(zhì)量的三維實(shí)體模型。
OpenGL中提供了十幾個(gè)生成三維實(shí)體模型的輔助庫函
數(shù),這些函數(shù)均以aux作為函數(shù)名的前綴。簡單的模型,如球
體、立方體、圓柱等可以使用這些輔助函數(shù)來實(shí)現(xiàn),如
auxWireSphere(GLdoubleradius)(繪制一半徑為radius的網(wǎng)狀球體)。
但是這些函數(shù)難以滿足建立復(fù)雜三維實(shí)體的需要,所以用
戶可以通過其它建模工具(如3DS等)來輔助建立三維實(shí)體模
型數(shù)據(jù)庫。筆者在三維實(shí)體的建模過程中采用3DS提供的2D
Shape、3DLofter和3DEditor進(jìn)行模型的編輯,最后通過將模型數(shù)
據(jù)以DXF文件格式輸出存儲(chǔ)供應(yīng)用程序使用。
真實(shí)感圖形的繪制
1.定義光照模型和材質(zhì)
(1)光源。OpenGL提供了一系列建立光照模型的庫函
數(shù),使用戶可以十分方便地在三維場景中建立所需的光照
模型。OpenGL中的光照模型由環(huán)境光(AmbientLight)、漫射光
(DiffuseLight)、鏡面反射光(SpecularLight)等組成,同時(shí)還可設(shè)
置光線衰減因子來模擬真實(shí)的光源效果。
例如,定義一個(gè)黃色光源如下:
GlfloatLight_position[]={1.0,1.0,1.0,0.0,};
GlfloatLight_diffuse[]={1.0,1.0,0.0,1.0,};
glLightfv(GL_LIGHT0,GL_POSTTION,light_position);//定義光源位置
glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse);//定義光源漫射光
光源必須經(jīng)過啟動(dòng)后才會(huì)影響三維場景中的實(shí)體,可以通過以下指令使光源有效:<
glEnable(LIGHTING);//啟動(dòng)光照模型;
glEnable(GL_LIGHT0);//使光源GL_LIGHT0有效;
OpenGL中一共可以定義GL_LIGHT0~GL_LIGHT7八個(gè)光源。
(2)材質(zhì)。OpenGL中的材質(zhì)是指構(gòu)成三維實(shí)體的材料在
光照模型中對(duì)于紅、綠、藍(lán)三原色的反射率。與光源的定義
類似,材質(zhì)的定義分為環(huán)境、漫射、鏡面反射成分,另外還
有鏡面高光指數(shù)、輻射成分等。通過對(duì)三維實(shí)體的材質(zhì)定義
可以大大提高應(yīng)用程序所繪制的三維場景的逼真程度。例
如:
/*設(shè)置材質(zhì)的反射成分*/
GLfloatmat_ambient[]={0.8,0.8,0.8,1.0};
GLfloatmat_diffuse[]={0.8,0.0,0.8,1.0};/*紫色*/
GLfloatmat_specular[]={1.0,0.0,1.0,1.0};/*鏡面高光亮紫色*/
GLfloatmat_shiness[]={100.0};/*高光指數(shù)*/
glMaterialfv(GL_FRONT,GL_AMBIENT,mat_ambient);/*定義環(huán)境光反射率*/
glMaterialfv(GL_FRONT,GL_DIFFUSE,mat_diffuse);/*定義漫射光反射率*/
glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);/*定義鏡面光反射率*/
glMaterialfv(GL_FRONT,GL_SHINESS,mat_shiness);/*定義高光指數(shù)*/
(3)材質(zhì)RGB值與光源RGB值的關(guān)系。OpenGL中材質(zhì)的顏色
與光照模型中光源的顏色含義略有不同。對(duì)于光源,R、G、B
值表示三原色在光源中所占有的比率;而對(duì)于材質(zhì)定義,R、
G、B的值表示具有這種材質(zhì)屬性的物體對(duì)于三原色的反射
比率,場景中物體所呈現(xiàn)的顏色與光照模型、材質(zhì)定義都相
關(guān)。例如,若定義的光源顏色是(Lr,Lg,Lb)=(1.0,1.0,1.0)(白光),
物體的材質(zhì)顏色定義為(Mr,Mg,Mb)=(0.0,0.0,0.8),則最終到達(dá)人
眼的物體顏色應(yīng)當(dāng)是(Lr*Mr,Lg*Mg,Lb*Mb)=(0.0,0.0,0.8)(藍(lán)色)。
2.讀取三維模型數(shù)據(jù)
為了繪制三維實(shí)體,我們首先必須將預(yù)先生成的三
維實(shí)體模型從三維實(shí)體模型庫中讀出。下圖描述了讀取三
維實(shí)體模型的流程。
3.三維實(shí)體繪制
由于3DS的DXF文件中對(duì)于三維實(shí)體的描述是采用三角
形面片逼近的方法,而在OpenGL函數(shù)庫中,提供了繪制三角形
面片的方法,所以為三維實(shí)體的繪制提供了方便。以下提供
了繪制三角形面片的方法:
glBegin(TRANGLES);//定義三角形繪制開始
glVertexf((GLfloat)x1,(GLfloat)y1,(GLfloat)z1);//第一個(gè)頂點(diǎn)
glVertexf((GLfloat)x2,(GLfloat)y2,(GLfloat)z2);//第二個(gè)頂點(diǎn)
glVertexf((GLfloat)x3,(GLfloat)y3,(GLfloat)z3);//第三個(gè)頂點(diǎn)
glEnd();//繪制結(jié)束
為了提高三維實(shí)時(shí)動(dòng)畫的顯示速度,我們利用了
OpenGL庫中的顯示列表(DisplayList)的功能,將三維場景中的實(shí)
體分別定義為單獨(dú)的顯示列表,預(yù)先生成三維實(shí)體。在圖形
顯示時(shí),只需調(diào)用所需的顯示列表即可顯示相應(yīng)的三維實(shí)
體,而不需要重新計(jì)算實(shí)體在場景中的坐標(biāo),避免了大量的
浮點(diǎn)運(yùn)算。在調(diào)用顯示列表前所作的旋轉(zhuǎn)、平移、光照、材
質(zhì)的設(shè)定都將影響顯示列表中的三維實(shí)體的顯示效果。具
體實(shí)現(xiàn)算法如下:
for(ObjectNo=0;ObjectNo<實(shí)體個(gè)數(shù);ObjectNo++)
{
glNewList(ObjectNo,GL_COMPILE);//創(chuàng)建第ObjectNo個(gè)實(shí)體的顯示列表
for(Fac