溫故知新,水面很早就實現了,但沒有在這里寫過,今天總結一下。
水的模擬要達到以下效果:水面的折射與反射,水的波動。
要達到這種效果,需要以下四張紋理:折射紋理(RenderTarget),反射紋理(RenderTarget),Bumpmap,水自己的紋理。
折射與反射的原理就不具體說了,下面只說實現步驟。
一、渲染到紋理
RenderTarget的創建我不多述了,網上查查,我創建的是256X256的紋理,格式為X8R8G8B8。折射紋理比較簡單,直接把當前的地形或在水面以下的物體渲染多次,注意,為提高性能,在這次pass中,可以選擇帶clip的shader(假如用到shader)或者直接使用水面的平面作為一個clipplane(不使用Shader)。
然后是反射的實現,首先生成一個以水面為反射面的反射矩陣,攝像機的坐標乘與反射矩陣求得新的坐標。然后按渲染流程再走一次,(即計算裁剪空間,加入渲染對列,到最后渲染)。渲染到紋理后,注意,此時的紋理U坐標應該做一個反轉操作。如果在shader中修改,必須比較簡單就是u = 1.0 - uvCoord.x。
二、水的波動
需要利用一個Bumpmap做作紋理UV值的偏移,下面是HLSL的代碼:
float2 BumpUVCoords = input.uvCoords;
BumpUVCoords.x += time;
BumpUVCoords.y -= time;
float4 dudv_offset = tex2D(BumpMap, BumpUVCoords);//primary_motion + secondary_motion); //, 0.0001, 0.9999)); // + secondary_motion);
float2 offsets = (2 * dudv_offset.xy - 1) * 0.1;
//這里的clamp是多余的,明天試試去掉
float2 lastCoords = input.uvCoords + offsets; //clamp(input.uvCoords + offsets, 0.00, 4.00);//offsets; //, 0.00, 1.00);
float2 waterUV = input.uvCoords;
waterUV.x += time;
waterUV.y -= time;
float4 colorWater = tex2D(Samp0, waterUV);
output.Color = colorWater;
clamp(input.outTexProj, 0.0, 1.0);
float2 texProj = input.outTexProj.xy / input.outTexProj.w;
texProj.x = 1.0 - texProj.x;
lastCoords = clamp(texProj + offsets, 0.0, 1.0);
截圖:
