#
找了很久的相關(guān)資料,關(guān)于水面渲染的還真不好找呢,突然發(fā)現(xiàn)了一個(gè)地方有介紹紋理動(dòng)畫,于是就試著做了做,效果還真是不錯(cuò)呢。

只是還沒有實(shí)現(xiàn)倒影,下次再做。
雖然大蝦很多,但像我這樣自己搗鼓的也同樣存在,那我就說(shuō)說(shuō)怎么實(shí)現(xiàn)的吧,也順便理清自己的思路
我說(shuō)說(shuō)我的實(shí)現(xiàn)方法吧
std::vector<IDirect3DTexture9 *> vecTexture(0); //這個(gè)就是用來(lái)存儲(chǔ)我們的幾十張紋理。
先把他們?nèi)考虞d進(jìn)去。
然后我們先畫一個(gè)矩形(略)
然后我們根據(jù)下面這個(gè)來(lái)動(dòng)態(tài)切換紋理
Direct3DTexture9* Texture = NULL;
float timeElapsed = 0;
DWORD dwFrameSpeed = 0;
timeElapsed += timeDelta*FrameSpeed;//timeDelta是兩次渲染的間隔時(shí)間
if(timeElapsed>vecTexture.size()) timeElapsed = 0;
Texture = vecTexture[(int)timeElapsed];
接下來(lái)我們就可以設(shè)置紋理,然后渲染那個(gè)矩形就可以了。
如果要使水呈透明效果,只要和地形進(jìn)行ALPHA混合就行了,混合參數(shù)自己多調(diào)兩下。
霧化效果

首先來(lái)看看我們可以設(shè)置哪些參數(shù)
1、D3DFOGSTART、D3DFOGEND表示霧的起始和結(jié)束距離
2、D3DFOGDENSITY 霧的濃度
3、D3DFOGCOLOR 霧的顏色
4、D3DFOGTABLEMODE、D3DFOGVERTEXMODE 霧的模式,第一個(gè)為像素霧化,第二個(gè)為頂點(diǎn)霧化
首先看看霧化的方程
Color = f * Color(scene) + (1-f) * color(fog)
Color(scene):背景色
Color(fog): 霧色
f:霧化參數(shù),隨觀察點(diǎn)的距離的增大而減小,從而可知最后得到的顏色,當(dāng)觀察點(diǎn)越遠(yuǎn)時(shí),霧色占的比例越大。
霧有四種方式
D3DFOG_NONE 禁用霧化效果
D3DFOG_EXP 霧化效果隨指數(shù)增加 f = 1/(e^density)
D3DFOG_EXP2 同上,不過(guò)公式變?yōu)?f = 1/(e^(density^2))
D3DFOG_LINEAR 線性霧 f = (end-d)/(end-start) d 為當(dāng)前計(jì)算點(diǎn)與觀察點(diǎn)距離
現(xiàn)在我們來(lái)看如何實(shí)現(xiàn)霧化
首先開啟霧化效果
Device->SetRenderState(D3DRS_FOGENABLE,true);
然后我們要設(shè)置霧化的模式和公式
Device->SetRenderState(DEDRS_FOGTABLEMODE,D3DFOG_LINEAR);
這里我將其設(shè)置成了像素霧和線性,同樣可以將其換成上面介紹的其它模式和公式
接下來(lái)我們就要設(shè)置霧化參數(shù)了
Device->SetRenderState(D3DRS_FOGCOLOR,oxffffffff);//設(shè)置成白色
設(shè)置start end
float start= 50,end = 400;
Device->SetRenderState(D3DRS_FOGSTART,*(DWORD*)&start);
Device->SetRenderState(D3DRS_FOGEND,*(DWORD*)&end);
設(shè)置濃度
float density = 0.001f;//0.0 -- 1.0
Device->SetRenderState(D3DRS_FOGDENSITY,*(DWORD*)&density);
這樣,我們的設(shè)置就完了,只要將霧化設(shè)置放入我們渲染場(chǎng)景中,就可以看到霧化效果了.
但應(yīng)該注意以下幾點(diǎn)
-----------------------------------------line
A B C
\ | /
\ /
\ | /
\ /
\ d /
\ /
\ | /
\ /
P
------------------------------------------
霧化效果是以剛剛上面講的 d 作為計(jì)算標(biāo)準(zhǔn),所以,我們從P點(diǎn)看到A ,B ,C三點(diǎn)的霧化效果是一樣的,而按常理,A ,C的霧應(yīng)該更濃才對(duì).
很顯然,這讓我們想到,D3D會(huì)有對(duì)應(yīng)的處理辦法.
D3D提供了基于發(fā)散的霧化效果,霧化隨觀察點(diǎn)的距離增大而增大,就像點(diǎn)光源,不過(guò),這要求我們的硬件支持,所以在設(shè)置前應(yīng)該檢查
D3DCAPS9 caps;
Device->GetDeviceCaps(&caps);
if(caps.RasterCaps&D3DPRASTERCAPS_FOGRANGE)
Device->SetRenderState(D3DRS_RANGEFOGENABLE,true);
把這個(gè)增加到霧化設(shè)置中即可~~~
已經(jīng)12點(diǎn)了,估計(jì)人有點(diǎn)暈,也講不明白些什么東西了,到此為止

