unity用shader来实现2D涟漪/水波纹特效

一、效果图

如何在画面中产生一个涟漪的效果?

仔细看上面的效果视频,不难发现扩散的涟漪就是高中物理学过的,事实上游戏中也通常使用正弦函数/正弦波来逼近真实世界中的涟漪的效果。正弦函数/正弦波是最基础的波形,如果想要更加复杂的表现效果可以通过修改波的公式或者修改计算的坐标空间。(我们非常机智的使用了自定义的曲线来定义了波形)

我们自定义的波形

有了波形,然后呢?

有了波形并不意味着就能产生涟漪的效果,画面中的折射、反射、扭曲效果还需要我们实现。但如果仔细观察效果并提炼规律,其实也不难得到涟漪效果的原理:

对于涟漪(水波)上的某一点,我们很轻松的就能根据上面的波形曲线得到它的振幅。此处的振幅就对应着这一处对附近空间的扭曲,可能文字说起来有点难以想象,可以看下面的图示:

看图中的涟漪效果,之所以人眼看起来像涟漪,是因为在涟漪处空间发生了轻微的扭曲(珊瑚、鲸鱼的身体),而“空间扭曲”,也就是贴图偏移

OK,核心思想我们已经阐述完毕,所以我们现在可以自信的说出:

涟漪 ≈ 波形 ≈ 振幅 ≈ 画面的扭曲 ≈ 贴图偏移

回过头来看代码片段:

首先是将预设的波形传给shader:

        //伪代码 [rippleeffect.cs]
        //初始化波形贴图(也就是把waveform曲线初始化到gradTexture上面)
        //初始化之后gradTexture的color.a即为波形曲线上对应的值
        gradTexture = new Texture2D;
        for (var i = 0; i < gradTexture.width; i++)
        {
            var x = 1.0f / gradTexture.width * i;
            var a = waveform.Evaluate(x);
            gradTexture.SetPixel(i, 0, new Color(a, a, a, a));
        }

然后是如何得到振幅:

    //伪代码 [RippleEffect.shader]    
    float wave(float2 position, float2 origin, float time) //当前点位置, 出发点位置, 时间
    {
        float d = length(position - origin);//计算当前点到出发点的距离
        float t = time - d * _Params1.z;//计算已扩散时间
	return (tex2D(_GradTex, float2(t, 0)).a - 0.5f) * 2;//在波形曲线上得到振幅
    }

最后是根据振幅算出贴图偏移:

    //伪代码 [RippleEffect.shader]  
    //_MainTex是原来没有涟漪效果的贴图
    half4 frag(v2f_img i) : SV_Target
    {
        const float2 dx = float2(0.01f, 0);//delta x
        const float2 dy = float2(0, 0.01f);// delta y
        float2 p = i.uv * _Params1.xy;//根据相机比例变换当前点的UV坐标
        float w = allwave(p);//振幅,用振幅来对当前点做UV上面的偏移,即可产生涟漪效果
        float2 dw = float2(allwave(p + dx) - w, allwave(p + dy) - w);//xy上振幅
        float2 duv = dw * _Params2.xy * 0.2f * _Params2.z; //UV上的振幅
        half4 c = tex2D(_MainTex, i.uv + duv);//在原图上做偏移,到这一步涟漪效果已经出来了
        float fr = pow(length(dw) * 3 * _Params2.w, 3);
        return lerp(c, _Reflection, fr);//lerp来实现灰色的反射效果,优化表现
    }

最核心的代码就是上面这一块了,在这个过程中将原贴图的某些区域进行了一些像素的偏移,使得这些区域看起来就像高低起伏的水面一样,产生了涟漪的效果

源码下载

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一零壹0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值