利用OpenGL點精靈實現雲模擬(Cloud Simulation Using OpenGL PointSprite)

 [教學視頻]計算機圖形學基礎 在線學習教程  

*原創文章,轉載請註明出處*

 

利用OpenGL點精靈實現雲模擬

 Cloud Simulation Using OpenGL PointSprite

 

 

這篇教程介紹一種利用OpenGL點精靈,也就是PointSprite來實現雲的模擬。在網上找了一些資料和論文,都是模擬真實的雲和光照,且都比較複雜。後來看到一篇文章,介紹了一篇相對簡單但效果比較好的方法。首先建立好雲的輪廓模型,可以使用3DMax或其他的建模工具,然後創建該模型的包圍體,將包圍體中屬於雲的部分抽取出來,最後對抽取出來的部分進行三角化,然後貼圖,最後加上光照。受到該方法的啓發,這裏我介紹一種更爲簡單的方法來實現對雲的模擬。

 

和從文件讀取雲模型相比,用代碼生成雲的輪廓要快的多。雲的輪廓我們可以用球來模擬,使用多個不同大小的球可以組成不同形狀的雲。圖Fig1中顯示了利用三個半徑不同的球組成的雲的形狀。當然你也可以使用更多不同大小的球來組成更逼真,更復雜的雲。

 

 

 

 

Fig1. 不同大小的球組成的雲的形狀

 

描述這樣三個球只需用幾個結構體即可。

 

      struct VECTOR3

      {

           float x,y,z;

           VECTOR3(){}

           VECTOR3(float _x, float _y, float _z)

           {

                 x = _x; y = _y; z = _z;

           }

      };

 

結構體VECTOR3是一個三維向量結構體,用來表示球的圓心。再加上半徑R我們就可以描述球的幾何性質了。於是球的結構體可以定義爲

 

      struct Sphere

      {

           VECTOR3 C;

           float   R;

           Sphere(){}

           Sphere(VECTOR3 c, float r)

           {

                 C.x = c.x; C.y = c.y; C.z = c.z;

                 R = r;

           }

      };

 

接下來就要得到整個雲的包圍盒,包圍盒可以用包圍盒立方體對角線上的兩個頂點來描述,這裏使用頂點座標全爲負和全爲正的兩個點。包圍盒機構體可以定義爲

 

      struct BoundingBox

      {

           VECTOR3 origin;

           VECTOR3 MinPt;

           VECTOR3 MaxPt;

           Line Boundaries[12];

      };

 

在上面的結構體中,origin表示包圍盒的中心座標,MinPt表示全爲負的頂點,MaxPt表示全爲正的頂點。利用球心所在位置和球半徑就可以決定包圍盒的大小。用每一個球的球心位置減去該球的半徑,然後比較這個值,最小的就是MinPt的值。同樣用每一個球的球心位置加上該球的半徑,其中最大的就是MaxPt的值。爲了方便後面繪製該包圍球,該結構體中還有一個Line結構體,該結構體表示包圍盒的邊的信息,定義如下

 

struct Line

      {

           VECTOR3 origin;

           VECTOR3 end;

      };

 

 

很明顯Line結構體中originend分別表示包圍體一條邊的起點和終點。Fig2顯示了Fig1中雲形狀的包圍盒。

 

(a)

(b)

 

 Fig2. 雲的包圍盒

 

 

爲了用PointSprite來模型雲,我們需知道每個PointSprite在三維空間中的位置。而這些位置就是由雲的形狀來決定的。只要能找到每個球內的PointSprite,那麼就能利用PointSprite來模擬雲的形狀了。這裏用的方法有點體渲染(Volume Rendering)的味道。先將包圍盒分成一個一個的體素(voxel)voxel的多少由voxel的大小來決定。現在要做的就是抽取出所有球內的voxel

抽取的過程很簡單,只要判斷當前voxel和球的位置關係即可。將voxel的座標帶入球的方程(已知球心和半徑),判斷和半徑的關係,只要小於等於半徑的平方,那麼該voxel就在球內。

 

(x-a)2+(y-b)2+(z-c)2 R2

 

上式中(a,b,c)爲球心,R爲半徑。

 

 

(a)

(b)

(c)

(d)

 
 

Fig3 從包圍盒中抽取雲輪廓內的體素

 

Fig3中可以看到,(a)中顯示了包圍盒的所有體素,(b)中抽取出了在雲形狀內部的部分體素。(c)中可以清楚的看到雲內部體素的形狀,而(d)則是將雲內部每個體素的位置加上一定隨機擾動的結果。

 

有了雲內部voxel,就可以將每個voxel當作一個PointSprite,適當的調節PointSprite的大小和體素的大小,然後給PointSprite貼上帶alpha通道的紋理即可,如Fig4

 

 

(a)

(b)

  Fig4 PointSprite模擬的雲

 

整個雲模擬的過程中,重要的部分就是將包圍盒中用於模擬雲的球內部的體素抽取出來。只要正確的抽取出雲內部的體素,那麼雲的形狀也就得到了。具體的內容是實現方法可以參考該教程的源代碼。如果OpenGL版本不支持PointSprite,請更新OpenGL驅動,並下載高版本的OpenGL庫。

 

 

下載該教程和源代碼 

 

 

*原創文章,轉載請註明出處*

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