查看: 9222|回复: 95

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

  [复制链接]

19

主题

21

听众

476

积分

小学生

Rank: 2

升级   92%

发表于 2012-12-30 21:49 |显示全部楼层
共享资源可获取更多积分,所有资源仅供参考学习研究!
资源信息 Tutorial Information
教程名称: Unity3D中实现常见的水面效果教程(发布原创教程可获得更多积分哦!)
适用引擎:   (资源适用引擎)
教程语种: 中文
教程等级: 小白(等级越高教程越难,但能学到的东西越多)
教程格式: 图文(请用IE9以上浏览器访问本版块)
教程作者: 转载自互联网 (如有问题请短消息联系作者或发表回复)
点击查看原图
请先回复 --点击试用VIP 美丽分割线


一 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 人评分鲜花 收起 理由
peterchang1211 + 1 淡定
没事儿瞎蹦跶 + 1 神马都是浮云
yugo215 + 1 赞一个!
graywolfx21 + 1 很给力!

总评分: 鲜花 + 3  + 1   查看全部评分

认真总结可一下自己unity的日志

0

主题

0

听众

9

积分

问题学生

Rank: 1

升级   4.5%

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

使用道具 举报

6

主题

31

听众

195

积分

问题学生

Rank: 1

升级   97.5%

发表于 2013-9-15 10:44 |显示全部楼层

感谢楼主的无私分享!
回复

使用道具 举报

0

主题

32

听众

191

积分

问题学生

Rank: 1

升级   95.5%

发表于 2013-9-17 16:32 |显示全部楼层

感谢楼主的无私分享!
回复

使用道具 举报

0

主题

32

听众

194

积分

问题学生

Rank: 1

升级   97%

发表于 2013-11-25 16:47 |显示全部楼层
感谢楼主   分享很好的教程   
回复

使用道具 举报

0

主题

32

听众

195

积分

问题学生

Rank: 1

升级   97.5%

发表于 2013-12-2 10:25 |显示全部楼层
kankan                                 
回复

使用道具 举报

0

主题

0

听众

8

积分

问题学生

Rank: 1

升级   4%

发表于 2014-2-28 18:03 |显示全部楼层

感谢楼主的无私分享!
回复

使用道具 举报

0

主题

32

听众

196

积分

问题学生

Rank: 1

升级   98%

发表于 2014-3-6 10:51 |显示全部楼层
谢谢你的分享!
回复

使用道具 举报

0

主题

0

听众

8

积分

问题学生

Rank: 1

升级   4%

发表于 2014-5-16 09:03 |显示全部楼层
我完全看不懂,感觉很牛逼的样子
回复

使用道具 举报

0

主题

31

听众

166

积分

问题学生

Rank: 1

升级   83%

发表于 2014-5-17 18:24 |显示全部楼层

膜拜中。。。。
回复

使用道具 举报

温馨提示:求助请到“Unity技术讨论”版块中发帖,便于集中解决!
您需要登录后才可以回帖 登录 | 立即注册

关闭

站长推荐 上一条 /1 下一条

Unity3D开发中国社区 -Unity3D,Unreal ( 粤ICP备20003399号 )

GMT+8, 2020-10-24 05:22 , Processed in 0.121066 second(s), 47 queries .