【游戏技术群】959392658  【游戏出海群】12067810
游戏蛮牛 手机端
开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

开发者专栏

关注:2373

当前位置:游戏蛮牛 技术专区 开发者专栏

__________________________________________________________________________________
开发者干货区版块规则:

  1、文章必须是图文形式。(至少2幅图)
      2、文章字数必须保持在1500字节以上。(编辑器右下角有字数检查)
      3、本版块只支持在游戏蛮牛原创首发,不支持转载。
      4、本版块回复不得无意义,如:顶、呵呵、不错......【真的会扣分的哦】
      5、......
__________________________________________________________________________________
查看: 3758|回复: 51

[士郎] Unity3D水特效之雨天模拟(一)

[复制链接]  [移动端链接]
排名
3
昨日变化

7088

主题

7615

帖子

2万

积分

Rank: 16

UID
1231
好友
185
蛮牛币
11121
威望
30
注册时间
2013-7-29
在线时间
3645 小时
最后登录
2018-12-17

社区QQ达人活力之星原创精华达人突出贡献奖财富之证游戏蛮牛QQ群会员蛮牛妹VIP

发表于 2018-9-26 14:55:50 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
在写实类游戏制作时,常需要下雨场景的制作,由于日常生活中几乎所有物体都会被淋湿,所以下雨的制作其实需要考虑的方面有很多,我们将从粒子,材质,脚本控制等方面,分析一下应该如何渲染一个下雨的场景。
  • 材质高光:
Unity的Standard Lighting中,使用GGX作为BRDF的高光算法,GGX具有拖尾感,可以较好的模拟潮湿物体表面的反光效果,首先我们来看一下这张故宫下雨时的照片(图侵删):
1.jpg
在普通游客的眼里,地面变得“湿滑”了,然而在渲染工程师的眼里,我们应该将这个“湿滑”的效果在PBR中分成四部分:Smoothness的提高,Specular Color的变亮以及GI Occlusion的降低和法线贴图比重的降低。首先,提高Smoothness是毫无疑问的,要让物体表面光滑首先要降低粗糙度,但是仅仅降低粗糙度是不行的,水停留在物体表面,这时反射光线的是水而不是物体本身,因此物体本身的漫反射会被降低,因此被淋水的物体看起来颜色会变深,根据物理反射定律,物体本身色彩无变化,即光线反射比例无变化的情况下,高光程度应提高,所以会表现出高光率提高的现象。同样,因为积水在物体表面的停留,物体受环境光影响会增大,这时我们应该适当降低Occlusion Map的影响,并降低法线贴图的偏移强度,这些在Unity的Standard Shader中都有提供,不需要手动写Shader,当然,如果要处理一个大场景,希望通过全局变量控制,还是应该手写shader进行精确优化的,因此,希望读者能够不依赖Shader Forge, Unity Surface Shader等辅助功能,独立编写基于PBR Shader。至于反射图像的处理,我们一般通过Reflection Probe, Screen Space Reflection & Planar Reflection等方法实现,这并不在本文讨论的范围内,我们将会在本专栏的其他文章中详细讨论。
2.jpg
不同反射率的材质
接下来就是雨水的制作了,雨水本身的粒子效果制作虽然属于比较初级的粒子制作,甚至Assets Store上也有大量的资源,但是对美术制作能力有比较高的要求。如果像我一样,美术功底奇差无比,完全可以直接买一个效果实现#手动斜眼#,然后在粒子发射器上绑定一个脚本,使其始终在摄像机上方悬停,可以看到在示例中,我们使用粒子碰撞防止穿帮:
3.jpg
在摄像机第一视角效果如下:
4.jpg
雨水落在平面
到此,一个简单的雨水渲染就出来了,然而,整个画面看起来僵硬死板,这是因为我们没有表现出雨滴打在地上的效果,因此,我们需要模拟一个动态的法线贴图,让地面的法线“动起来”,解决的方法有许多,最简单的方法就是序列帧,在CG软件(如Houdini,Substance Painter等)中制作序列帧并且渲染,然后在Unity中播放,这当然是一种比较简单的方法,但是同样也无法实现真正的实时与随机,我们这里则是使用Unity自带的CommandBuffer进行比较底层的图形绘制,实现随机的雨点特效。

