基于屏幕的2D实时反射

3128d04cd0d9d2dd47d2e358395f9159.jpeg

前言

提到屏幕空间的反射,熟悉 3D 渲染的同学应该第一时间会想到 SSR,需要深度图、法线、RayMarching。

相对来说,2D 的反射就简单多了,不需要复杂的算法,我们就能实现反射效果。

比如光滑的大理石地面、水面等。

本文就以水面为题,做一个动态的2D屏幕的反射效果。

c0ec6cf621e24aaabe7eb1b64aca7f09.gif

原理

2D的反射,不需要深度相关信息,其实就是对反射物体的基于自己y方向的一个镜像,可是我们也不能简单的实例化一个自己,然后scale的y给-1。这种方式虽然也能实现镜像,但是会让场景的渲染开销成倍增加,并且达不到我们想要的细节效果。

但我们真正想要的,是这个镜像被渲染到接收反射物的物体上去,比如水面,而且不想除了水面的其他物体接受反射,比如陆地,石头等非水面区域。

所以我们需要利用后处理,把想要反射的物体单独绘制成一张图,然后对这张图进行处理,最后输出到水面的材质里,作为水面渲染的一部分。

反射物体渲染

第一步,创建一个 Cocos 自带的 3D 的 Mesh片 Quad,作为反射物的子物体,Scale 要和反射物的 width 和 height 一致,如果你想反射效果拉长或缩短,那就调整它的 height。

第二步,给它一个自定义的 Layer,我这里叫 REFLECT,然后我们自定义个材质,赋予它反射的魔法。

84b5b6b0824031c4f71d5c183e5b8c27.png

我们要对它做 y 方向的镜像,其实就是在模型空间对它的顶点的 y 值取反,然后再转到世界空间,shader 的顶点着色器代码如下:

27ea533a7cc816756c38181cdd917e10.png

如上所示,vec3(1, -1, 1) * a_position; 就是对模型空间y值的取反。现在它就已经倒过来了,转到世界空间后,我们要给他个坐标偏移,因为锚点在图的中心,所以倒过来也是基于这个锚点翻转的,所以我们要让它向下偏移,偏移到脚对脚,一般来说,这个 Offset 设置为图片的 height 就行。

片段着色器没啥好说的,就是把反射物的图给它,采样就行了。

这里要提一个 mesh 的好处,就是勾选USE INSTANCING,可以让我们的相同材质相同 mesh 的物体通过 gpuInstancing 合批。

8c2c20a30827f8968673837d6758d17b.png

反射相机

做完上一步,我们就获得了物体的反射效果,原理中说了,我们要把这些反射效果绘制到一张图中,然后对这个图一顿操作,所以这个图应该只有反射的倒影,那就需要一个 Camera 去专门做这个事情了。这也就是我上面为什么给我们的 Quad 一个 Layer--REFLECT。记住主相机的 Visibility 不要加 REFLECT。这时候,我们的反射相机大概会渲染成这样。

89fa0221c6ea59f158f15650ea7dcd36.png

反射图拿到了,我们要对它进行操作了。

自定义反射效果

我们要模拟好看的反射效果,就要考虑你现实中看到的反射是啥样的,答案是跟接受反射的物体相关,比如地砖等相对光滑的物体,你能看到相对清晰的倒影,而稍微粗糙点的表面,可能看到模糊并且淡淡的倒影,而对水流的倒影,你还会看到它随着水流来回抖动。那我们就先定义它的清晰度和模糊度。

到这一步,我们就要用到自定义后处理了,有关自定义后处理的知识,Cocos 官方文档和社区开发者分享过很多,如果不了解的请自行查找,本文不做介绍。

我们到目前为止已经拿到了反射图,自定义清晰度其实很简单,就是调整图的 Alpha 就行了。

e3eb858f9af38a034fdcdbeeaebcbddc.png

_ReflectPPRt 是反射图,_Intesity 就是清晰度。

模糊呢,可能很多人会想到高斯,那太复杂了,毕竟是反射的模糊,不要求那么完美,简单的对周围像素求个均值就行。Shader 如下:

84597b489b22c1b0c62305daab08b16d.png

cc_nativeSize,它是系统内置的 vec4 变量,xy 是屏幕的宽高,zw 就是宽高的倒数,也就是屏幕 rt 的纹素,_BlurSize 是模糊度,越大越模糊,这里是对当前像素相邻四个角的像素取平均值。

Shader 里我会拆分成 2 个 Pass,就如同上面两个代码截图,第一个 Pass 是没有模糊的,第二个 Pass 是有模糊的。然后在后处理的代码里,我通过是否勾选模糊来判断走哪个 Pass。

296a043ea5cd7e512a53d18bf3bb5a92.png

后处理编辑器如图:

5784fb0c3cb4ab45ec0760ed4fdfce36.png

