coreldraw水涟漪怎么做_Unity基于噪声随机的涟漪模拟

这篇博客介绍了如何利用噪声生成和Voronoi函数来创建更逼真的随机涟漪效果。作者通过分析现有涟漪过于规律的问题,提出了引入随机性和时间变化的解决方案。通过修改Voronoi函数的代码,实现了涟漪在达到最大范围时消失的效果,并通过数学和图形操作对结果进行优化,使其更符合涟漪的形态。最后,作者提到了使用Compute Shader进行计算的建议,并链接了一个包含相关代码资源的Git仓库。
摘要由CSDN通过智能技术生成

eb1852463f30502ce3ec30fbb8c1ebf3.png

之前做过一版涟漪,参考的是:

https://seblagarde.wordpress.com/2013/01/03/water-drop-2b-dynamic-rain-and-its-effects/​seblagarde.wordpress.com

理论就是这张图:

bbfe365056ac718b69636d1c0a824ae5.png

做完了然后效果其实还行,但是盯着只要看两个周期,就会发现涟漪的位置太规律了,虽然是模拟,就算不能真正做到雨滴落地位置和涟漪生成位置产生关联,那起码也要看不出规律。可能这就是强迫症吧。

8a97257969e13317ef8eb40239b49c91.png

大佬之前给我发过一篇闪耀暖暖技术分享:

《闪耀暖暖》如何实现顶级美术表现?先看看叠纸怎么做3D建模吧​mp.weixin.qq.com
881f098519cc39f571fb9df8589af596.png

0c95e5e1dd35816ac7a6e03d560bdd06.png

6ed9924f51c9578c1d11d2322d39825e.png

这不就是晶格么,噪声生成啊,好像的确可以这样做随机。

4eb18d823b150a2cdbf46a769c5ccd51.png

理一下思路,现在是需要一个位置随机,闪烁随机的点。那不就是相当于一个float3(x,_Time,y)为变量的3DWorley么,先在SD里拖出来验证一下:

b16c0762fe436b1232a9906e1a0a6b1a.gif

9a34c24fa38302b5527b11878a404b30.png
应要求补发节点大图

a7dd8f4f115eb77cf4695240a42d9e78.png

毛的问题,好像可以搞!

下面new shader开始搞,voronoiNoise我就不多说了,但是在抄下面代码之前建议去看一下噪声生成原理,不然下下步看不懂。

            float voronoi(float3 value)
            {
                float3 baseCell = floor(value);
                
                //first pass to find the closest cell
                float minDistToCell = 10;
                float3 toClosestCell;
                float3 closestCell;
                [unroll]
                for (int x1 = -1; x1 <= 1; x1 ++)
                {
                    [unroll]
                    for (int y1 = -1; y1 <= 1; y1 ++)
                    {
                        [unroll]
                        for (int z1 = -1; z1 <= 1; z1 ++)
                        {
                            float3 cell = baseCell + float3(x1, y1, z1);
                            float3 cellPosition = cell + rand3dTo3d(cell);
                            float3 toCell = cellPosition - value;
                            float distToCell = length(toCell);
                            if (distToCell < minDistToCell)
                            {
                                minDistToCell = distToCell;
                                closestCell = cell;
                                toClosestCell = toCell;
                            }
                        }
                    }
                }
                return minDistToCell;
            }

//frag
float3 value = float3(i.uv.x / _CellSize, _Time.x * _TimeScale, i.uv.y / _CellSize);
world = voronoi(value);
return world;

e46daa22cad11cf6fd9fa4f621c8824e.gif

好,voronoi出来了,但是仔细思考了一下,涟漪到最大范围的时候应该直接消失啊,可是这个Distance是一个-1到1的过程。

4eb18d823b150a2cdbf46a769c5ccd51.png

求点Distance的时候:

                            float3 toCell = cellPosition - value;
                            float distToCell = length(toCell);

这个distToCell是现在点到目标点的向量,直接把这个向量在Y负半轴的Discard掉应该可行,改一下:

                            float3 cellPosition = cell + rand3dTo3d(cell);
                            float3 toCell = cellPosition - value;
                            float distToCell = 10;
                            if (toCell.y > 0)
                            {
                                distToCell = length(toCell);
                            }
                            /*if (distToCell < minDistToCell)
                            {
                                minDistToCell = distToCell;
                                closestCell = cell;
                                toClosestCell = toCell;
                            }*/
                            minDistToCell = min(distToCell, minDistToCell);

f15973222d1c8aca59003d9724506e89.gif

d8f9f09ddcf3f07fa693f1960a413c4e.png

好,完美!剩下就是拟合一下,把这个图拟合得像涟漪一点:

                float world = voronoiNoise(value);
                float Color = 0;
                Color = 1 - world;
                // Color += 1.0 - step(0.02, world);
                Color = saturate((Color - 0.5) * 2);
                
                Color = sin(clamp(Color * 9.0, 0.0, 4.0) * 3.141592);

b4c2608a9b9bf04a7be13f2460b5fbfb.gif

不要问我怎么拟的,问就是魔术!

ceb50f722c4c59f8d8db04341d6d4474.png

然后求曲率转法线!ddx、ddy操作一下:

            float3 heightToNormal(float height, float intensity)
            {
                float dU = ddx(height);
                float dV = ddy(height);
                float3 n = normalize(float3(0, 0, 1) + float3(dU, dV, 0) * intensity);
                n = n * 0.5 + 0.5;
                return n;
            }

22a09d216562ec58321b0e99473d5b73.gif

伽马矫正一下:

float3 n = pow(heightToNormal(Color, _Intensity), 2.2);

b9df16470e56504e079a186490ac533a.png

矫正完颜色就对了。

贴上去,完事!

dd8134ae5280af7cd1f1c2030eda50a8.gif

当然,这部分计算最好是要拿去ComputeShader里算。


最后我贴一下大佬的Git,上面的代码有用到大佬的Random.cginc:

ronja-tutorials/ShaderTutorials​github.com
9262582d9217a204eac2275730634729.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值