学习过渲染管线基础的朋友都知道,Unity的摄像机其实并不是绘制RenderTexture的唯一方法,它只是封装的比较上层的方法,其实摄像机的工作流程就是(剔除->绘制网格->后处理)这三部分,无论是Forward path或是Deferred Shading path,亦或是Unity 2018最新提供的HDRP和LWRP,本质上都是这三部,区别仅仅在于,deferred shading会将光照作为后处理运算,而forward path会直接将灯光信息传入shader中进行光影运算并直接输出色彩,而我们这里并不需要动态剔除,只需要使用command buffer在一个指定的Render Target上进行GPU Instance,使用指定的材质绘制大量面片即可。有朋友问我为何不使用Unity 2017推出的CustomRenderTexture进行绘制,我认为,CustomRenderTexture只是给不会渲染底层的程序提供的一个上层封装,实际功能不如使用Graphics类或CommandBuffer直接进行绘制,后者虽然门槛较高但是功能更加强大,大概相当于美图秀秀和PhotoShop的关系(只是个人看法,别怼别怼)。

首先我们需要手动生成一个正方形Mesh,并将indexBuffer设置为四边形绘制,实现非常简单,代码如下:
5.jpg
由于我们是直接往屏幕上绘制的,所以根本不需要考虑ViewProjectionMatrix的问题,直接用NDC坐标(-1, 1)进行绘制即可,如果直接将这个mesh绘制到RenderTarget上,就是一个覆盖全屏的Mesh。

接下来我们要让这个mesh缩小并且随机分布在RenderTarget上,实现雨滴随机散落的效果,这时候就需要使用矩阵进行变换了,然而,雨滴数量众多,在本例中我们绘制了1023个雨点,所以很难依靠CPU进行迭代绘制,无论是计算还是Drawcall,消耗都是难以接受的。所以我们使用Compute Shader与Gpu Instance进行绘制,大幅度提高运算效率。

首先是Compute Shader,这里不赘述如何使用Compute Shader,只是提供Compute Shader的实现目标与过程。实现目标:生成1023个随机分配位置的矩阵并执行1023个计时器。为何要用计时器呢,原因很简单,当一个雨点散落到地上时,涟漪应该是越来越浅直到消失的,在涟漪消失时更新位置信息,使面片在另一个位置绘制。实现代码如下:
6.jpg
这里来解释一下这段代码的意义,MatrixBuffer是我们需要使用的1023个坐标矩阵,而timeSliceBuffer则是我们需要使用的计时器,其中float2的x值是计时器数值而y值是计时器速度。_DeltaFlashSpeed则是由脚本传入的每帧的更新,即Time.DeltaTime * X; 然后是两个LocalRand函数,使用魔数运算输出一个伪随机数。其中第一个函数会输出一个(-1, 1)区间的float2随机数,用于随机生成一个平面位置,而第二个函数则会输出一个(0, 1)区间的float随机数,用于生成一个随机的计时器速度。

下面的CSMain函数就比较简单了,当计时器数值>1时,归0并重新生成随机的速度与位置。根据线代基础,矩阵的M03, M13决定了xy轴的位置,M00,M11则决定了xy轴的Scale,而这里为了偷懒,果断省略了雨滴大小的随机,直接用同样大小的面片。

在ComputeShader中运算完毕后,就可以在脚本里获取计算的结果,并且使用运算结果进行绘制了,当然,在此之前我们需要先进行初始化:
7.jpg
这里初始化了Compute Shader,Compute Buffer以及需要用到的GPU Instance材质与高斯模糊材质(之后会用到)。
接下来就是调用Compute Shader并使用CommandBuffer进行绘制:
8.jpg

首先,指定renderTarget并初始化为(0.5,0.5,1)也就是标准的法线贴图格式,然后使用Compute Shader输出的矩阵进行Gpu Instance,最后经过高斯高斯模糊,使画面顺滑一些。

