#
找了很久的相关资料,关于水面渲染的还真不好找呢,突然发现了一个地方有介绍纹理动画,于是就试着做了做,效果还真是不错呢。

只是还没有实现倒影,下次再做。
虽然大虾很多,但像我这样自己捣鼓的也同样存在,那我就说说怎么实现的吧,也顺便理清自己的思路
我说说我的实现方法吧
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);