真實感場景繪製(附源碼)

首先給出繪製效果圖:


說明:

本系統繪製了一個真實感的三維場景,並實現場景漫遊。使用按鍵↑、↓、←、→或W、S、A、D控制運動方向,PgDn和PgUp可以改變觀察者的高度,鼠標控制轉向,按鍵‘F’可以打開和關閉“霧氣”,Esc退出程序。

本場景中繪製了牆壁與地面、天空、石柱、箱子、玻璃球、雪人、霧等對象,下面將依次分析它們的設計思路,這裏將使用相同繪製技術的對象放到一起說明。

1、 牆壁、地面、箱子

它們的基本操作對四邊形的紋理映射,將一幅紋理圖的四個頂點座標分別映射到四邊形的四個頂點上即可。OpenGL就自動通過插值填充多邊形內部的紋理。由於在OpenGL中紋理座標是一個點的屬性,故需要在繪製點之前指定該點的紋理座標。另外在繪製四邊形時要保證繪製順序的一致,這裏統一採用逆時針順序繪製。紋理座標範圍在[0,1]之間,座標超過1則採用重複的方式(OpenGL默認處理方式)。這樣可以在映射時按四邊形的比例設置紋理座標,從而防止紋理圖過度拉伸造成的變形。一個四邊形的紋理映射步驟爲:

glBindTexture(GL_TEXTURE_2D,texture[0]); 

glBegin(GL_QUADS); 

glTexCoord2f(0.0f, 0.0f); glVertex3f(30.0f,0.0f, -170.0f);

glTexCoord2f(1.0f, 0.0f); glVertex3f(30.0f,0.0f, -150.0f);

glTexCoord2f(1.0f, 1.0f); glVertex3f(30.0f,20.0f,-150.0f);

glTexCoord2f(0.0f, 1.0f); glVertex3f(30.0f,20.0f,-170.0f);

glEnd();

實驗效果如下:


圖1.牆壁、地面、箱子

2、 石柱、雪人

石柱和雪人都屬於二次幾何體的繪製和紋理映射,其中雪人由圓柱、球體、圓盤、圓錐構成。OpenGL提供了這些基本幾何體的繪製函數,而且在紋理映射時我們採用自動生成紋理座標的方法,所以這一部分工作量其實很少。另外,爲了給雪人的身體、鼻子等部位設置顏色時,我們需要關閉紋理映射、並更改材質的屬性(物體的顏色是由光源和材質共同作用的結果)。對於石柱,我們加上了繞自身局部座標Y軸的勻速旋轉。實驗效果如下:


圖2.雪人                                                                                   圖3.石柱


我們使用Glut庫提供的如下函數繪製二次幾何體:

gluCylinder:繪製圓柱和圓柱

gluSphere:繪製球體

gluDisk:繪製圓盤

使用gluQuadricTexture設置自動計算紋理座標。

3、 玻璃球

在繪製玻璃球時,爲了在球面上反射出周圍的場景,我們使用了環境映射。由於我們能夠在三維場景中漫遊,這就需要球面上反射出的場景是隨着視點移動而變化的,這一需求可以利用“渲染到紋理”(RTT)技術實現。其基本思想是:首先繪製出環境中的所有物體(除了該玻璃球),接着將繪製得到的場景圖製作成紋理,在繪製該玻璃球時將此紋理圖貼在球面上即可。

我們使用的核心函數是glCopyTexImage2D,該函數可以將幀緩存中的顏色值複製到紋理緩存中。實驗發現該函數性能較低,會拖慢整個程序的速度,爲了平衡繪製質量和速度,可以只拷貝一部分像素值。實驗效果如下:


圖4.玻璃球

4、 霧氣

OpenGL中提供了完整的霧化接口,我們只需要選擇合適的霧氣的混合因子、密度、顏色、起始位置等。我們的霧氣設置如下:

GLfloat fogColor[4]={0.5f, 0.5f, 0.5f, 0.5f};    

glFogi(GL_FOG_MODE,GL_EXP2);//模式

glFogfv(GL_FOG_COLOR,fogColor);//顏色

glFogf(GL_FOG_DENSITY, 0.004f);//密度

glFogf(GL_FOG_START, 5.0f);//開始距離

glFogf(GL_FOG_END, 300.0f);//結束距離

glHint(GL_FOG_HINT,GL_NICEST);//霧化效果

實驗效果如下:



圖5.霧氣

5、 天空

天空包含雲、星星、閃電三個對象。我們要實現的目標是:雲在空中飄動、且能夠遮蓋住空中的星星,每間隔一段時間都會有閃電和雷聲。

天空的繪製主要使用了顏色混合技術。首先將星星的紋理圖映射到天空,爲了實現雲朵覆蓋住星星,我們使用瞭如下技巧:製作一個關於雲圖(圖6)的二值圖像(圖7),其中有云的部分爲黑色、無雲的部分爲白色。將該二值圖像作爲“掩模”與星星圖進行混合,並設置混合因子glBlendFunc (GL_DST_COLOR,GL_ZERO),該設置可以將星星圖中對應“掩模”黑色的部分置爲黑色、對應“掩模”白色的部分保留原色。接着再將雲圖映射至天空,並更改混合因子glBlendFunc(GL_ONE, GL_ONE),該設置實現源色與目的色相加。至此已經實現雲對星星的遮蓋,另外,在進行顏色混合時需要打開OpenGL的顏色混合功能,且要關閉深度測試功能。

圖6.雲圖                           圖7.二值圖


爲了實現雲的飄動,我們在設置雲圖紋理座標時添加一個變量,該變量從0遞增至1,超過1時做減1操作,這樣就可以模擬雲的移動。如下的roll即爲該變量:

glBegin(GL_QUADS); 

glTexCoord2f(0.0f, 3.0f-roll);glVertex3f(-50.0f, 100.0f, -300.0f);

glTexCoord2f(1.0f, 3.0f-roll);glVertex3f( 50.0f, 100.0f, -300.0f);

glTexCoord2f(1.0f, 0.0f-roll);glVertex3f( 50.0f, 100.0f,  300.0f);

glTexCoord2f(0.0f, 0.0f-roll);glVertex3f(-50.0f, 100.0f,  300.0f);

glEnd();

每繪製一定幀數後,我們將一幅閃電紋理圖映射到天空,使用簡單的相加混合,且在首次繪製閃電時調用音頻播放函數,播放一段雷聲,音頻調用函數爲PlaySound。實驗效果如下:



圖8.天空

源碼下載


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章