日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

三维粒子系统的实现

發布時間:2023/12/20 windows 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 三维粒子系统的实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本篇文章中,我們將一起探討三維游戲中粒子系統的方方面面,首先對粒子系統的基本概念特性做一個全面的認知,然后我們依舊是把粒子系統封裝在一個C++類中,模擬了三維游戲中唯美的雪花飛揚的景象,讓我們之前的綜合三維游戲場景更加炫。依舊是放出一張本篇文章的配套程序的截圖:

?

這個帥氣的大天使為我們唯美的雪花飛揚示例程序平添了幾分霸氣有木有?

?PS:示例程序的源代碼在文章末尾提供下載

?

大家應該記得,我們之前也用GDI實現過雪花粒子系統,那個時候由于圖形庫GDI的限制,實現效果或多或少顯得有些拙劣,這篇文章中,我們在DirectX的幫助下,專門用粒子系統重新實現了唯美雪花的飛揚景象,算是在為強大的粒子系統正名吧。

?

?

?

?

一、對粒子系統的基本認知

1983年,奇才Reeves.V.T在它發表的論文《Particle Systems A Technique for?Modeling a Class of Fuzzy Objects》中首次提出了粒子系統的概念。從此,粒子系統就開始廣泛運用于計算機中各種模糊景物的模擬。經常使用粒子系統模擬的現象有火焰、爆炸、煙、水流、火花、落葉、云、霧、雪、塵、流星尾跡或者像發光軌跡這樣的抽象視覺效果等等。這些物體模型在計算機中往往很難用具體的形狀、大小來描述,但是我們可以通過粒子系統的思想,去描述組成這些物體的每個元素和它的變化。

一般情況下,粒子的幾何特征都十分的簡單,可以采用一個像素或者是一個小的多邊形來表示。需要注意的是,粒子系統的最大的缺陷是,當粒子數量達到很大的規模的時候,對運行時機器性能的要求會更加苛刻,如果機器的性能跟不上,就會顯得達不到實時的運行效果,俗話說,就是粒子太多了,我們的電腦跑不動了,就會很卡。

在許多三維建模及渲染包內部就可以創建、修改粒子系統,如 3D Studio Max、Maya 以及 Blender 等。這些編輯程序使藝術家能夠立即看到他們設定的特性或者規則下粒子系統的表現,另外還有一些插件能夠提供增強的粒子系統效果,例如 AfterBurn 以及用于流體的 RealFlow。而2D的粒子特效軟件中particleIllusion最為出色,因為他的渲染比一般的3D軟件快較為平面化。Combustion 這樣的多用途軟件或者只能用于粒子系統的 Particle Studio 等都可以用來生成電影或者視頻中的粒子系統。而目前,粒子系統技術被廣泛用于大型3D游戲地制作中。首先看幾張用粒子系統制作出來的效果圖吧:

?

然后下圖是DirectX SDK中自帶sample一個和粒子系統相關的非常華麗的demo,推薦大家去運行一下,如果你的DirectX SDK安裝在D盤,那么路徑就是

D:\Program Files\Microsoft DirectXSDK (Jun 2010)\Samples\C++\Direct3D11\NBodyGravityCS11

放幾張運行的截圖:

?

粒子系統通常有三個要素:群體性、統一性和隨機性。下面我們分別來簡單看一下:

?

群體性:粒子系統是由大量的可見元素構成的。因此用粒子系統描述一團煙霧是合情合理的,但是我們所用粒子系統去描述一粒煙霧顯然只有鬧笑話了。

統一性:粒子系統的每個元素有具有相同的表現規律。比如,雪花粒子系統中的每一片雪花,都是白色無暇、輕盈靈動的。如果雪花粒子系統中出現了彩色的粒子,那顯然就是異類了。

隨機性粒子系統中每個元素又隨機表現出不同的特性。比如煙霧中每一個煙霧粒子的運動軌跡往往都是雜亂無章的,但是對于整個煙霧系統來說,這些煙霧粒子往往都有一個大體的運動方向。

?

?

?

?

二、粒子系統的基本原理

?

粒子通常都是一個帶有紋理的四邊形。我們通過這個使用了紋理映射的四邊形,可以認為粒子實際上是一個很小的網格模型,只不過是紋理賦予了它特殊的外表罷了。繪制粒子就如果繪制多邊形一樣簡單,因為一個粒子說白了就是一個可改變大小并映射了紋理的四邊形罷了。

下圖就是一個20個單位大小的粒子。

?

?

如果給出了粒子中心點的坐標和粒子的大小,不難計算出繪制粒子所需要的4個頂點坐標,這樣往往比直接給4個頂點坐標來得直觀和節省空間。

另外,很多情況下,因為一個例子是使用兩個三角形組成的一個矩形來表示的,所以通常需要使粒子四邊形始終面向觀察者,這就用到了我們在Direct3D中的廣告板(Billboard)技術,也叫公告版技術。公告版技術的基本原理在這里也提一下吧,后面有機會就專門用一次更新來講解。公告版技術的基本原理就是在渲染一個多邊形時,首先根據觀察方向構造一個旋轉矩陣,利用這個旋轉矩陣旋轉多邊形讓這個多邊形始終是面向觀察者的,如果觀察方向是不斷變化的,那么我們這個旋轉矩陣也要不斷進行調節。這樣,我們始終看到的是這個多邊形“最美好”的一面。這樣先讓多邊形面向觀察者,然后再渲染的技術,就是傳說中的廣告板(Billboard)技術。

我們知道,粒子系統都由大量的粒子構成,每個粒子都有一組屬性,如位置、大小以及紋理,還比如顏色、透明度、運動速度、加速度、自旋周期,生命周期等等屬性。一個粒子需要具有什么樣的屬性,當然是取決于具體的運用了。

另外,粒子屬性的初始值常常都是隨機值,而粒子的產生也常常是由位于空間中某個位置的粒子源產生的。

?

粒子系統在宏觀和微觀上都是隨時間不斷變化的,一套粒子系統在它生命周期的每一刻,一般都需完成以下的四步曲的工作:

?

1.產生新的粒子

這一步當中,我們會根據預定的要求,產生一定數目的新粒子。粒子的各項初始屬性都可以用rand函數來在一定的范圍內賦上隨機的值。

?

2.更新現有粒子的屬性

比如粒子有位置和移動速度,自旋速度等等屬性,這就需要在每一幀當中根據原來的粒子的位置、移動速度和自旋速度重新進行計算和賦值更新。

?

3.刪除已經消亡的粒子

這一步是可選的,具體情況具體分析,因為有些粒子系統中粒子是一直都存在的,沒有消亡一說。在規定了粒子生命周期的一套粒子系統中,就需要判斷每個粒子是否生命走到了盡頭,如果是的話,那么它就game over,消亡了,得用相關代碼把它從粒子系統中消除。

?

4.繪制出粒子

這步沒有的話什么都不是,不顯示出來叫什么粒子系統啊。人家可不管你在之前做了多少工作,算了多少東西,反正玩家是要看到最終的顯示效果的。

?

在Direct3D 8.0以后,我們可以通過一種稱為點精靈(Point Sprite)的特殊點元來描述粒子系統中的粒子。和一般點元不同的是,點精靈可以進行紋理映射并改變大小。點精靈的使用常常是伴隨著SetRenderState中第一個參數取如下的幾個值:

?

D3DRS_POINTSIZE = 154,D3DRS_POINTSIZE_MIN = 155,D3DRS_POINTSPRITEENABLE = 156,D3DRS_POINTSCALEENABLE = 157,D3DRS_POINTSCALE_A = 158,D3DRS_POINTSCALE_B = 159,D3DRS_POINTSCALE_C = 160,

?

另外,粒子系統中的一個重要要素是保存粒子的存儲結構。我們可以用數組,如果需要動態插入和刪除原始的話,就進一步使用鏈表用或者模板了。

需要注意的是,因為粒子系統中會有很多粒子需要不斷地產生、消亡,如果在每個粒子產生時都分配內存,或者在每個粒子消亡時都釋放內存,這顯然會造成巨大的資源開銷,非常不推薦。這里我們按鏈表這種方案來講解。我們通常采用的做法是,未雨綢繆,預先為所有的粒子分配內存,并將這些粒子保存到一個鏈表當中。當需要產生新的粒子時,從這個鏈表中取出所需數量的粒子,并將它們加入到渲染鏈表中,而當一個粒子消亡后,重新將它們放回到原鏈表中,并從渲染鏈表中刪除這些粒子。最后,在程序結束時,統一一次性釋放所有粒子所占的內存空間。這就是比較科學的做法。

呼,不講概念了,太悶了,開始準備動手做些東西吧。

?

?

?

?

三、雪花粒子系統的設計

?

?

我們之前已經提到過,粒子系統可以模擬很多的現象,比如火焰、爆炸、煙、水流、火花、落葉、云、霧、雪、塵、流星尾跡或者發光軌跡。對于現象的模擬,粒子的特性往往需要根據模擬的現象的屬性來具體地設計。

?

對于我們今天要用粒子系統來模擬的雪花飛揚場景,有兩個比較特殊的地方:

1.在雪花飛揚場景中,不需要用點精靈或者公告版技術來讓粒子的四個頂點所在的面始終朝向觀察者,因為雪花飛舞起來是非常優雅的,會悠揚地繞著不同的軸打轉,用了公告板技術反而畫蛇添足,顯得不那么真實了。你見過圓圓的雪花始終面朝著你轉圈的嗎,見鬼了吧!

2.?在雪花飛揚場景中,可以不需要粒子的動態消亡與產生,可以讓雪花粒子在一定區域內下落,如果下落到Y軸的臨界區域,就把粒子的Y坐標設為預定的臨界最高點的Y坐標,就像粒子都是從這個地方產生的一樣,這樣就會模擬出源源不斷地下雪景象。其實,我們又在用慣用伎倆來欺騙玩家了。

