Shader-水面波纹效果

最近要用到一个水面的波纹效果,又不想用现成的资源,就像自己写一个。

要求解一个真实的水面的波纹,首先需要知道当前水面的状态,还要知道当前所施加的扰动。一开始的想法肯定是用一个二维数组来储存整个水面的高度和速度,再根据外加扰动计算下一帧的状态,生成高度贴图后扔给shader。然而,这样的实现虽然是最真实的,可是应该没有电脑能做到一秒60帧。。。所以肯定得做一些简化。毕竟我们要的只是一个比较真实的效果,而不是求解整个物理场。

注意到水波会以一个中心点向四周发展,那就可以抽象出一个先进先出的队列数据结构来储存某个源点的历史扰动信息。然后在每一帧将所有源点信息向后移一个位置。

class HistoryWave
    {
        public bool dirty = false;
        public Vector2 position = new Vector2(-1, -1);
        List<float> history = new List<float>();
        int min = -1;
        int max = -1;
        int ExistTime = 120;
        public HistoryWave(int ET,Vector2 PS)
        {
            ExistTime = ET;
            position = PS;
        }
        public bool NewInf(float inf)
        {
            if (inf != 0)
            {
                min = 0;
                max++;
            }
            else if (min != -1)
            {
                min++;
                max++;
            }
            else
            {
                min = -1;
                max = -1;
            }
            if (min > ExistTime || min == -1)
            {
                history.Clear();
                min = -1;
                max = -1;
                return true;
            }
            history.Insert(0, inf);
            if (max > ExistTime)
            {
                history.RemoveAt(history.Count - 1);
                int i = history.Count - 1;
                for (; i >= 0; i--)
                    if (history[i] != 0) break;
                max = i;
            }
            return false;
        }
        private float _GetInf(int index)
        {
            if (index < min || index > max) return 0;
            if (min == -1) return 0;
            return history[index];
        }
        public float GetInf(float time)
        {
            if (time < 0) Debug.Log("time = "+time);
            if (time > ExistTime) return 0;
            int l = Mathf.FloorToInt(time);
            int r = l+1;
            float res = _GetInf(l)*(r-time) + _GetInf(r)*(time-l);
            return res * (ExistTime - time)/ExistTime;
        }
    }
再创建一个类来管理所有的源点:

class HistoryWaves
    {
        public List<HistoryWave> waves = new List<HistoryWave>();
        int existTime;

        public HistoryWaves(int ET)
        {
            existTime = ET;
        }

        public void TimePass()
        {
            foreach (var wave in waves)
            {
                if (wave.dirty)
                {
                    wave.dirty = false;
                    continue;
                }
                if (wave.NewInf(0))
                    waves.Remove(wave);
            }
        }
        public void NewInf(Vector2 pos, float Inf)
        {
            HistoryWave wave = waves.Find(iter => iter.position == pos);
            if (wave == null)
            {
                wave = new HistoryWave(existTime, pos);
                wave.NewInf(Inf);
                waves.Add(wave);
            }
            else if (wave.NewInf(Inf))
            {
                
                waves.Remove(wave);
            }
            wave.dirty = true;
        }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值