#
找了很久的相關資料,關于水面渲染的還真不好找呢,突然發現了一個地方有介紹紋理動畫,于是就試著做了做,效果還真是不錯呢。

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

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

加入了影子后的效果
渲染樹目紋理之前,進行如下設置
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);
渲染陰影的時候,使用的是同一紋理,但需進行如下設置
Device->SetRenderState(D3DRS_SCRBLEND,D3DBLEND_INVSCRALPHA);
調了一下午,才調出這陰影,難得呀~~`

D3DMULTISAMPLE_0_SAMPLES

D3DMULTISAMPLE_4_SAMPLES
終于成功地把天空盒,公告板,MESH,紋理等一起用在了一個工程中,哈哈,雖然比較白啦,但還是很有成就感。
平面陰隱其實就是將物體“壓扁”到某一平面進行繪制。原理類似于投影
而對于一個三維物體來說,當多個部分投影到平面上時,會產生疊加效果,導致某一部位顏色較深,而此時我們可以通過模版緩存來防止二次融合,從而避免這類現象的產生。
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);
首先開啟模版,將測試規則設置為"相等",模版參考設置為0,失敗時候不更改,成功的時候增加1.
由于我們已經將模版緩存清0 ,于是,當第一次寫入模版的時候,測試總是成功的,模版值加1.而當第二次寫入的時候,模版值與模版參考值不相等,測試便會失敗,從而阻止了再次寫入緩存.
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);