加入了影子后的效果
渲染樹目紋理之前,進(jìn)行如下設(shè)置
Device->SetRenderState(D3DRS_ALPHABLENDENABLE,true);
Device->SetRenderState(D3DRS_SCRBLEND,D3DBLEND_SCRALPHA);
Device->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSCRALPHA);
Device->SetRenderState(D3DRS_ALPHATESTENABLE,true);
Device->SetRenderState(D3DRS_ALPHAREF,0x0);
Device->SetRenderState(D3DRS_ALPHAFUNC,D3DCMP_GREATEREQUAL);
渲染陰影的時(shí)候,使用的是同一紋理,但需進(jìn)行如下設(shè)置
Device->SetRenderState(D3DRS_SCRBLEND,D3DBLEND_INVSCRALPHA);
調(diào)了一下午,才調(diào)出這陰影,難得呀~~`

D3DMULTISAMPLE_0_SAMPLES

D3DMULTISAMPLE_4_SAMPLES
終于成功地把天空盒,公告板,MESH,紋理等一起用在了一個(gè)工程中,哈哈,雖然比較白啦,但還是很有成就感。
平面陰隱其實(shí)就是將物體“壓扁”到某一平面進(jìn)行繪制。原理類似于投影
而對(duì)于一個(gè)三維物體來(lái)說(shuō),當(dāng)多個(gè)部分投影到平面上時(shí),會(huì)產(chǎn)生疊加效果,導(dǎo)致某一部位顏色較深,而此時(shí)我們可以通過(guò)模版緩存來(lái)防止二次融合,從而避免這類現(xiàn)象的產(chǎn)生。
Device->Clear(0,0,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,0xfff0000,1.0,0);
Device->SetRenderState(D3DRS_STENCILENABLE,true);
Device->SetRenderState(D3DRS_STENCILFUNC,D3DCMP_EQUAL);
Device->SetRenderState(D3DRS_STENCILREF,0x0);
Device->SetRenderState(D3DRS_STENCILMASK,0xffffffff);
Device->SetRenderState(D3DRS_STENCILWRITEMASK,0xffffffff);
Device->SetRenderState(D3DRS_STENCILZFAIL,D3DSTENCILOP_KEEP);
Device->SetRenderState(D3DRS_STENCILFAIL,D3DSTENCILOP_KEEP);
Device->SetRenderState(D3DRS_STENCILPASS,D3DSTENCILOP_INCR);
首先開啟模版,將測(cè)試規(guī)則設(shè)置為"相等",模版參考設(shè)置為0,失敗時(shí)候不更改,成功的時(shí)候增加1.
由于我們已經(jīng)將模版緩存清0 ,于是,當(dāng)?shù)谝淮螌懭肽0娴臅r(shí)候,測(cè)試總是成功的,模版值加1.而當(dāng)?shù)诙螌懭氲臅r(shí)候,模版值與模版參考值不相等,測(cè)試便會(huì)失敗,從而阻止了再次寫入緩存.
Device->SetRenderState(D3DRS_ALPHABLENDENABLE,true);
Device->SetRenderState(D3DRS_SCRBLEND,D3DBLEND_SCRALPHA);
Device->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCAPHA);
Device->SetRenderState(D3DRS_ZENABLE,false);
//使用D3DXMatrixShadow(&S,&linghtDirection,&groundplane);
//S為最后輸出的矩陣,然后是光線方向,然后是要繪制陰影的平面
//繪制
//最后做收尾工作
Device->SetRenderState(D3DRS_ZENABLE,true);
Device->SetRenderState(D3DRS_ALPHABLENDENABLE,false);
Device->SetRenderState(D3DRS_STENCILENABLE,false);