Intensity 就是清晰度,Open Blur 是判断是否开启模糊,会影响上面走哪个 PassBlur Size 就是模糊度。

到这一步,我们自定义了反射图的模糊和清晰度,如果是地砖等静态的模糊,我们做的工作就差不多完成了,只需要把反射图赋给地砖做渲染就行了,而如果做水的反射,那我们还得做动态扭曲。

把它交给水吧

反射 Camera 经过自定义后处理,我们把它渲染到自定义的 RenderTexture,我起名叫 reflect-rt ,然后就把它交给水做最后的渲染吧。

话不多说,直接上代码,下面是水的Shader。

d56faeef6bd69df4b4e797aa409f2872.png

主要看 USE_REFLECT_MAP 这个宏定义的部分,这是水是否有反射效果的开关,而 USE_REFLECT_NOISE 这个宏,是反射是否开启抖动的开关。

我先说说我们要干吗,我们要反射图抖动起来,那采样反射图时它的 uv 就得是抖动的,怎么让它的 uv 抖动呢,我们得用一张噪声图去影响这个 uv,然后让噪声图动起来,然后就发生了连锁反应。

我们来看这行代码,vec2 noiseUv = v_uv_reflect * _ReflectUvScale - cc_time.x * _ReflectNoiseSpeed;

其中:

  • v_uv_reflect 是水的当前像素在屏幕上的uv

  • _ReflectUvScale 是控制这个uv的大小。

  • _ReflectNoiseSpeed是噪声的速度,所以这行代码是搞噪声图uv的,让噪声图的uv动起来。

  • _ReflectNoiseTex 噪声图,动态的uv采样得到动态的噪声,我们只关心noiseCol的r值就行,它是从0到1的

  • _ReflectNoiseStrength 是抖动的程度,最后我们把这个噪声加到反射图的uv--reflectUv上去

  • _ReflectTex 反射图

这样,我们就得到了反射图的抖动效果。

最后,我们用反射图的Alpha值对水的颜色做一个混合,反射图的Alpha大家还记得是什么吗,就是反射图的清晰度啊,这个值越小,反射就越淡。

我们看一下效果。

6ade11ad746622b03da6abb4e55f79b2.gif

这是清晰度为 0.5,模糊度为 1.0 的效果,扭曲参数如下图:

314c58ec0918f540197e162ad7a2881d.png

看英文名字应该就能对号入座了。不多解释。

如果不要扭曲抖动,取消 USE_REFLECT_NOISE 勾选即可,那些抖动相关的参数也不用设置了,比如下面的地板反射效果

2b1e4b376898aebfaa1ad8c25fe64a88.png

到此为止就是全部的内容了,如果有不明白的欢迎留言探讨。

往期文章

  • 2D光影系统-光源一:全局方向光

    • https://forum.cocos.org/t/topic/156363

  • 2D光影系统-光源二:Sprite光

    • https://forum.cocos.org/t/topic/156390

  • 2D光影系统-阴影

    • https://forum.cocos.org/t/topic/156536

  • 2D描边-内描边

    • https://forum.cocos.org/t/topic/156861

  • 2D描边-外描边

    • https://forum.cocos.org/t/topic/156878

欢迎关注 Cocos 引擎官方公众号

官方信息、技术干货、行业资讯

  • 25
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Shader 2D近岸海浪是一种用于在游戏或动画中模拟海浪效果的图形处理技术。它通过在屏幕上运行特定的计算程序,改变像素的颜色和位置来呈现出逼真的海浪效果。 实现Shader 2D近岸海浪的基本思路是使用数学公式和算法来模拟海浪的行为。这些公式通常基于物理原理,如波动方程和海洋动力学等。通过将这些公式转化为计算机可执行的代码,可以实现对海浪的模拟和渲染。 Shader 2D近岸海浪可以通过改变像素的颜色和位置来模拟海浪的表面形状和运动。根据海浪的高度和方向,可以调整每个像素的颜色和位置,使其在屏幕上形成波浪的效果。这样就可以呈现出逼真的海浪场景,让玩家或观众感受到真实的海洋氛围。 为了实现Shader 2D近岸海浪效果,开发人员需要在图形引擎中编写或使用特定的着色器程序。这些着色器程序通常包含对每个像素进行计算的代码,包括计算海浪高度、光照效果和反射等。在渲染过程中,图形引擎将每个像素的颜色和位置计算结果传递给显卡进行处理,最终在屏幕上呈现出逼真的海浪效果。 总结一下,Shader 2D近岸海浪是一种通过数学公式和算法模拟海浪效果的图形处理技术。它使用着色器程序对每个像素进行计算,改变颜色和位置以呈现出真实的海浪场景。这种技术广泛应用于游戏和动画中,能够为玩家或观众创造出逼真的海洋体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值