就像SisMVG童鞋在淺墨上篇文章中評論的一樣“其實世界上最大的騙子團體就是程序員”。我們只是其實是在讓規定數量的雪花粒子不斷地在跑堂,到了終點再讓他們從起點重新開始跑,一遍一遍地,只要程序不停止運行,那么就永不止息。你以為你體驗了無數的雪花從你眼前呼嘯而過優雅下落的樣子,其實也就是那么來來回回PARTICLE_NUMBER= 8000個而已,哈哈。而這個PARTICLE_NUMBER就是下面我們要封裝雪花飛揚粒子系統的類中給粒子數量規定的宏。

?

好了,我們開始寫這個雪花粒子系統的內容吧。

?

首先依舊是寫出這個名為SnowParticleClass類的大體輪廓。

首先當頭棒喝怒寫4個宏,方便宏觀調控。這四個宏分別用于表示雪花粒子數量,雪花飛揚區域的長度,雪花飛揚區域的寬度,雪花飛揚區域的高度。

?

[cpp]?view plaincopy print?
  • #define?PARTICLE_NUMBER??100000???//雪花粒子數量,顯卡不好、運行起來卡的的童鞋請取小一點。??
  • #define?SNOW_SYSTEM_LENGTH_X??20000???//下雪區域的長度??
  • #define?SNOW_SYSTEM_WIDTH_Z??????????20000???//下雪區域的寬度??
  • #define?SNOW_SYSTEM_HEIGHT_Y????20000???//下雪區域的高度??
  • ?

    這里的PARTICLE_NUMBER雪花粒子數量我們取的10萬,那么后面我們寫出來的游戲場景中就有10萬個雪花粒子,當然,前提是你的顯卡是糕富帥,才禁得住10萬及以上的粒子數量。如果像淺墨這樣的顯卡明日黃花ATI Radeon HD 5730,取八萬的雪花粒子,跑起來幀數就只有10幀左右了,卡的飛起。當然,你取20萬的粒子數量,在下雪區域是在20000x20000x20000的區域中就是超級大暴雪了。。。建議這時候把長度和寬度調大一些,來讓這20萬的粒子的活動區域更大。

    ?

    然后我們寫出雪花粒子的FVF靈活頂點格式。頂點屬性當然是頂點坐標加上紋理坐標了:

    ?

    [cpp]?view plaincopy print?
  • //-----------------------------------------------------------------------------??
  • //點精靈頂點結構和頂點格式??
  • //-----------------------------------------------------------------------------??
  • struct?POINTVERTEX??
  • {??
  • ???????floatx,?y,?z;????//頂點位置??
  • ???????floatu,v?;???????????????//頂點紋理坐標??
  • };??
  • #define?D3DFVF_POINTVERTEX(D3DFVF_XYZ|D3DFVF_TEX1)??
  • ?

    ?

    ?

    接下來是雪花粒子的屬性結構體,想一想現實生活中的雪花有哪些特定的屬性呢?唯美的雪花,有特定的位置,會旋轉,有下降速度,樣子不同,嗯,好,那么我們就這樣寫:

    ?

    ?

    [cpp]?view plaincopy print?
  • //-----------------------------------------------------------------------------??
  • //?Desc:?雪花粒子結構體的定義??
  • //-----------------------------------------------------------------------------??
  • struct?SNOWPARTICLE??
  • {??
  • ???????floatx,?y,?z;??????//坐標位置??
  • ???????floatRotationY;?????????//雪花繞自身Y軸旋轉角度??
  • ???????floatRotationX;???????//雪花繞自身X軸旋轉角度??
  • ???????floatFallSpeed;???????//雪花下降速度??
  • ???????floatRotationSpeed;???????//雪花旋轉速度??
  • ???????int???TextureIndex;?????//紋理索引數??
  • };??

  • ?


    好,邊角廢料寫完了,下面正式來設計這個類吧。首先來看一看要寫哪些成員變量,LPDIRECT3DDEVICE9類型的設備接口指針m_pd3dDevice不能少吧,雪花粒子數組m_Snows要有吧,頂點緩存對象m_pVertexBuffer要有吧,保存不同雪花紋理樣式的雪花紋理數組m_pTexture要有吧,嗯,成員變量就這些。

    然后看看要有哪些成員函數,構造函數,析構函數先顯式地寫出來,然后粒子系統初始化函數InitSnowParticle,粒子系統更新函數UpdateSnowParticle,粒子系統渲染函數RenderSnowParticle,嗯,成員函數也就是這些了。整體來看,這里類的輪廓就是如下,即貼出SnowParticleClass.h的全部代碼:

    ?

    [cpp]?view plaincopy print?
  • //=============================================================================??
  • //?Name:?SnowParticleClass.h??
  • //????Des:一個封裝了雪花粒子系統系統的類的頭文件??
  • //?2013年?3月31日?Create?by?淺墨??
  • //=============================================================================??
  • ???
  • ???
  • #pragma?once??
  • #include?"D3DUtil.h"??
  • #define?PARTICLE_NUMBER??20000???//雪花粒子數量,顯卡不好、運行起來卡的童鞋請取小一點。??
  • #define?SNOW_SYSTEM_LENGTH_X??20000???//下雪區域的長度??
  • #define?SNOW_SYSTEM_WIDTH_Z??????????20000???//下雪區域的寬度??
  • #define?SNOW_SYSTEM_HEIGHT_Y????20000???//下雪區域的高度??
  • ???
  • //-----------------------------------------------------------------------------??
  • //點精靈頂點結構和頂點格式??
  • //-----------------------------------------------------------------------------??
  • struct?POINTVERTEX??
  • {??
  • ???????floatx,?y,?z;????//頂點位置??
  • ???????floatu,v?;???????????????//頂點紋理坐標??
  • };??
  • #define?D3DFVF_POINTVERTEX(D3DFVF_XYZ|D3DFVF_TEX1)??
  • ???
  • ???
  • //-----------------------------------------------------------------------------??
  • //?Desc:?雪花粒子結構體的定義??
  • //-----------------------------------------------------------------------------??
  • struct?SNOWPARTICLE??
  • {??
  • ???????floatx,?y,?z;??????//坐標位置??
  • ???????floatRotationY;?????????//雪花繞自身Y軸旋轉角度??
  • ???????floatRotationX;???????//雪花繞自身X軸旋轉角度??
  • ???????floatFallSpeed;???????//雪花下降速度??
  • ???????floatRotationSpeed;???????//雪花旋轉速度??
  • ???????int???TextureIndex;?????//紋理索引數??
  • };??
  • ???
  • //-----------------------------------------------------------------------------??
  • //?Desc:?粒子系統類的定義??
  • //-----------------------------------------------------------------------------??
  • class?SnowParticleClass??
  • {??
  • private:??
  • ???????LPDIRECT3DDEVICE9????????????????????????????m_pd3dDevice;?????????????????//D3D設備對象??
  • ???????SNOWPARTICLE????????????????????????????????????m_Snows[PARTICLE_NUMBER];????//雪花粒子數組??
  • ???????LPDIRECT3DVERTEXBUFFER9???m_pVertexBuffer;??????//保存粒子數據的頂點緩存??
  • ???????LPDIRECT3DTEXTURE9??????????????????m_pTexture[6];??//雪花紋理??
  • ???
  • public:??
  • ???????SnowParticleClass(LPDIRECT3DDEVICE9pd3dDevice);???//構造函數??
  • ???????~SnowParticleClass();??????????????????????????????????//析構函數??
  • ???????HRESULTInitSnowParticle();????????//粒子系統初始化函數??
  • ???????HRESULTUpdateSnowParticle(?float?fElapsedTime);???//粒子系統更新函數??
  • ???????HRESULTRenderSnowParticle(?);???//粒子系統渲染函數??
  • };??


  • ?

    ?

    ?

    ?

    四、雪花粒子系統的實現

    ?

    又到了做填空題的時候,對著上面我們寫勾勒出來的SnowParticleClass類,我們有5個函數需要填上實現代碼,還等什么,我們開始吧。

    首先呢,構造函數:

    ?

    [cpp]?view plaincopy print?
  • //-------------------------------------------------------------------------------------------------??
  • //?Desc:?構造函數??
  • //-------------------------------------------------------------------------------------------------??
  • SnowParticleClass::SnowParticleClass(LPDIRECT3DDEVICE9pd3dDevice)??
  • {??
  • ???????//給各個參數賦初值??
  • ???????m_pd3dDevice=pd3dDevice;??
  • ???????m_pVertexBuffer=NULL;???
  • ???????for(inti=0;?i<5;?i++)??
  • ??????????????m_pTexture[i]=?NULL;??
  • }??

  • ?

    ?

    接下來,粒子系統初始化函數InitSnowParticle()。首先呢,調用srand重新播種一下隨機數種子。然后for循環為所有的雪花粒子賦予獨一無二的各項屬性值。接著,用講爛了的頂點緩存使用五步曲的其中的三步為代表著所有雪花粒子屬性的一個頂點緩存賦值,最后調用6次D3DXCreateTextureFromFile從文件加載6種不同的雪花紋理進來。這6種雪花紋理圖是淺墨按照素材PS出來,分別導出的,效果圖在下面,還不錯,各有特點,非常漂亮:

    ?

    ??????????

    ?

    ?


    經過上面的思考,InitSnowParticle()函數的實現代碼我們就知道怎么寫了:

    ?

    [cpp]?view plaincopy print?
  • //-------------------------------------------------------------------------------------------------??
  • //?Name:?SnowParticleClass::InitSnowParticle(?)??
  • //?Desc:?粒子系統初始化函數??
  • //-------------------------------------------------------------------------------------------------??
  • HRESULTSnowParticleClass::InitSnowParticle(?)??
  • {??
  • ???????//初始化雪花粒子數組??
  • ???????srand(GetTickCount());??
  • ???????for(inti=0;?i<PARTICLE_NUMBER;?i++)??
  • ???????{???????
  • ??????????????m_Snows[i].x????????=float(rand()%SNOW_SYSTEM_LENGTH_X-SNOW_SYSTEM_LENGTH_X/2);??
  • ??????????????m_Snows[i].z????????=?float(rand()%SNOW_SYSTEM_WIDTH_Z-SNOW_SYSTEM_WIDTH_Z/2);??
  • ??????????????m_Snows[i].y????????=?float(rand()%SNOW_SYSTEM_HEIGHT_Y);??
  • ??????????????m_Snows[i].RotationY?????=?(rand()%100)/50.0f*D3DX_PI;??
  • ??????????????m_Snows[i].RotationX???=?(rand()%100)/50.0f*D3DX_PI;??
  • ??????????????m_Snows[i].FallSpeed???=?300.0f?+?rand()%500;??
  • ??????????????m_Snows[i].RotationSpeed???=?5.0f?+?rand()%10/10.0f;??
  • ??????????????m_Snows[i].TextureIndex=?rand()%6;??
  • ???????}??
  • ???
  • ???
  • ???????//創建雪花粒子頂點緩存??
  • ???????m_pd3dDevice->CreateVertexBuffer(4*sizeof(POINTVERTEX),?0,??
  • ??????????????D3DFVF_POINTVERTEX,D3DPOOL_MANAGED,&m_pVertexBuffer,?NULL?);??
  • ???
  • ???????//填充雪花粒子頂點緩存??
  • ???????POINTVERTEXvertices[]?=??
  • ???????{??
  • ??????????????{-20.0f,?0.0f,?0.0f,???0.0f,?1.0f,?},??
  • ??????????????{-20.0f,?40.0f,?0.0f,???0.0f,?0.0f,?},??
  • ??????????????{??20.0f,?0.0f,?0.0f,???1.0f,?1.0f,?},??
  • ??????????????{??20.0f,?40.0f,?0.0f,???1.0f,?0.0f,?}??
  • ???????};??
  • ???????//加鎖??
  • ???????VOID*pVertices;??
  • ???????m_pVertexBuffer->Lock(0,?sizeof(vertices),?(void**)&pVertices,?0?);??
  • ???????//訪問??
  • ???????memcpy(pVertices,?vertices,?sizeof(vertices)?);??
  • ???????//解鎖??
  • ???????m_pVertexBuffer->Unlock();??
  • ???
  • ???????//創建6種雪花紋理??
  • ???????D3DXCreateTextureFromFile(m_pd3dDevice,?L"GameMedia\\snow1.jpg",?&m_pTexture[0]?);??
  • ???????D3DXCreateTextureFromFile(m_pd3dDevice,?L"GameMedia\\snow2.jpg",?&m_pTexture[1]?);??
  • ???????D3DXCreateTextureFromFile(m_pd3dDevice,?L"GameMedia\\snow3.jpg",?&m_pTexture[2]?);??
  • ???????D3DXCreateTextureFromFile(m_pd3dDevice,?L"GameMedia\\snow4.jpg",?&m_pTexture[3]?);??
  • ???????D3DXCreateTextureFromFile(m_pd3dDevice,?L"GameMedia\\snow5.jpg",?&m_pTexture[4]?);??
  • ???????D3DXCreateTextureFromFile(m_pd3dDevice,?L"GameMedia\\snow6.jpg",?&m_pTexture[5]?);??
  • ???
  • ???????returnS_OK;??
  • }??
  • ?

    ?

    接著我們來看一下粒子系統更新函數UpdateSnowParticle怎么實現。其實非常簡單,就是一個for循環遍歷所有的粒子,看有哪些需要更新的就可以了,對于我們雪花粒子系統,需要更新一下每個粒子的Y坐標,然后判斷是否到了“地面”,然后還要改變其自旋角度。那么,代碼寫出來就是這樣了:

    ?

    [cpp]?view plaincopy print?
  • //-------------------------------------------------------------------------------------------------??
  • //?Name:?SnowParticleClass::UpdateSnowParticle(?)??
  • //?Desc:?粒子系統更新函數??
  • //-------------------------------------------------------------------------------------------------??
  • HRESULTSnowParticleClass::UpdateSnowParticle(?float?fElapsedTime)??
  • {??
  • ???
  • ???????//一個for循環,更新每個雪花粒子的當前位置和角度??
  • ???????for(inti=0;?i<PARTICLE_NUMBER;?i++)??
  • ???????{??
  • ??????????????m_Snows[i].y-=?m_Snows[i].FallSpeed*fElapsedTime;??
  • ???
  • ??????????????//如果雪花粒子落到地面,?重新將其高度設置為最大??
  • ??????????????if(m_Snows[i].y<0)??
  • ?????????????????????m_Snows[i].y=?SNOW_SYSTEM_WIDTH_Z;??
  • ??????????????//更改自旋角度??
  • ??????????????m_Snows[i].RotationY????+=?m_Snows[i].RotationSpeed?*?fElapsedTime;??
  • ??????????????m_Snows[i].RotationX??+=?m_Snows[i].RotationSpeed?*?fElapsedTime;??
  • ???????}??
  • ???
  • ???????returnS_OK;??
  • }??
  • ?

    ?

    ?

    最后來看一下最關鍵的粒子系統渲染函數RenderSnowParticle怎么寫。首先禁用照明,然后設置紋理狀態,接著設置設置Alpha混合系數,設置背面消隱模式為不剔除,然后就開始渲染了。需要注意的是設置Alpha混合系數這里依舊是我們之前沒有專門花一篇文章講,這里理解它的功能為進行透明貼圖就行了。就是我們在寫GDI游戲小程序的時候一直在做的糾結事情,把圖片背景的黑邊去掉。好了,思路有了,寫代碼還會難嗎:

    ?

    ?

    [cpp]?view plaincopy print?
  • //-------------------------------------------------------------------------------------------------??
  • //?Name:?SnowParticleClass::RenderSnowParticle(?)??
  • //?Desc:?粒子系統渲染函數??
  • //-------------------------------------------------------------------------------------------------??
  • HRESULT?SnowParticleClass::RenderSnowParticle(??)??
  • {??
  • ???????//禁用照明效果??
  • ???????m_pd3dDevice->SetRenderState(D3DRS_LIGHTING,?false?);??
  • ???
  • ???????//設置紋理狀態??
  • ???????m_pd3dDevice->SetTextureStageState(0,?D3DTSS_COLOROP,??D3DTOP_SELECTARG1);???//將紋理顏色混合的第一個參數的顏色值用于輸出??
  • ???????m_pd3dDevice->SetTextureStageState(0,?D3DTSS_COLORARG1,?D3DTA_TEXTURE?);??//紋理顏色混合的第一個參數的值就取紋理顏色值??
  • ???????m_pd3dDevice->SetSamplerState(0,?D3DSAMP_MINFILTER,?D3DTEXF_LINEAR?);?//縮小過濾狀態采用線性紋理過濾??
  • ???????m_pd3dDevice->SetSamplerState(0,?D3DSAMP_MAGFILTER,?D3DTEXF_LINEAR?);?//放大過濾狀態采用線性紋理過濾??
  • ???
  • ???????//設置Alpha混合系數??
  • ???????m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,true);???//打開Alpha混合??
  • ???????m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE);???//源混合系數設為1??
  • ???????m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE);??//目標混合系數設為1??
  • ???
  • ???????//設置剔出模式為不剔除任何面??
  • ???????m_pd3dDevice->SetRenderState(D3DRS_CULLMODE,?D3DCULL_NONE?);??
  • ???
  • ???????//渲染雪花??
  • ???????for(inti=0;?i<PARTICLE_NUMBER;?i++)??
  • ???????{??
  • ??????????????//構造并設置當前雪花粒子的世界矩陣??
  • ??????????????staticD3DXMATRIX?matYaw,?matPitch,?matTrans,?matWorld;??
  • ??????????????D3DXMatrixRotationY(&matYaw,m_Snows[i].RotationY);??
  • ??????????????D3DXMatrixRotationX(&matPitch,m_Snows[i].RotationX);??
  • ??????????????D3DXMatrixTranslation(&matTrans,m_Snows[i].x,?m_Snows[i].y,?m_Snows[i].z);??
  • ??????????????matWorld=?matYaw?*?matPitch?*?matTrans;??
  • ??????????????m_pd3dDevice->SetTransform(D3DTS_WORLD,??&matWorld);??
  • ???
  • ??????????????//渲染當前雪花粒子??
  • ??????????????m_pd3dDevice->SetTexture(0,?m_pTexture[m_Snows[i].TextureIndex]?);???//設置紋理??
  • ??????????????m_pd3dDevice->SetStreamSource(0,m_pVertexBuffer,?0,?sizeof(POINTVERTEX));?//把包含的幾何體信息的頂點緩存和渲染流水線相關聯???
  • ??????????????m_pd3dDevice->SetFVF(D3DFVF_POINTVERTEX);????//設置FVF靈活頂點格式??
  • ??????????????m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,0,?2);???//繪制??
  • ???
  • ???????}??
  • ???
  • ???????//恢復相關渲染狀態:Alpha混合?、剔除狀態、光照??
  • ???????m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,false);??
  • ???????m_pd3dDevice->SetRenderState(D3DRS_CULLMODE,?D3DCULL_CCW?);??
  • ???????m_pd3dDevice->SetRenderState(D3DRS_LIGHTING,?true?);??
  • ???
  • ???????returnS_OK;??
  • }??
  • ?

    ?

    析構函數就很簡單了,就是在收拾殘局,看有什么COM接口要釋放的:

    ?

    [cpp]?view plaincopy print?
  • //-------------------------------------------------------------------------------------------------??
  • //?Desc:?析構函數??
  • //-------------------------------------------------------------------------------------------------??
  • SnowParticleClass::~SnowParticleClass()??
  • {??
  • ???????SAFE_RELEASE(m_pVertexBuffer);??
  • ???
  • ???????for(inti=0;i<3;?i++)??
  • ???????{??
  • ??????????????SAFE_RELEASE(m_pTexture[i]);??
  • ???????}??
  • ???
  • ?


    五,雪花飛揚粒子類的使用

    與類打交道封裝功能和我們經歷的生活一樣,也是一個先苦后甜的過程。

    設計和實現這個類的時候或許是苦澀的,但是先苦后甜是必須的,寫完這個類之后,用起來非常的方便,只用幾行代碼而已,一個唯美的雪花飛揚景象就加入到我們的游戲場景中了。。

    也就是如下的三步:

    ?

    Ⅰ.首先,定義一個SnowParticleClass類的全局指針實例:

    ?

    [cpp]?view plaincopy print?
  • SnowParticleClass*?????????????????g_pSnowParticles=?NULL;?????????????//雪花粒子系統的指針實例??
  • ?

    ?

    Ⅱ.然后,在初始化階段拿著雪花飛揚類的指針對象SnowParticleClass到處“指”,創建并初始化粒子系統:

    ?

    [cpp]?view plaincopy print?
  • //創建并初始化雪花粒子系統??
  • ????g_pSnowParticles=?new?SnowParticleClass(g_pd3dDevice);??
  • ????g_pSnowParticles->InitSnowParticle();??
  • ?

    ?

    ?

    Ⅲ.最后,就是在Render函數中依然是拿著天空類的指針對象g_pSnowParticles先指一下UpdateSnowParticle函數,更新粒子系統,然后再指一下RenderSnowParticle函數,進行渲染。

    ?

    [cpp]?view plaincopy print?
  • //繪制雪花粒子系統??
  • ??????g_pSnowParticles->UpdateSnowParticle(fTimeDelta);??
  • ??????g_pSnowParticles->RenderSnowParticle();??
  • ?

    ? ? ??

    另外需要注意上面更新粒子系統的UpdateSnowParticle函數我們用到了一個流逝時間參數fTimeDelta,所以我們就要把我們服役多年的消息循環中改成如下含有流逝時間的更加先進的消息循環體系,然后讓Direct3D_Update和Direct3D_Render各增加一個代表流逝時間的fTimeDelta參數。

    ?

    [cpp]?view plaincopy print?
  • //消息循環過程??
  • ???????MSGmsg?=?{?0?};??//初始化msg??
  • ???????while(msg.message?!=?WM_QUIT?)??????????????????//使用while循環??
  • ???????{??
  • ??????????????staticFLOAT?fLastTime??=(float)::timeGetTime();??
  • ??????????????staticFLOAT?fCurrTime??=(float)::timeGetTime();??
  • ??????????????staticFLOAT?fTimeDelta?=?0.0f;??
  • ??????????????fCurrTime??=?(float)::timeGetTime();??
  • ??????????????fTimeDelta=?(fCurrTime?-?fLastTime)?/?1000.0f;??
  • ??????????????fLastTime??=?fCurrTime;??
  • ???
  • ??????????????if(PeekMessage(?&msg,?0,?0,?0,?PM_REMOVE?)?)??//查看應用程序消息隊列,有消息時將隊列中的消息派發出去。??
  • ??????????????{??
  • ?????????????????????TranslateMessage(&msg?);??????????//將虛擬鍵消息轉換為字符消息??
  • ?????????????????????DispatchMessage(&msg?);??????????//該函數分發一個消息給窗口程序。??
  • ??????????????}??
  • ??????????????else??
  • ??????????????{??
  • ?????????????????????Direct3D_Update(hwnd,fTimeDelta);?????????//調用更新函數,進行畫面的更新??
  • ?????????????????????Direct3D_Render(hwnd,fTimeDelta);?????????????????//調用渲染函數,進行畫面的渲染???????????????????
  • ??????????????}??
  • ???????}<span?style="font-family:?'Microsoft?YaHei';?">????</span>??
  • ?

    ?

    嗯,既然類都寫完了,用起來就是這么簡單。

    ?

    ?

    六、詳細注釋的源代碼欣賞

    ?

    本篇文章配套的源代碼在之前的基礎上又增加了兩個文件,也就是實現雪花飛揚粒子系統類的源文件和頭文件。全部文件數量增加到了12個,它們的列表如下:

    ?

    ?

    我們依舊只貼出核心代碼main.cpp,其他的眾多文件大家下源代碼回去看就好了。

    ?

    [cpp]?view plaincopy print?
  • //*****************************************************************************************??
  • //??
  • //【Visual?C++】游戲開發筆記系列配套源碼五十??淺墨DirectX教程十八??雪花飛揚:實現唯美的粒子系統??
  • //???????VS2010版??
  • //?2013年?3月31日??Create?by?淺墨???
  • //圖標素材出處:?VAMPIRE_SWEETIE??
  • //背景音樂素材出處:魔獸爭霸3?暗夜精靈戰斗曲??
  • //人物模型素材出處:英雄無敵6??
  • //更多內容請訪問我的博客:?http://blog.csdn.net/zhmxy555???
  • //??
  • //*****************************************************************************************???
  • ??
  • ??
  • //*****************************************************************************************??
  • //?Desc:?宏定義部分?????
  • //*****************************************************************************************??
  • #define?SCREEN_WIDTH????932?????????????????????//為窗口寬度定義的宏,以方便在此處修改窗口寬度??
  • #define?SCREEN_HEIGHT???700?????????????????????????//為窗口高度定義的宏,以方便在此處修改窗口高度??
  • #define?WINDOW_TITLE????_T("【Visual?C++】游戲開發筆記系列配套示例程序五十??淺墨DirectX教程十八??雪花飛揚:實現唯美的粒子系統")?//為窗口標題定義的宏??
  • ??
  • ??
  • ??
  • //*****************************************************************************************??
  • //?Desc:?頭文件定義部分????
  • //*****************************************************************************************?????????????????????????????????????????????????????????????????????????????????????????
  • #include?<d3d9.h>??
  • #include?<d3dx9.h>??
  • #include?<tchar.h>??
  • #include?<time.h>???
  • #include?"DirectInputClass.h"??
  • #include?"CameraClass.h"??
  • #include?"TerrainClass.h"??
  • #include?"SkyBoxClass.h"??
  • #include?"SnowParticleClass.h"??
  • ??
  • ??
  • //*****************************************************************************************??
  • //?Desc:?庫文件定義部分????
  • //*****************************************************************************************???
  • #pragma?comment(lib,"d3d9.lib")??
  • #pragma?comment(lib,"d3dx9.lib")??
  • #pragma?comment(lib,?"dinput8.lib")?????//?使用DirectInput必須包含的庫文件,注意這里有8??
  • #pragma?comment(lib,"dxguid.lib")??
  • #pragma?comment(lib,?"winmm.lib")???
  • ??
  • ??
  • ??
  • //*****************************************************************************************??
  • //?Desc:?全局變量聲明部分????
  • //*****************************************************************************************??
  • LPDIRECT3DDEVICE9???????????????????g_pd3dDevice?=?NULL;????????????????//Direct3D設備對象??
  • LPD3DXFONT??????????????????????????????g_pTextFPS?=NULL;????//字體COM接口??
  • LPD3DXFONT??????????????????????????????g_pTextAdaperName?=?NULL;??//?顯卡信息的2D文本??
  • LPD3DXFONT??????????????????????????????g_pTextHelper?=?NULL;??//?幫助信息的2D文本??
  • LPD3DXFONT??????????????????????????????g_pTextInfor=?NULL;??//?繪制信息的2D文本??
  • float???????????????????????????????????????????g_FPS=?0.0f;???????//一個浮點型的變量,代表幀速率??
  • wchar_t?????????????????????????????????????g_strFPS[50]?={0};????//包含幀速率的字符數組??
  • wchar_t?????????????????????????????????????g_strAdapterName[60]?={0};???//包含顯卡名稱的字符數組??
  • D3DXMATRIX??????????????????????????g_matWorld;?????????????????????????//世界矩陣??
  • LPD3DXMESH??????????????????????????g_pMesh?=?NULL;?????????????//?網格對象??
  • D3DMATERIAL9*???????????????????????g_pMaterials=?NULL;?????????//?網格的材質信息??
  • LPDIRECT3DTEXTURE9*?????????????g_pTextures?=?NULL;?????????//?網格的紋理信息??
  • DWORD???????????????????????????????????g_dwNumMtrls?=?0;???????????//?材質的數目??
  • LPD3DXMESH??????????????????????????g_cylinder?=?NULL;??????????????//柱子網格對象??
  • D3DMATERIAL9????????????????????????????g_MaterialCylinder;?????????????//柱子的材質??
  • D3DLIGHT9???????????????????????????????g_Light;???//全局光照??
  • DInputClass*????????????????????????????????g_pDInput?=?NULL;???????????????//DInputClass類的指針實例??
  • CameraClass*????????????????????????????g_pCamera?=?NULL;???????????????//攝像機類的指針實例??
  • TerrainClass*???????????????????????????????g_pTerrain?=?NULL;??????????????//地形類的指針實例??
  • SkyBoxClass*????????????????????????????????g_pSkyBox=NULL;?????????????????//天空盒類的指針實例??
  • SnowParticleClass*??????????????????????g_pSnowParticles?=?NULL;????????//雪花粒子系統的指針實例??
  • ???
  • ??
  • ??
  • ??
  • ??
  • //*****************************************************************************************??
  • //?Desc:?全局函數聲明部分???
  • //*****************************************************************************************???
  • LRESULT?CALLBACK????????WndProc(?HWND?hwnd,?UINT?message,?WPARAM?wParam,?LPARAM?lParam?);??
  • HRESULT?????????????????????Direct3D_Init(HWND?hwnd,HINSTANCE?hInstance);??
  • HRESULT?????????????????????Objects_Init();??
  • void????????????????????????????????Direct3D_Render(?HWND?hwnd,FLOAT?fTimeDelta);??
  • void????????????????????????????????Direct3D_Update(?HWND?hwnd,FLOAT?fTimeDelta);??
  • void????????????????????????????????Direct3D_CleanUp(?);??
  • float???????????????????????????????Get_FPS();??
  • void????????????????????????????????HelpText_Render(HWND?hwnd);??
  • ??
  • //*****************************************************************************************??
  • //?Name:?WinMain(?)??
  • //?Desc:?Windows應用程序入口函數??
  • //*****************************************************************************************??
  • int?WINAPI?WinMain(HINSTANCE?hInstance,?HINSTANCE?hPrevInstance,LPSTR?lpCmdLine,?int?nShowCmd)??
  • {??
  • ??
  • ????//開始設計一個完整的窗口類??
  • ????WNDCLASSEX?wndClass={0}?;???????????????//用WINDCLASSEX定義了一個窗口類,即用wndClass實例化了WINDCLASSEX,用于之后窗口的各項初始化??????
  • ????wndClass.cbSize?=?sizeof(?WNDCLASSEX?)?;????//設置結構體的字節數大小??
  • ????wndClass.style?=?CS_HREDRAW?|?CS_VREDRAW;???//設置窗口的樣式??
  • ????wndClass.lpfnWndProc?=?WndProc;?????????????//設置指向窗口過程函數的指針??
  • ????wndClass.cbClsExtra?????=?0;??
  • ????wndClass.cbWndExtra?????=?0;??
  • ????wndClass.hInstance?=?hInstance;?????????????//指定包含窗口過程的程序的實例句柄。??
  • ????wndClass.hIcon=(HICON)::LoadImage(NULL,_T("GameMedia\\icon.ico"),IMAGE_ICON,0,0,LR_DEFAULTSIZE|LR_LOADFROMFILE);?//從全局的::LoadImage函數從本地加載自定義ico圖標??
  • ????wndClass.hCursor?=?LoadCursor(?NULL,?IDC_ARROW?);????//指定窗口類的光標句柄。??
  • ????wndClass.hbrBackground=(HBRUSH)GetStockObject(GRAY_BRUSH);??//為hbrBackground成員指定一個灰色畫刷句柄??
  • ????wndClass.lpszMenuName?=?NULL;???????????????????????//用一個以空終止的字符串,指定菜單資源的名字。??
  • ????wndClass.lpszClassName?=?_T("ForTheDreamOfGameDevelop");????????//用一個以空終止的字符串,指定窗口類的名字。??
  • ??
  • ????if(?!RegisterClassEx(?&wndClass?)?)?????????????//設計完窗口后,需要對窗口類進行注冊,這樣才能創建該類型的窗口??
  • ????????return?-1;????????
  • ??
  • ????HWND?hwnd?=?CreateWindow(?_T("ForTheDreamOfGameDevelop"),WINDOW_TITLE,??????????//喜聞樂見的創建窗口函數CreateWindow??
  • ????????WS_OVERLAPPEDWINDOW,?CW_USEDEFAULT,?CW_USEDEFAULT,?SCREEN_WIDTH,??
  • ????????SCREEN_HEIGHT,?NULL,?NULL,?hInstance,?NULL?);??
  • ??
  • ??
  • ????//Direct3D資源的初始化,調用失敗用messagebox予以顯示??
  • ????if?(!(S_OK==Direct3D_Init?(hwnd,hInstance)))??
  • ????{??
  • ????????MessageBox(hwnd,?_T("Direct3D初始化失敗~!"),?_T("淺墨的消息窗口"),?0);?//使用MessageBox函數,創建一個消息窗口???
  • ????}??
  • ????PlaySound(L"GameMedia\\NightElf1.wav",?NULL,?SND_FILENAME?|?SND_ASYNC|SND_LOOP);???//循環播放背景音樂??
  • ??
  • ??????
  • ??
  • ????MoveWindow(hwnd,200,10,SCREEN_WIDTH,SCREEN_HEIGHT,true);???//調整窗口顯示時的位置,窗口左上角位于屏幕坐標(200,0)處??
  • ????ShowWindow(?hwnd,?nShowCmd?);????//調用Win32函數ShowWindow來顯示窗口??
  • ????UpdateWindow(hwnd);??//對窗口進行更新,就像我們買了新房子要裝修一樣??
  • ??
  • ????//進行DirectInput類的初始化??
  • ????g_pDInput?=?new?DInputClass();??
  • ????g_pDInput->Init(hwnd,hInstance,DISCL_FOREGROUND?|?DISCL_NONEXCLUSIVE,DISCL_FOREGROUND?|?DISCL_NONEXCLUSIVE);??
  • ??
  • ????//消息循環過程??
  • ????MSG?msg?=?{?0?};??//初始化msg??
  • ????while(?msg.message?!=?WM_QUIT?)?????????//使用while循環??
  • ????{??
  • ????????static?FLOAT?fLastTime??=?(float)::timeGetTime();??
  • ????????static?FLOAT?fCurrTime??=?(float)::timeGetTime();??
  • ????????static?FLOAT?fTimeDelta?=?0.0f;??
  • ????????fCurrTime??=?(float)::timeGetTime();??
  • ????????fTimeDelta?=?(fCurrTime?-?fLastTime)?/?1000.0f;??
  • ????????fLastTime??=?fCurrTime;??
  • ??
  • ????????if(?PeekMessage(?&msg,?0,?0,?0,?PM_REMOVE?)?)???//查看應用程序消息隊列,有消息時將隊列中的消息派發出去。??
  • ????????{??
  • ????????????TranslateMessage(?&msg?);???????//將虛擬鍵消息轉換為字符消息??
  • ????????????DispatchMessage(?&msg?);????????//該函數分發一個消息給窗口程序。??
  • ????????}??
  • ????????else??
  • ????????{??
  • ????????????Direct3D_Update(hwnd,fTimeDelta);?????????//調用更新函數,進行畫面的更新??
  • ????????????Direct3D_Render(hwnd,fTimeDelta);???????????//調用渲染函數,進行畫面的渲染??????????????
  • ????????}??
  • ????}??
  • ??
  • ????UnregisterClass(_T("ForTheDreamOfGameDevelop"),?wndClass.hInstance);??
  • ????return?0;????
  • }??
  • ??
  • ??
  • ??
  • //*****************************************************************************************??
  • //?Name:?WndProc()??
  • //?Desc:?對窗口消息進行處理??
  • //*****************************************************************************************??
  • LRESULT?CALLBACK?WndProc(?HWND?hwnd,?UINT?message,?WPARAM?wParam,?LPARAM?lParam?)???//窗口過程函數WndProc??
  • {??
  • ????switch(?message?)???????????????//switch語句開始??
  • ????{??
  • ????case?WM_PAINT:???????????????????//?客戶區重繪消息??
  • ????????Direct3D_Render(hwnd,0.0f);??????????//調用Direct3D_Render函數,進行畫面的繪制??
  • ????????ValidateRect(hwnd,?NULL);???//?更新客戶區的顯示??
  • ????????break;??????????????????????????????????//跳出該switch語句??
  • ??
  • ????case?WM_KEYDOWN:????????????????//?鍵盤按下消息??
  • ????????if?(wParam?==?VK_ESCAPE)????//?ESC鍵??
  • ????????????DestroyWindow(hwnd);????//?銷毀窗口,?并發送一條WM_DESTROY消息??
  • ????????break;??
  • ????case?WM_DESTROY:????????????????//窗口銷毀消息??
  • ????????Direct3D_CleanUp();?????//調用Direct3D_CleanUp函數,清理COM接口對象??
  • ????????PostQuitMessage(?0?);???????//向系統表明有個線程有終止請求。用來響應WM_DESTROY消息??
  • ????????break;??????????????????????//跳出該switch語句??
  • ??
  • ????default:????????????????????????//若上述case條件都不符合,則執行該default語句??
  • ????????return?DefWindowProc(?hwnd,?message,?wParam,?lParam?);??????//調用缺省的窗口過程來為應用程序沒有處理的窗口消息提供缺省的處理。??
  • ????}??
  • ??
  • ????return?0;???????????????????//正常退出??
  • }??
  • ??
  • ??
  • //*****************************************************************************************??
  • //?Name:?Direct3D_Init(?)??
  • //?Desc:?初始化Direct3D??
  • //?Point:【Direct3D初始化四步曲】??
  • //??????1.初始化四步曲之一,創建Direct3D接口對象??
  • //??????2.初始化四步曲之二,獲取硬件設備信息??
  • //??????3.初始化四步曲之三,填充結構體??
  • //??????4.初始化四步曲之四,創建Direct3D設備接口??
  • //*****************************************************************************************??
  • ??
  • HRESULT?Direct3D_Init(HWND?hwnd,HINSTANCE?hInstance)??
  • {??
  • ??
  • ????//--------------------------------------------------------------------------------------??
  • ????//?【Direct3D初始化四步曲之一,創接口】:創建Direct3D接口對象,?以便用該Direct3D對象創建Direct3D設備對象??
  • ????//--------------------------------------------------------------------------------------??
  • ????LPDIRECT3D9??pD3D?=?NULL;?//Direct3D接口對象的創建??
  • ????if(?NULL?==?(?pD3D?=?Direct3DCreate9(?D3D_SDK_VERSION?)?)?)?//初始化Direct3D接口對象,并進行DirectX版本協商??
  • ????????????return?E_FAIL;??
  • ??
  • ????//--------------------------------------------------------------------------------------??
  • ????//?【Direct3D初始化四步曲之二,取信息】:獲取硬件設備信息??
  • ????//--------------------------------------------------------------------------------------??
  • ????D3DCAPS9?caps;?int?vp?=?0;??
  • ????if(?FAILED(?pD3D->GetDeviceCaps(?D3DADAPTER_DEFAULT,?D3DDEVTYPE_HAL,?&caps?)?)?)??
  • ????????{??
  • ????????????return?E_FAIL;??
  • ????????}??
  • ????if(?caps.DevCaps?&?D3DDEVCAPS_HWTRANSFORMANDLIGHT?)??
  • ????????vp?=?D3DCREATE_HARDWARE_VERTEXPROCESSING;???//支持硬件頂點運算,我們就采用硬件頂點運算,妥妥的??
  • ????else??
  • ????????vp?=?D3DCREATE_SOFTWARE_VERTEXPROCESSING;?//不支持硬件頂點運算,無奈只好采用軟件頂點運算??
  • ??
  • ????//--------------------------------------------------------------------------------------??
  • ????//?【Direct3D初始化四步曲之三,填內容】:填充D3DPRESENT_PARAMETERS結構體??
  • ????//--------------------------------------------------------------------------------------??
  • ????D3DPRESENT_PARAMETERS?d3dpp;???
  • ????ZeroMemory(&d3dpp,?sizeof(d3dpp));??
  • ????d3dpp.BackBufferWidth????????????=?SCREEN_WIDTH;??
  • ????d3dpp.BackBufferHeight???????????=?SCREEN_HEIGHT;??
  • ????d3dpp.BackBufferFormat???????????=?D3DFMT_A8R8G8B8;??
  • ????d3dpp.BackBufferCount????????????=?2;??
  • ????d3dpp.MultiSampleType????????????=?D3DMULTISAMPLE_NONE;??
  • ????d3dpp.MultiSampleQuality?????????=?0;??
  • ????d3dpp.SwapEffect?????????????????=?D3DSWAPEFFECT_DISCARD;???
  • ????d3dpp.hDeviceWindow??????????????=?hwnd;??
  • ????d3dpp.Windowed???????????????????=?true;??
  • ????d3dpp.EnableAutoDepthStencil?????=?true;???
  • ????d3dpp.AutoDepthStencilFormat?????=?D3DFMT_D24S8;??
  • ????d3dpp.Flags??????????????????????=?0;??
  • ????d3dpp.FullScreen_RefreshRateInHz?=?0;??
  • ????d3dpp.PresentationInterval???????=?D3DPRESENT_INTERVAL_IMMEDIATE;??
  • ??
  • ????//--------------------------------------------------------------------------------------??
  • ????//?【Direct3D初始化四步曲之四,創設備】:創建Direct3D設備接口??
  • ????//--------------------------------------------------------------------------------------??
  • ????if(FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT,?D3DDEVTYPE_HAL,???
  • ????????hwnd,?vp,?&d3dpp,?&g_pd3dDevice)))??
  • ????????return?E_FAIL;??
  • ??
  • ??
  • ????//獲取顯卡信息到g_strAdapterName中,并在顯卡名稱之前加上“當前顯卡型號:”字符串??
  • ?????wchar_t?TempName[60]=L"當前顯卡型號:";???//定義一個臨時字符串,且方便了把"當前顯卡型號:"字符串引入我們的目的字符串中??
  • ?????D3DADAPTER_IDENTIFIER9?Adapter;??//定義一個D3DADAPTER_IDENTIFIER9結構體,用于存儲顯卡信息??
  • ?????pD3D->GetAdapterIdentifier(0,0,&Adapter);//調用GetAdapterIdentifier,獲取顯卡信息??
  • ?????int?len?=?MultiByteToWideChar(CP_ACP,0,?Adapter.Description,?-1,?NULL,?0);//顯卡名稱現在已經在Adapter.Description中了,但是其為char類型,我們要將其轉為wchar_t類型??
  • ?????MultiByteToWideChar(CP_ACP,?0,?Adapter.Description,?-1,?g_strAdapterName,?len);//這步操作完成后,g_strAdapterName中就為當前我們的顯卡類型名的wchar_t型字符串了??
  • ?????wcscat_s(TempName,g_strAdapterName);//把當前我們的顯卡名加到“當前顯卡型號:”字符串后面,結果存在TempName中??
  • ?????wcscpy_s(g_strAdapterName,TempName);//把TempName中的結果拷貝到全局變量g_strAdapterName中,大功告成~??
  • ??
  • ????if(!(S_OK==Objects_Init()))?return?E_FAIL;??
  • ??
  • ????SAFE_RELEASE(pD3D)?//LPDIRECT3D9接口對象的使命完成,我們將其釋放掉??
  • ??
  • ??
  • ??
  • ????return?S_OK;??
  • }??
  • ??
  • ??
  • HRESULT?Objects_Init()??
  • {??
  • ????//創建字體??
  • ????D3DXCreateFont(g_pd3dDevice,?36,?0,?0,?1000,?false,?DEFAULT_CHARSET,???
  • ????????OUT_DEFAULT_PRECIS,?DEFAULT_QUALITY,?0,?_T("Calibri"),?&g_pTextFPS);??
  • ????D3DXCreateFont(g_pd3dDevice,?20,?0,?1000,?0,?false,?DEFAULT_CHARSET,???
  • ????????OUT_DEFAULT_PRECIS,?DEFAULT_QUALITY,?0,?L"華文中宋",?&g_pTextAdaperName);???
  • ????D3DXCreateFont(g_pd3dDevice,?23,?0,?1000,?0,?false,?DEFAULT_CHARSET,???
  • ????????OUT_DEFAULT_PRECIS,?DEFAULT_QUALITY,?0,?L"微軟雅黑",?&g_pTextHelper);???
  • ????D3DXCreateFont(g_pd3dDevice,?26,?0,?1000,?0,?false,?DEFAULT_CHARSET,???
  • ????????OUT_DEFAULT_PRECIS,?DEFAULT_QUALITY,?0,?L"黑體",?&g_pTextInfor);???
  • ??
  • ??
  • ??
  • ????//?從X文件中加載網格數據??
  • ????LPD3DXBUFFER?pAdjBuffer??=?NULL;??
  • ????LPD3DXBUFFER?pMtrlBuffer?=?NULL;??
  • ??
  • ????D3DXLoadMeshFromX(L"angle.X",?D3DXMESH_MANAGED,?g_pd3dDevice,???
  • ????????&pAdjBuffer,?&pMtrlBuffer,?NULL,?&g_dwNumMtrls,?&g_pMesh);??
  • ????//?讀取材質和紋理數據??
  • ????D3DXMATERIAL?*pMtrls?=?(D3DXMATERIAL*)pMtrlBuffer->GetBufferPointer();?//創建一個D3DXMATERIAL結構體用于讀取材質和紋理信息??
  • ????g_pMaterials?=?new?D3DMATERIAL9[g_dwNumMtrls];??
  • ????g_pTextures??=?new?LPDIRECT3DTEXTURE9[g_dwNumMtrls];??
  • ????for?(DWORD?i=0;?i<g_dwNumMtrls;?i++)???
  • ????{??
  • ????????//獲取材質,并設置一下環境光的顏色值??
  • ????????g_pMaterials[i]?=?pMtrls[i].MatD3D;??
  • ????????g_pMaterials[i].Ambient?=?g_pMaterials[i].Diffuse;??
  • ??
  • ????????//創建一下紋理對象??
  • ????????g_pTextures[i]??=?NULL;??
  • ????????D3DXCreateTextureFromFileA(g_pd3dDevice,?pMtrls[i].pTextureFilename,?&g_pTextures[i]);??
  • ????}??
  • ????SAFE_RELEASE(pAdjBuffer)??
  • ????SAFE_RELEASE(pMtrlBuffer)??
  • ??
  • ??
  • ??
  • ????//創建柱子??
  • ????D3DXCreateCylinder(g_pd3dDevice,?280.0f,?10.0f,?3000.0f,?60,?60,??&g_cylinder,?0);??
  • ????g_MaterialCylinder.Ambient??=?D3DXCOLOR(1.0f,?0.0f,?0.0f,?1.0f);????
  • ????g_MaterialCylinder.Diffuse??=?D3DXCOLOR(1.0f,?0.0f,?0.0f,?1.0f);????
  • ????g_MaterialCylinder.Specular?=?D3DXCOLOR(0.5f,?0.0f,?0.3f,?0.3f);????
  • ????g_MaterialCylinder.Emissive?=?D3DXCOLOR(0.0f,?0.0f,?0.0f,?1.0f);??
  • ??
  • ????//?設置光照????
  • ????::ZeroMemory(&g_Light,?sizeof(g_Light));????
  • ????g_Light.Type??????????=?D3DLIGHT_DIRECTIONAL;????
  • ????g_Light.Ambient???????=?D3DXCOLOR(0.7f,?0.7f,?0.7f,?1.0f);????
  • ????g_Light.Diffuse???????=?D3DXCOLOR(1.0f,?1.0f,?1.0f,?1.0f);????
  • ????g_Light.Specular??????=?D3DXCOLOR(0.9f,?0.9f,?0.9f,?1.0f);????
  • ????g_Light.Direction?????=?D3DXVECTOR3(1.0f,?1.0f,?1.0f);????
  • ????g_pd3dDevice->SetLight(0,?&g_Light);????
  • ????g_pd3dDevice->LightEnable(0,?true);????
  • ????g_pd3dDevice->SetRenderState(D3DRS_NORMALIZENORMALS,?true);????
  • ????g_pd3dDevice->SetRenderState(D3DRS_SPECULARENABLE,?true);??
  • ??
  • ????//?創建并初始化虛擬攝像機??
  • ????g_pCamera?=?new?CameraClass(g_pd3dDevice);??
  • ????g_pCamera->SetCameraPosition(&D3DXVECTOR3(0.0f,?1400.0f,?-1800.0f));??//設置攝像機所在的位置??
  • ????g_pCamera->SetTargetPosition(&D3DXVECTOR3(0.0f,?1200.0f,?0.0f));??//設置目標觀察點所在的位置??
  • ????g_pCamera->SetViewMatrix();??//設置取景變換矩陣??
  • ????g_pCamera->SetProjMatrix();??//設置投影變換矩陣??
  • ??
  • ????//?創建并初始化地形??
  • ????g_pTerrain?=?new?TerrainClass(g_pd3dDevice);?????
  • ????g_pTerrain->LoadTerrainFromFile(L"GameMedia\\heighmap.raw",?L"GameMedia\\terrainstone.jpg");?????//從文件加載高度圖和紋理??
  • ????g_pTerrain->InitTerrain(200,?200,?60.0f,?8.0f);??//四個值分別是頂點行數,頂點列數,頂點間間距,縮放系數??
  • ??
  • ????//創建并初始化天空對象??
  • ????g_pSkyBox?=?new?SkyBoxClass(?g_pd3dDevice?);??
  • ????g_pSkyBox->LoadSkyTextureFromFile(L"GameMedia\\TropicalSunnyDayFront2048.png",L"GameMedia\\TropicalSunnyDayBack2048.png",L"GameMedia\\TropicalSunnyDayRight2048.png",L"GameMedia\\TropicalSunnyDayLeft2048.png",?L"GameMedia\\TropicalSunnyDayUp2048.png");//從文件加載前、后、左、右、頂面5個面的紋理圖??
  • ????g_pSkyBox->InitSkyBox(50000);??//設置天空盒的邊長??
  • ??
  • ????//創建并初始化雪花粒子系統??
  • ????g_pSnowParticles?=?new?SnowParticleClass(g_pd3dDevice);??
  • ????g_pSnowParticles->InitSnowParticle();??
  • ??
  • ??
  • ????return?S_OK;??
  • }??
  • ??
  • void????????????????Direct3D_Update(?HWND?hwnd,FLOAT?fTimeDelta)??
  • {??
  • ????//使用DirectInput類讀取數據??
  • ????g_pDInput->GetInput();??
  • ??
  • ????//?沿攝像機各分量移動視角??
  • ????if?(g_pDInput->IsKeyDown(DIK_A))??g_pCamera->MoveAlongRightVec(-3.0f);??
  • ????if?(g_pDInput->IsKeyDown(DIK_D))??g_pCamera->MoveAlongRightVec(?3.0f);??
  • ????if?(g_pDInput->IsKeyDown(DIK_W))?g_pCamera->MoveAlongLookVec(?3.0f);??
  • ????if?(g_pDInput->IsKeyDown(DIK_S))??g_pCamera->MoveAlongLookVec(-3.0f);??
  • ????if?(g_pDInput->IsKeyDown(DIK_R))??g_pCamera->MoveAlongUpVec(?3.0f);??
  • ????if?(g_pDInput->IsKeyDown(DIK_F))??g_pCamera->MoveAlongUpVec(-3.0f);??
  • ??
  • ????//沿攝像機各分量旋轉視角??
  • ????if?(g_pDInput->IsKeyDown(DIK_LEFT))??g_pCamera->RotationUpVec(-0.003f);??
  • ????if?(g_pDInput->IsKeyDown(DIK_RIGHT))??g_pCamera->RotationUpVec(?0.003f);??
  • ????if?(g_pDInput->IsKeyDown(DIK_UP))??g_pCamera->RotationRightVec(-0.003f);??
  • ????if?(g_pDInput->IsKeyDown(DIK_DOWN))??g_pCamera->RotationRightVec(?0.003f);??
  • ????if?(g_pDInput->IsKeyDown(DIK_Q))?g_pCamera->RotationLookVec(0.001f);??
  • ????if?(g_pDInput->IsKeyDown(DIK_E))?g_pCamera->RotationLookVec(?-0.001f);??
  • ??
  • ????//鼠標控制右向量和上向量的旋轉??
  • ????g_pCamera->RotationUpVec(g_pDInput->MouseDX()*?0.001f);??
  • ????g_pCamera->RotationRightVec(g_pDInput->MouseDY()?*?0.001f);??
  • ??
  • ????//鼠標滾輪控制觀察點收縮操作??
  • ????static?FLOAT?fPosZ=0.0f;??
  • ????fPosZ?+=?g_pDInput->MouseDZ()*0.03f;??
  • ??
  • ????//計算并設置取景變換矩陣??
  • ????D3DXMATRIX?matView;??
  • ????g_pCamera->CalculateViewMatrix(&matView);??
  • ????g_pd3dDevice->SetTransform(D3DTS_VIEW,?&matView);??
  • ??
  • ????//把正確的世界變換矩陣存到g_matWorld中??
  • ????D3DXMatrixTranslation(&g_matWorld,?0.0f,?0.0f,?fPosZ);??
  • ??
  • ??
  • ??
  • ????//以下這段代碼用于限制鼠標光標移動區域??
  • ????POINT?lt,rb;??
  • ????RECT?rect;??
  • ????GetClientRect(hwnd,&rect);??//取得窗口內部矩形??
  • ????//將矩形左上點坐標存入lt中??
  • ????lt.x?=?rect.left;??
  • ????lt.y?=?rect.top;??
  • ????//將矩形右下坐標存入rb中??
  • ????rb.x?=?rect.right;??
  • ????rb.y?=?rect.bottom;??
  • ????//將lt和rb的窗口坐標轉換為屏幕坐標??
  • ????ClientToScreen(hwnd,<);??
  • ????ClientToScreen(hwnd,&rb);??
  • ????//以屏幕坐標重新設定矩形區域??
  • ????rect.left?=?lt.x;??
  • ????rect.top?=?lt.y;??
  • ????rect.right?=?rb.x;??
  • ????rect.bottom?=?rb.y;??
  • ????//限制鼠標光標移動區域??
  • ????ClipCursor(&rect);??
  • ??
  • ????ShowCursor(false);??????//隱藏鼠標光標??
  • ??
  • }??
  • ??
  • ??
  • ??
  • //*****************************************************************************************??
  • //?Name:?Direct3D_Render()??
  • //?Desc:?進行圖形的渲染操作??
  • //?Point:【Direct3D渲染五步曲】??
  • //??????1.渲染五步曲之一,清屏操作??
  • //??????2.渲染五步曲之二,開始繪制??
  • //??????3.渲染五步曲之三,正式繪制??
  • //??????4.渲染五步曲之四,結束繪制??
  • //??????5.渲染五步曲之五,翻轉顯示??
  • //*****************************************************************************************??
  • ??
  • void?Direct3D_Render(HWND?hwnd,FLOAT?fTimeDelta)??
  • {??
  • ????//--------------------------------------------------------------------------------------??
  • ????//?【Direct3D渲染五步曲之一】:清屏操作??
  • ????//--------------------------------------------------------------------------------------??
  • ????g_pd3dDevice->Clear(0,?NULL,?D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,?D3DCOLOR_XRGB(100,?255,?255),?1.0f,?0);??
  • ??
  • ????//--------------------------------------------------------------------------------------??
  • ????//?【Direct3D渲染五步曲之二】:開始繪制??
  • ????//--------------------------------------------------------------------------------------??
  • ????g_pd3dDevice->BeginScene();?????????????????????//?開始繪制??
  • ??????
  • ????//--------------------------------------------------------------------------------------??
  • ????//?【Direct3D渲染五步曲之三】:正式繪制??
  • ????//--------------------------------------------------------------------------------------??
  • ??
  • ??
  • ??
  • ????//繪制人物??
  • ????D3DXMATRIX?mScal,mRot2,mTrans,mFinal;???//定義一些矩陣,準備對大黃蜂進行矩陣變換??
  • ????D3DXMatrixTranslation(&mTrans,50.0f,1200.0f,0.0f);??
  • ????D3DXMatrixScaling(&mScal,3.0f,3.0f,3.0f);??
  • ????mFinal=mScal*mTrans*g_matWorld;??
  • ????g_pd3dDevice->SetTransform(D3DTS_WORLD,?&mFinal);//設置模型的世界矩陣,為繪制做準備??
  • ????//?用一個for循環,進行模型的網格各個部分的繪制??
  • ????for?(DWORD?i?=?0;?i?<?g_dwNumMtrls;?i++)??
  • ????{??
  • ????????g_pd3dDevice->SetMaterial(&g_pMaterials[i]);??//設置此部分的材質??
  • ????????g_pd3dDevice->SetTexture(0,?g_pTextures[i]);//設置此部分的紋理??
  • ????????g_pMesh->DrawSubset(i);??//繪制此部分??
  • ????}??
  • ??
  • ??
  • ????//繪制柱子??
  • ????D3DXMATRIX?TransMatrix,?RotMatrix,?FinalMatrix;??
  • ????D3DXMatrixRotationX(&RotMatrix,?-D3DX_PI?*?0.5f);??
  • ????g_pd3dDevice->SetLight(0,?&g_Light);????
  • ????g_pd3dDevice->SetMaterial(&g_MaterialCylinder);??
  • ????g_pd3dDevice->SetTexture(0,?NULL);//設置此部分的紋理??
  • ????for(int?i?=?0;?i?<?4;?i++)??
  • ????{??
  • ????????D3DXMatrixTranslation(&TransMatrix,?-300.0f,?0.0f,?-350.0f?+?(i?*?500.0f));??
  • ????????FinalMatrix?=?RotMatrix?*?TransMatrix?;??
  • ????????g_pd3dDevice->SetTransform(D3DTS_WORLD,?&FinalMatrix);??
  • ????????g_cylinder->DrawSubset(0);??
  • ??
  • ????????D3DXMatrixTranslation(&TransMatrix,?300.0f,?0.0f,?-350.0f?+?(i?*?500.0f));??
  • ????????FinalMatrix?=?RotMatrix?*?TransMatrix?;??
  • ????????g_pd3dDevice->SetTransform(D3DTS_WORLD,?&FinalMatrix);??
  • ????????g_cylinder->DrawSubset(0);??
  • ????}??
  • ??
  • ??
  • ????//繪制地形??
  • ????g_pTerrain->RenderTerrain(&g_matWorld,?false);??//渲染地形,且第二個參數設為false,表示不渲染出地形的線框??
  • ??
  • ????//繪制天空??
  • ????D3DXMATRIX?matSky,matTransSky,matRotSky;??
  • ????D3DXMatrixTranslation(&matTransSky,0.0f,-12000.0f,0.0f);??
  • ????D3DXMatrixRotationY(&matRotSky,?-0.000005f*timeGetTime());???//旋轉天空網格,?簡單模擬云彩運動效果??
  • ????matSky=matTransSky*matRotSky;??
  • ????g_pSkyBox->RenderSkyBox(&matSky,?false);??
  • ??
  • ????//繪制雪花粒子系統??
  • ????g_pSnowParticles->UpdateSnowParticle(fTimeDelta);??
  • ????g_pSnowParticles->RenderSnowParticle();??
  • ??
  • ????//繪制文字信息??
  • ????HelpText_Render(hwnd);??
  • ??
  • ??
  • ????//--------------------------------------------------------------------------------------??
  • ????//?【Direct3D渲染五步曲之四】:結束繪制??
  • ????//--------------------------------------------------------------------------------------??
  • ????g_pd3dDevice->EndScene();???????????????????????//?結束繪制??
  • ????//--------------------------------------------------------------------------------------??
  • ????//?【Direct3D渲染五步曲之五】:顯示翻轉??
  • ????//--------------------------------------------------------------------------------------??
  • ????g_pd3dDevice->Present(NULL,?NULL,?NULL,?NULL);??//?翻轉與顯示??
  • ???????
  • }??
  • ??
  • ??
  • void?HelpText_Render(HWND?hwnd)??
  • {??
  • ????//定義一個矩形,用于獲取主窗口矩形??
  • ????RECT?formatRect;??
  • ????GetClientRect(hwnd,?&formatRect);??
  • ??
  • ????//在窗口右上角處,顯示每秒幀數??
  • ????formatRect.top?=?5;??
  • ????int?charCount?=?swprintf_s(g_strFPS,?20,?_T("FPS:%0.3f"),?Get_FPS()?);??
  • ????g_pTextFPS->DrawText(NULL,?g_strFPS,?charCount?,?&formatRect,?DT_TOP?|?DT_RIGHT,?D3DCOLOR_RGBA(0,239,136,255));??
  • ??
  • ????//顯示顯卡類型名??
  • ????g_pTextAdaperName->DrawText(NULL,g_strAdapterName,?-1,?&formatRect,???
  • ????????DT_TOP?|?DT_LEFT,?D3DXCOLOR(1.0f,?0.5f,?0.0f,?1.0f));??
  • ??
  • ????//?輸出幫助信息??
  • ????formatRect.left?=?0,formatRect.top?=?380;??
  • ????g_pTextInfor->DrawText(NULL,?L"控制說明:",?-1,?&formatRect,???
  • ????????DT_SINGLELINE?|?DT_NOCLIP?|?DT_LEFT,?D3DCOLOR_RGBA(235,123,230,255));??
  • ????formatRect.top?+=?35;??
  • ????g_pTextHelper->DrawText(NULL,?L"????W:向前飛翔?????S:向后飛翔?",?-1,?&formatRect,???
  • ????????DT_SINGLELINE?|?DT_NOCLIP?|?DT_LEFT,?D3DCOLOR_RGBA(255,200,0,255));??
  • ????formatRect.top?+=?25;??
  • ????g_pTextHelper->DrawText(NULL,?L"????A:向左飛翔?????D:向右飛翔",?-1,?&formatRect,???
  • ????????DT_SINGLELINE?|?DT_NOCLIP?|?DT_LEFT,?D3DCOLOR_RGBA(255,200,0,255));??
  • ????formatRect.top?+=?25;??
  • ????g_pTextHelper->DrawText(NULL,?L"????R:垂直向上飛翔?????F:垂直向下飛翔",?-1,?&formatRect,???
  • ????????DT_SINGLELINE?|?DT_NOCLIP?|?DT_LEFT,?D3DCOLOR_RGBA(255,200,0,255));??
  • ????formatRect.top?+=?25;??
  • ????g_pTextHelper->DrawText(NULL,?L"????Q:向左傾斜???????E:向右傾斜",?-1,?&formatRect,???
  • ????????DT_SINGLELINE?|?DT_NOCLIP?|?DT_LEFT,?D3DCOLOR_RGBA(255,200,0,255));??
  • ????formatRect.top?+=?25;??
  • ????g_pTextHelper->DrawText(NULL,?L"????上、下、左、右方向鍵、鼠標移動:視角變化?",?-1,?&formatRect,???
  • ????????DT_SINGLELINE?|?DT_NOCLIP?|?DT_LEFT,?D3DCOLOR_RGBA(255,200,0,255));??
  • ????formatRect.top?+=?25;??
  • ????g_pTextHelper->DrawText(NULL,?L"?????鼠標滾輪:人物模型Y軸方向移動",?-1,?&formatRect,???
  • ????????DT_SINGLELINE?|?DT_NOCLIP?|?DT_LEFT,?D3DCOLOR_RGBA(255,200,0,255));??
  • ????formatRect.top?+=?25;??
  • ????g_pTextHelper->DrawText(NULL,?L"????ESC鍵?:?退出程序",?-1,?&formatRect,???
  • ????????DT_SINGLELINE?|?DT_NOCLIP?|?DT_LEFT,?D3DCOLOR_RGBA(255,200,0,255));??
  • }??
  • ??
  • //*****************************************************************************************??
  • //?Name:Get_FPS()函數??
  • //?Desc:?用于計算幀速率??
  • //*****************************************************************************************??
  • float?Get_FPS()??
  • {??
  • ??
  • ????//定義四個靜態變量??
  • ????static?float??fps?=?0;?//我們需要計算的FPS值??
  • ????static?int????frameCount?=?0;//幀數??
  • ????static?float??currentTime?=0.0f;//當前時間??
  • ????static?float??lastTime?=?0.0f;//持續時間??
  • ??
  • ????frameCount++;//每調用一次Get_FPS()函數,幀數自增1??
  • ????currentTime?=?timeGetTime()*0.001f;//獲取系統時間,其中timeGetTime函數返回的是以毫秒為單位的系統時間,所以需要乘以0.001,得到單位為秒的時間??
  • ??
  • ????//如果當前時間減去持續時間大于了1秒鐘,就進行一次FPS的計算和持續時間的更新,并將幀數值清零??
  • ????if(currentTime?-?lastTime?>?1.0f)?//將時間控制在1秒鐘??
  • ????{??
  • ????????fps?=?(float)frameCount?/(currentTime?-?lastTime);//計算這1秒鐘的FPS值??
  • ????????lastTime?=?currentTime;?//將當前時間currentTime賦給持續時間lastTime,作為下一秒的基準時間??
  • ????????frameCount????=?0;//將本次幀數frameCount值清零??
  • ????}??
  • ??
  • ????return?fps;??
  • }??
  • ??
  • ??
  • ??
  • //*****************************************************************************************??
  • //?Name:?Direct3D_CleanUp()??
  • //?Desc:?對Direct3D的資源進行清理,釋放COM接口對象??
  • //*****************************************************************************************??
  • void?Direct3D_CleanUp()??
  • {??
  • ??
  • ????//釋放COM接口對象??
  • ????for?(DWORD?i?=?0;?i<g_dwNumMtrls;?i++)???
  • ????????SAFE_RELEASE(g_pTextures[i]);??
  • ????SAFE_DELETE(g_pTextures);???
  • ????SAFE_DELETE(g_pMaterials);???
  • ????SAFE_DELETE(g_pDInput);??
  • ????SAFE_RELEASE(g_cylinder);??
  • ????SAFE_RELEASE(g_pMesh);??
  • ????SAFE_RELEASE(g_pd3dDevice);??
  • ????SAFE_RELEASE(g_pTextAdaperName)??
  • ????SAFE_RELEASE(g_pTextHelper)??
  • ????SAFE_RELEASE(g_pTextInfor)??
  • ????SAFE_RELEASE(g_pTextFPS)??
  • ????SAFE_RELEASE(g_pd3dDevice)??
  • }??

  • ?

    ?

    學到目前為止,我們用學的知識寫出來的游戲場景程序已經比較炫了,一些運行截圖如下:

    ?

    ?

    我們操縱著攝像機在雪中飛行,那種雪花鋪面而來的感覺非常地舒服。

    ?

    仰望天空,任雪花飄落到“身上”:

    ?

    ?

    下面這張圖可以明顯看到雪花被我們規定了活動區域:

    ?

    冒著顯卡被燒的危險拍了一張10萬粒子數量時的“暴雪”畫面,大家看右上角的幀數,只有可憐的8幀了。。。。

    ?

    ?

    ?

    ?

    撲,一朵雪花砸臉上了。。。。

    ?

    ?

    大家如果覺得這雪花太大了,沒事,這是淺墨為了表現力故意調大了一點。自己去調一下雪花頂點緩存POINTVERTEX vertices數組的大小即可。

    ?

    我們可以發現,其實Direct3D的固定功能流水線學到目前,基礎知識也就那么多,頂點緩存,索引緩存,四大變換,紋理映射,網格,模板緩存等 等,把他們其中的幾個合理地組合在一起運用一下就是新的知識,這就衍生出了我們近期剛出的三篇文章中講到的地形,天空,粒子系統。以及還 沒講到的 公告板,拾取等等知識。

    轉載于:https://www.cnblogs.com/dandansang/p/6481149.html

    總結

    以上是生活随笔為你收集整理的三维粒子系统的实现的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。