unity3d 制造自己的水体water effect(二)
2015-09-14 07:58
579 查看
前篇:unity3d制造自己的水体watereffect(一)
曲面细分:Unity3d使用DX11的曲面细分
PBR:
讲求基本算法
plus篇
之前一直在用unity4.6写shader,终于下定决心换unity5,然后发现,unity5的渲染比4强太多,
这次完成之前2月份自制拖着没解决的normal问题,算出normal真的很简单。
本次水体分别使用两种波动算法,一个是ShaderX6中Szecsi和Arman的算法,另一个是Gpugems1里的Gerstner波算法。然后再用PBR渲染。然后还是曲面细分。
这次的效果:
求波动速度,λ为波长,波长就是波峰到波峰之间的距离,速度v为每秒钟波峰移动的距离。
然后是相函数,k为波动方向,运动方向,垂直于波阵面的水平方向,p为position,t为时间(_Time.y)
求得一个波的位移S,a为振幅,振幅就是从水平面到波峰的高度。
最终我们的水是多个波组合在一起的,所以最终结果为:
博主整共合了4个波
关键代码如下:
vv=sqrt(_G*_Lambda/(2*_PIE));
psi=2*_PIE/_Lambda*(dot(v.vertex.xyz,_K.xyz)+vv*_Time.y);
s=lerp(-cos(psi),sin(psi),_A)*0.05;
p.y+=s;
vv=sqrt(_G*_Lambda2/(2*_PIE));
psi=2*_PIE/_Lambda2*(dot(v.vertex.xyz,_K2.xyz)+vv*_Time.y);
s=lerp(-cos(psi),sin(psi),_A2)*0.05;
p.y+=s;
vv=sqrt(_G*_Lambda3/(2*_PIE));
psi=2*_PIE/_Lambda3*(dot(v.vertex.xyz,_K3.xyz)+vv*_Time.y);
s=lerp(-cos(psi),sin(psi),_A3)*0.1;
p.y+=s;
vv=sqrt(_G*_Lambda4/(2*_PIE));
psi=2*_PIE/_Lambda4*(dot(v.vertex.xyz,_K4.xyz)+vv*_Time.y);
s=lerp(-cos(psi),sin(psi),_A4)*0.1;
p.y+=s;
v.vertex.xyz=p.xyz;</span>
产生了波动效果:
加上之前的pbr,可以模拟各种液体
牛奶
血,等等
但是由于曲面细分,离近了看水面上还是有小面的细节,这点有待解决。
关键代码如下:
floatwave(floatx,floatz,floattimer)
{
floaty=0;
floatoct=_OCT;
floatfac=_FAC;
floatd=sqrt(x*x+z*z);//length(float2(x,z));
for(oct;oct>0;oct--)
{
y-=fac*cos(timer*_SP+(1/fac)*x*z*_WS);
fac/=2;
}
return2*_VS*d*y;
}</span>
曲面细分带来的小面不是很明显,而且面不用分得很细就能看到平滑的效果
Normal的生成有复杂的和简单的,但本质上都是求偏导。
先看复杂的,来自GPUGems1的42章
首先求出Jacobian
举个例子(直接截图了^_^):
是不是很麻烦。。
法线本质上的求法就是这样的,但是,我们有函数:ddx,ddy这两个神器
我们只需要求出世界坐标点,worldpos
就可以简单地求出法线:
N=cross(ddx(worldpos),ddy(worldpos))
方法很简单,不过别忘记,本质上还是上面的一大串。。。
切记:ddx,ddy只能在fragmentshader中使用。
只有漫反射的水体如下:
--------bywolf96、
曲面细分:
PBR:
讲求基本算法
Unity3d基于物理渲染Physically-BasedRendering之specularBRDF
plus篇
Unity3d基于物理渲染Physically-BasedRendering之实现 最终篇
Unity3d基于物理渲染Physically-BasedRendering之最终篇
之前一直在用unity4.6写shader,终于下定决心换unity5,然后发现,unity5的渲染比4强太多,
这次完成之前2月份自制拖着没解决的normal问题,算出normal真的很简单。
本次水体分别使用两种波动算法,一个是ShaderX6中Szecsi和Arman的算法,另一个是Gpugems1里的Gerstner波算法。然后再用PBR渲染。然后还是曲面细分。
这次的效果:
Szecsi&Arman波动算法
首先来看ShaderX6中的波动算法:求波动速度,λ为波长,波长就是波峰到波峰之间的距离,速度v为每秒钟波峰移动的距离。
然后是相函数,k为波动方向,运动方向,垂直于波阵面的水平方向,p为position,t为时间(_Time.y)
求得一个波的位移S,a为振幅,振幅就是从水平面到波峰的高度。
最终我们的水是多个波组合在一起的,所以最终结果为:
博主整共合了4个波
关键代码如下:
psi=2*_PIE/_Lambda*(dot(v.vertex.xyz,_K.xyz)+vv*_Time.y);
s=lerp(-cos(psi),sin(psi),_A)*0.05;
p.y+=s;
vv=sqrt(_G*_Lambda2/(2*_PIE));
psi=2*_PIE/_Lambda2*(dot(v.vertex.xyz,_K2.xyz)+vv*_Time.y);
s=lerp(-cos(psi),sin(psi),_A2)*0.05;
p.y+=s;
vv=sqrt(_G*_Lambda3/(2*_PIE));
psi=2*_PIE/_Lambda3*(dot(v.vertex.xyz,_K3.xyz)+vv*_Time.y);
s=lerp(-cos(psi),sin(psi),_A3)*0.1;
p.y+=s;
vv=sqrt(_G*_Lambda4/(2*_PIE));
psi=2*_PIE/_Lambda4*(dot(v.vertex.xyz,_K4.xyz)+vv*_Time.y);
s=lerp(-cos(psi),sin(psi),_A4)*0.1;
p.y+=s;
v.vertex.xyz=p.xyz;</span>
产生了波动效果:
加上之前的pbr,可以模拟各种液体
牛奶
血,等等
但是由于曲面细分,离近了看水面上还是有小面的细节,这点有待解决。
Gerstner波
然后Gerstner波关键代码如下:
{
floaty=0;
floatoct=_OCT;
floatfac=_FAC;
floatd=sqrt(x*x+z*z);//length(float2(x,z));
for(oct;oct>0;oct--)
{
y-=fac*cos(timer*_SP+(1/fac)*x*z*_WS);
fac/=2;
}
return2*_VS*d*y;
}</span>
曲面细分带来的小面不是很明显,而且面不用分得很细就能看到平滑的效果
normal的生成
最后我们讲讲normal的生成,Normal的生成有复杂的和简单的,但本质上都是求偏导。
先看复杂的,来自GPUGems1的42章
首先求出Jacobian
举个例子(直接截图了^_^):
是不是很麻烦。。
法线本质上的求法就是这样的,但是,我们有函数:ddx,ddy这两个神器
我们只需要求出世界坐标点,worldpos
就可以简单地求出法线:
N=cross(ddx(worldpos),ddy(worldpos))
方法很简单,不过别忘记,本质上还是上面的一大串。。。
切记:ddx,ddy只能在fragmentshader中使用。
只有漫反射的水体如下:
--------bywolf96、
相关文章推荐
- unity3d 制造自己的水体water effect(二)
- unity两点之间抛物线,完美金手指
- unity发射弓箭轨迹的实现
- Unity3D笔记第十三天——关节、布料
- Unity3D笔记第十二天——鼠标事件、物理类、射线
- Unity3D笔记第十一天——碰撞器
- Unity Web Player修改加载页面的LOGO
- Unity中 yield return 1 的误区
- 宠物跟随效果
- unity 显示帧率
- 如何用unity发布Android程序APK
- unity3d简单的相机跟随及视野旋转缩放
- Unity T4M
- Unity 3D 泰课网小球移动 相机跟随
- 【Unity3D技巧】一个简单的Unity-UI框架的实现
- 用鼠标控制角色移动
- unity Test Tools 测试
- [Unity3D]Unity3D游戏开发Lua随着游戏的债券(在)
- Unity使用 ShareSDK 分享Android篇
- Untiy3D笔记之番外篇——Unity3D的四种坐标系