本文实例为大家分享了unity shader实现水波纹的具体代码,供大家参考,具体内容如下
效果:
shader代码:
shader "custom/shuibowen"{ properties{ _maintex("base (rgb)",2d)="white"{} _distancefactor("distancefactor",float)=1 _timefactor("time factor",float)=2 _totalfactor("total factor",float)=3 _wavewidth("wave width",float)=4 _curwavedis("curwave dis",float)=5 _startpos("star pos",vector) = (1,1,1,1) _maintex_texelsize("maintex_texelsize",vector)=(1,1,1,1) } cginclude #include "unitycg.cginc" uniform sampler2d _maintex; float4 _maintex_texelsize; uniform float _distancefactor; uniform float _timefactor; uniform float _totalfactor; uniform float _wavewidth; uniform float _curwavedis; uniform float4 _startpos; fixed4 frag(v2f_img i) : sv_target { //dx下纹理坐标反向问题 #if unity_uv_starts_at_top if (_maintex_texelsize.y < 0) _startpos.y = 1 - _startpos.y; #endif //计算uv到中间点的向量(向外扩,反过来就是向里缩) float2 dv = _startpos.xy - i.uv; //按照屏幕长宽比进行缩放 dv = dv * float2(_screenparams.x / _screenparams.y, 1); //计算像素点距中点的距离 float dis = sqrt(dv.x * dv.x dv.y * dv.y); //用sin函数计算出波形的偏移值factor //dis在这里都是小于1的,所以我们需要乘以一个比较大的数,比如60,这样就有多个波峰波谷 //sin函数是(-1,1)的值域,我们希望偏移值很小,所以这里我们缩小100倍,据说乘法比较快,so... float sinfactor = sin(dis * _distancefactor _time.y * _timefactor) * _totalfactor * 0.01; //距离当前波纹运动点的距离,如果小于wavewidth才予以保留,否则已经出了波纹范围,factor通过clamp设置为0 float discardfactor = clamp(_wavewidth - abs(_curwavedis - dis), 0, 1) / _wavewidth; //归一化 float2 dv1 = normalize(dv); //计算每个像素uv的偏移值 float2 offset = dv1 * sinfactor * discardfactor; //像素采样时偏移offset float2 uv = offset i.uv; return tex2d(_maintex, uv); } endcg subshader { pass { ztest always cull off zwrite off fog { mode off } cgprogram #pragma vertex vert_img #pragma fragment frag #pragma fragmentoption arb_precision_hint_fastest endcg } } fallback off }
c#代码:
using system.collections; using system.collections.generic; using unityengine; public class waterwaveeffect : posteffectsbase { //距离系数 public float distancefactor = 60.0f; //时间系数 public float timefactor = -30.0f; //sin函数结果系数 public float totalfactor = 1.0f; //波纹宽度 public float wavewidth = 0.3f; //波纹扩散的速度 public float wavespeed = 0.3f; private float wavestarttime; private vector4 startpos = new vector4(0.5f, 0.5f, 0, 0); public material _material; void onrenderimage(rendertexture source, rendertexture destination) { //计算波纹移动的距离,根据enable到目前的时间*速度求解 float curwavedistance = (time.time - wavestarttime) * wavespeed; //设置一系列参数 _material.setfloat("_distancefactor", distancefactor); _material.setfloat("_timefactor", timefactor); _material.setfloat("_totalfactor", totalfactor); _material.setfloat("_wavewidth", wavewidth); _material.setfloat("_curwavedis", curwavedistance); _material.setvector("_startpos", startpos); graphics.blit(source, destination, _material); } void update() { if (input.getmousebutton(0)) { vector2 mousepos = input.mouseposition; //将mousepos转化为(0,1)区间 startpos = new vector4(mousepos.x / screen.width, mousepos.y / screen.height, 0, 0); wavestarttime = time.time; } } }
新建一个材质球,选择此shader,并赋值给这个脚本,点击屏幕即可看到效果