找回密码
 立即注册
查看: 12258|回复: 100

[特效Shader] Unity3D中实现常见的水面效果教程

  [复制链接]
发表于 2012-12-30 21:49 | 显示全部楼层 |阅读模式
资源信息 Tutorial Information
教程名称: Unity3D中实现常见的水面效果教程(发帖教程)
适用引擎:   (适用引擎,为空默认为Unity)
教程语种: 中文
教程等级: 1
教程格式: 图文(请用IE9以上浏览器访问本版块)
教程作者: 转载自互联网 (如有问题请短消息联系作者或发表回复)
下载地址: (兑换积分)
点击查看原图
美丽分割线


一 bump

float4 temp;

temp.xyzw = v.vertex.xzxz * _WaveScale4 / unity_Scale.w + _WaveOffset;

o.bumpuv0 = temp.xy;

o.bumpuv1 = temp.wz;

首先明确unity_Scale.w的含义,个人理解为当前模型的缩放值。

w = 1 / uniform scale.

uniform float4 unity_Scale : xyz components unused; .w contains scale for uniformly scaled objects.

先排除_WaveScale4和WaveOffset因素,就是直接把plane的各点局部坐标在乘系数当成uv坐标。然后用_WaveScale4去放缩,用WaveOffset去滚动。

Vector4 waveSpeed = mat.GetVector( "WaveSpeed" );
float waveScale = mat.GetFloat( "_WaveScale" );
Vector4 waveScale4 = new Vector4(waveScale, waveScale, waveScale * 0.4f, waveScale * 0.45f);

double t = Time.timeSinceLevelLoad / 20.0;

//此帧开始的时间(只读)。这是以秒计算到最后的关卡已经加载完的时间。也就是说,从最后加载的关卡到现在所用的时间。

Vector4 offsetClamped = new Vector4(
  (float)System.Math.IEEERemainder(waveSpeed.x * waveScale4.x * t, 1.0),
  (float)System.Math.IEEERemainder(waveSpeed.y * waveScale4.y * t, 1.0),
  (float)System.Math.IEEERemainder(waveSpeed.z * waveScale4.z * t, 1.0),
  (float)System.Math.IEEERemainder(waveSpeed.w * waveScale4.w * t, 1.0)
);
//IEEERemainder返回一指定数字被另一指定数字相除的余数。
//这里这么处理好像是让生成的数据符合ieee规范还是什么,希望有懂的人能告诉我一下。

更多延伸link

mat.SetVector( "_WaveOffset", offsetClamped );
mat.SetVector( "_WaveScale4", waveScale4 );

//这样生成的波形看上去结果还不错,就先用着了。



二 fresnel

对水面来说,当观察者和水面的角度越小时,反射效果越明显,角度越大时,折射效果越明显,称为菲捏尔效果。所以需要根据观察者的角度来计算反射,折射帖图,以及水面颜色的混合方式。物理上正确的菲捏尔向计算比较复杂,通常使用近似的计算方法。



1,最高效的是假设水的颜色只与水面高度和观察者角度有关。
half fresnelTerm = saturate(dot( eyeVector,normal));
finalColor  = lerp(reflectiveColor, refractiveColor,fresnelTerm);



2,在某个demo中看到的方法,也是我一直在用的。
R=normalize(eyepos-worldpos);
fastFresnel = R + ( 1.0f-R ) * pow ( 1.0 – dot ( eyeVector, normal ), 5.0);
finalColor = waterColor * lerp(reflectiveColor, refractiveColor,fastFresnel )+ sunlight;



3,u3d中的方法,大致上差不多,用了texture去模拟Fresnel,效果更多样一些。

o.viewDir.xzy = ObjSpaceViewDir(v.vertex);
//得到当前观察方向的向量
//这里用了u3d封装的函数去得到观察方向,不象我们在世界空间中,而是在观察空间中。
// Computes object space view direction

inline float3 ObjSpaceViewDir( in float4 v )
{

float3 objSpaceCameraPos = mul(_World2Object, float4

(_WorldSpaceCameraPos.xyz, 1)).xyz * unity_Scale.w;

return objSpaceCameraPos - v.xyz
;
}
//float4x4 _World2Object 为 Inverse of current world matrix
//float3 _WorldSpaceCameraPos 为 World space position of the camera



half fresnelFac = dot( i.viewDir, bump );






//水平线表示水面。指向上方的向量是像素的法线向量。另一个向量叫做eyeVector,是从相机指向像素的向量。法线向量上的绿色长度表示当前像素的反射量,红色表示折射量。
//那么我们如何找到绿色和红色线段的长度?我们需要将eyevector投影到法线向量上,这可以通过点乘做到:当你点乘eyeVector和法线后就会获得红色线段的长度。而绿色线段长度等于(1- 红色线段长度)。


//这时我们返回fresnelFac





half fresnel = tex2D( _Fresnel, float2(fresnelFac,fresnelFac) ).a;

//根据折射量去采样

//这时我们返回fresnel



uv1.xy += bump * _ReflDistort;
uv2.xy -= bump * _RefrDistort
//反射和折射的扭曲分开处理。

color = lerp( refr, refl, fresnel );
//到这一个基本的水效果就完成了。



//最后开启雾效

//这里我很倒霉,不清楚为什么u3d的fog在观察相机x 轴角度等于0时,用rtt得到的结果是错的。而我一直用0的条件在找错,浪费了大半天的时间。同时还发现个办法就是创建2个同样的cam,这样即使是0,rtt的结果也是正确的。







三 underWater

关于水下u3d自带的思路只是实现了一个blur,如果想在水下正确的看到水上,需要自己修改下refr的实现。

然后就是投影散焦图片序列,u3d自带了个组件,不用自己在写shader。GodRays效果看到也有预置,接下来准备都实际测试一下。



PS: 现在有很多插件已经支持水面效果 这里只做参考

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×

评分

参与人数 4鲜花 +3 +1 收起 理由
peterchang1211 + 1 淡定
没事儿瞎蹦跶 + 1 神马都是浮云
yugo215 + 1 赞一个!
graywolfx21 + 1 很给力!

查看全部评分

发表于 2013-6-18 16:12 | 显示全部楼层
没有工程文件么
发表于 2013-9-15 10:44 | 显示全部楼层

感谢楼主的无私分享!{:soso__11402694654016840197_7:}
发表于 2013-9-17 16:32 | 显示全部楼层

感谢楼主的无私分享!{:soso__11402694654016840197_7:}
发表于 2013-11-25 16:47 | 显示全部楼层
感谢楼主   分享很好的教程   
发表于 2013-12-2 10:25 | 显示全部楼层
kankan                                 
发表于 2014-2-28 18:03 | 显示全部楼层

感谢楼主的无私分享!{:soso__11402694654016840197_7:}
发表于 2014-3-6 10:51 | 显示全部楼层
谢谢你的分享!
发表于 2014-5-16 09:03 | 显示全部楼层
我完全看不懂,感觉很牛逼的样子{:5_397:}
发表于 2014-5-17 18:24 | 显示全部楼层

膜拜中。。。。{:soso__7524161091986203637_5:}
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-4-28 06:08 , Processed in 0.282172 second(s), 33 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表