有了输入的计时器与输入的矩阵,就可以开始绘制波纹了,波纹绘制实际非常简单,直接用Alpha Blend实现减弱效果,用三角函数实现波动即可,直接上代码:
[AppleScript] 纯文本查看 复制代码
Shader "Unlit/Wave"
{
    SubShader
    {
        Tags { "RenderType"="Opaque" }
	ZWrite Off
	ZTest Always
	Cull Off
        Blend oneMinusSrcAlpha srcAlpha
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_instancing
            #include "UnityCG.cginc"
            #pragma target 5.0
            #define MAXCOUNT 1023
            StructuredBuffer<float2> timeSliceBuffer;
            struct appdata
            {
                float4 vertex : POSITION;
                float4 uv : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
		float timeSlice : TEXCOORD0;
                float2 uv : TEXCOORD1;
            };

            v2f vert(appdata v, uint instanceID : SV_InstanceID)
            {
                v2f o;
                UNITY_SETUP_INSTANCE_ID(v);
                o.vertex = mul(unity_ObjectToWorld, v.vertex);
		o.timeSlice = timeSliceBuffer[instanceID].x;
                o.uv = v.uv;
                return o;
            }
            #define PI 18.84955592153876
            float4 frag(v2f i) : SV_Target
            {
                float4 c = 1;
                float2 dir = i.uv - 0.5;
                float len = length(dir);
                bool ignore = len > 0.5;
                dir /= max(len, 1e-5);
                c.xy = (dir * sin(-i.timeSlice * PI + len * 20)) * 0.5 + 0.5;
                c.a = ignore ? 1 : i.timeSlice;
                return c;
            }
            ENDCG
        }
    }
}

shader非常简单,只是绘制了一个大致效果,最后生成的法线贴图效果如下:
9.jpg
可以看到,这张对密集恐患者非常友好的图片,已经有了深浅不一的涟漪花纹(虽然比较难看),我们将这张renderTarget放到地面上,效果如下:
10.jpg
可以看到,地面已经有了法线的涟漪,最近放假回国探亲,只能用家里的古董笔记本写文章,不过从粒子到动图绘制,在这台古董上也只需要4ms左右的运算时间,drawcall也因为gpu instance的原因并没有额外增加,可以说性能表现比较令人满意。

当然,这只是比较基础的雨水表现,其他丰富的细节与最终的开源实现将会在之后的几篇文章中公布。

知乎@MaxwellGeng

评分

参与人数 2鲜花 +4 收起 理由
WhiteDep + 2 很给力!
cn15279256493 + 2

查看全部评分


跟我念“站长妹纸萌萌哒!”我说站长,你说YO!爱你们么么哒~
回复

使用道具 举报

排名
13380
昨日变化
4

0

主题

17

帖子

97

积分

Rank: 2Rank: 2

UID
221609
好友
0
蛮牛币
150
威望
0
注册时间
2017-5-11
在线时间
18 小时
最后登录
2018-10-22
发表于 2018-9-26 15:18:46 | 显示全部楼层
可以的.......................................

回复

使用道具 举报

5熟悉之中
662/1000
排名
2971
昨日变化
11

0

主题

41

帖子

662

积分

Rank: 5Rank: 5

UID
245874
好友
0
蛮牛币
1581
威望
0
注册时间
2017-9-25
在线时间
141 小时
最后登录
2018-12-17
发表于 2018-9-27 08:22:15 | 显示全部楼层
cool,多谢分享

回复

使用道具 举报

4四处流浪
301/500
排名
6786
昨日变化

0

主题

45

帖子

301

积分

Rank: 4

UID
200493
好友
0
蛮牛币
1306
威望
0
注册时间
2017-1-11
在线时间
68 小时
最后登录
2018-12-17
发表于 2018-9-27 08:40:11 | 显示全部楼层
炫酷...........
[发帖际遇]: MengC 在网吧通宵,花了 2 蛮牛币. 幸运榜 / 衰神榜

回复

使用道具 举报

7日久生情
1589/5000
排名
1435
昨日变化
1

0

主题

468

帖子

1589

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
87577
好友
0
蛮牛币
5366
威望
0
注册时间
2015-3-31
在线时间
271 小时
最后登录
2018-12-16

锦衣玉食

发表于 2018-9-27 08:49:14 | 显示全部楼层
too good too strong!

回复 支持 反对

使用道具 举报

5熟悉之中
768/1000
排名
16534
昨日变化

0

主题

500

帖子

768

积分

Rank: 5Rank: 5

UID
199204
好友
0
蛮牛币
355
威望
0
注册时间
2017-1-5
在线时间
228 小时
最后登录
2018-12-14
发表于 2018-9-27 09:07:46 | 显示全部楼层
感谢分享代码

回复

使用道具 举报

7日久生情
2587/5000
排名
280
昨日变化
1

0

主题

129

帖子

2587

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
18512
好友
0
蛮牛币
4840
威望
0
注册时间
2014-3-22
在线时间
578 小时
最后登录
2018-12-17
发表于 2018-9-27 09:16:32 | 显示全部楼层
不错的效果,谢谢分享!

回复 支持 反对

使用道具 举报

4四处流浪
431/500
排名
4796
昨日变化
2

1

主题

31

帖子

431

积分

Rank: 4

UID
217042
好友
0
蛮牛币
1291
威望
0
注册时间
2017-4-10
在线时间
107 小时
最后登录
2018-12-17
发表于 2018-9-27 09:30:56 | 显示全部楼层
感谢分享

回复

使用道具 举报

7日久生情
2341/5000
排名
2508
昨日变化
6

1

主题

1490

帖子

2341

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
119154
好友
0
蛮牛币
2628
威望
0
注册时间
2015-8-21
在线时间
296 小时
最后登录
2018-12-16
发表于 2018-9-27 10:42:11 | 显示全部楼层
谢谢楼主大大。

回复

使用道具 举报

2初来乍到
116/150
排名
20835
昨日变化
4

0

主题

49

帖子

116

积分

Rank: 2Rank: 2

UID
106127
好友
0
蛮牛币
64
威望
0
注册时间
2015-6-6
在线时间
43 小时
最后登录
2018-11-6
发表于 2018-9-27 11:07:40 | 显示全部楼层
2341654315653266

回复 支持 反对

使用道具 举报

5熟悉之中
566/1000
排名
5983
昨日变化
2

2

主题

167

帖子

566

积分

Rank: 5Rank: 5

UID
99709
好友
0
蛮牛币
1352
威望
0
注册时间
2015-5-12
在线时间
173 小时
最后登录
2018-12-17
发表于 2018-9-27 12:41:45 | 显示全部楼层
牛逼

回复

使用道具 举报

4四处流浪
457/500
排名
5437
昨日变化
2

0

主题

82

帖子

457

积分

Rank: 4

UID
282652
好友
1
蛮牛币
2586
威望
0
注册时间
2018-5-24
在线时间
121 小时
最后登录
2018-12-17
发表于 2018-9-27 13:53:58 | 显示全部楼层
666666666666666

回复 支持 反对

使用道具 举报

4四处流浪
318/500
排名
16534
昨日变化

0

主题

210

帖子

318

积分

Rank: 4

UID
289569
好友
0
蛮牛币
175
威望
0
注册时间
2018-7-12
在线时间
66 小时
最后登录
2018-12-17
发表于 2018-9-27 14:15:12 | 显示全部楼层

cool,多谢分享

回复

使用道具 举报

4四处流浪
413/500
排名
5920
昨日变化
25

0

主题

56

帖子

413

积分

Rank: 4

UID
288982
好友
0
蛮牛币
696
威望
0
注册时间
2018-7-8
在线时间
131 小时
最后登录
2018-12-17
发表于 2018-9-27 16:26:33 | 显示全部楼层
感谢分享,谢谢

回复

使用道具 举报

7日久生情
2070/5000
排名
587
昨日变化

0

主题

258

帖子

2070

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
1438
好友
4
蛮牛币
5673
威望
0
注册时间
2013-8-2
在线时间
408 小时
最后登录
2018-11-9
发表于 2018-9-27 18:10:45 | 显示全部楼层
非常酷~期待后续~~
[发帖际遇]: ldragon 在网吧通宵,花了 2 蛮牛币. 幸运榜 / 衰神榜

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

快速回复 返回顶部 返回列表