我的专栏目录:
小IVan:专题概述及目录![图标](https://pic4.zhimg.com/v2-adfc32ab6d1929ce6ebb6863da9e0f0f_180x120.jpg)
简介:
最近各大公司都在为自己项目的春节版本忙碌,需求单已经堆积成山,我的体积云海的研究进度也一直停滞不前。最近突然发现自己对各种光照计算还有点模糊不清,所以研究了下这部分细节。模型烘焙的AO和场景烘焙的LightMap里的AO,和SH,和IBL,和Specular这些究竟是如何组合计算的呢,体积光,bloom,应该如何与之前的pass混合呢。Shadowmap和镜面反射到底应该是什么样的关系。之前的PBR理论推导只做了模型表面的Shading的推导,这里将把后面的整个Lighting管线统统捋一遍。
从零开始推导PBR光照模型:从零开始推导PBR渲染模型
首先先把庞大的管线拆解开(实时渲染在Ray Tracing面前感觉就像邪教),游戏画面其实是众多元素合成而来的,我们需要清楚地知道这幅画面里到底有什么东西。拆开研究管线中的每个部分,然后再看他们的组合关系。(下面的排序并非是Unreal的渲染顺序)
(1)Planar Reflection
![v2-87b2130e6c0e8495bfce89563ef368c3_b.jpg](https://pic4.zhimg.com/v2-87b2130e6c0e8495bfce89563ef368c3_b.jpg)
平面反射是以一个平面为基准,把矩阵转一下再渲染一次。渲染出来的图片和物体的Specular根据距离衰减进行插值。在UE中需要在forward或者是mobile管线下才会开启。forward管线的这种倒影之类的反射一般会使用Planar Reflection。延迟管线虚幻没有使用Planar Reflection。
(2)ScreenSpaceReflection
![v2-750b6a4e9c55a098e7550a3d843bb6f1_b.jpg](https://pic2.zhimg.com/v2-750b6a4e9c55a098e7550a3d843bb6f1_b.jpg)
在屏幕空间做marching计算的反射,最大的问题是渲染不到屏幕外的东西。因为延迟管线已经有了深度,法线等信息,所以UE在延迟管线默认使用的是SSR。有了实时光线追踪后就能和SSR做一个对比,下面是实时光线追踪的反射效果:
![v2-4cd4f05d1e96486c7536a6b1faba9d19_b.jpg](https://pic2.zhimg.com/v2-4cd4f05d1e96486c7536a6b1faba9d19_b.jpg)
物体到屏幕外也能渲染出倒影,SSR的话就没办法了。
![v2-df086d0afdf19b39e4459a6fc9e71d01_b.jpg](https://pic2.zhimg.com/v2-df086d0afdf19b39e4459a6fc9e71d01_b.jpg)
Unreal会先画一张SSR的图然后再在第二个pass里把它和之前渲染的场景进行混合
![v2-2db8f103fc5cba160fa71bde20a1f12b_b.jpg](https://pic4.zhimg.com/v2-2db8f103fc5cba160fa71bde20a1f12b_b.jpg)
混合方式是再计算一次Reflection,而且在计算过程中会加入SSAO和Material AO对Reflection进行遮蔽。
![v2-4ffff29e04a36dd207af1db399b5bc40_b.jpg](https://pic1.zhimg.com/v2-4ffff29e04a36dd207af1db399b5bc40_b.jpg)
![v2-756cdf67847b5c54062540265e76a1c8_b.jpg](https://pic1.zhimg.com/v2-756cdf67847b5c54062540265e76a1c8_b.jpg)
MaterialAO是在BasePass渲染的时候填充进GBuffer的MaterialAO
![v2-7ff8e27ab450cbef0d6d4e47490ac7f0_b.png](https://pic1.zhimg.com/v2-7ff8e27ab450cbef0d6d4e47490ac7f0_b.png)
下面是SSAO:
![v2-f0ef7c961245937d9a7d02c9fc107640_b.jpg](https://pic1.zhimg.com/v2-f0ef7c961245937d9a7d02c9fc107640_b.jpg)
Unreal的SSAO效果还是挺搓的。
(3)Reflection probe
![v2-4f7c212ad9d0729bb42dc09ef9626e3b_b.jpg](https://pic4.zhimg.com/v2-4f7c212ad9d0729bb42dc09ef9626e3b_b.jpg)
![v2-204fad8f7479340e01641e6f0b9b2236_b.jpg](https://pic3.zhimg.com/v2-204fad8f7479340e01641e6f0b9b2236_b.jpg)
可以看到我的场景里只有一个漫反射球(选中的那个)。但是!第一幅图中居然有三个球!绿色圈起来的球是DefaultPlayer产生的,蓝色和红色都是漫反射球产生的,蓝色是ReflectionProbe烘焙上去的,红色是ScreenSpaceReflection产生的。
其实这个效果是比较诡异的
![v2-024268fb37b85235843a049d827e60bb_b.jpg](https://pic4.zhimg.com/v2-024268fb37b85235843a049d827e60bb_b.jpg)
SSR和Reflection的结果是叠在一起的,而且位置还没对上。
Reflection和之前的LightingPass的关系是相加的
![v2-249b5f2ec1209dac4b3db7250bd21f55_b.png](https://pic2.zhimg.com/v2-249b5f2ec1209dac4b3db7250bd21f55_b.png)
延迟管线中,会先渲染Lighting部分,然后渲染SSR,然后渲染ReflectionCapture的部分,这和Mobile和forward管线不同。Mobile管线中这部分是在一个pass里一次性渲染出来的。
(4)LightMap
LightMap在场景的World Setting里
![v2-89ae26f18fb2e2260ac5a7e6148374d3_b.jpg](https://pic4.zhimg.com/v2-89ae26f18fb2e2260ac5a7e6148374d3_b.jpg)
当我们Bake光照后会有一大片贴图。
这个计算会在BasePass中的GetPrecomputedIndirectLightingAndSkyLight完成
![v2-a17c79e3e5d38048bd6eddb2f8d46fd0_b.jpg](https://pic1.zhimg.com/v2-a17c79e3e5d38048bd6eddb2f8d46fd0_b.jpg)
![v2-2a53cc403de7c11d56c53ee7ee4d6fc5_b.jpg](https://pic2.zhimg.com/v2-2a53cc403de7c11d56c53ee7ee4d6fc5_b.jpg)
LightMap分为上下两部分使用UV0是上半部分,UV1是下半部分。
![v2-cc8d5c5489de9f20595417b8b029702f_b.png](https://pic4.zhimg.com/v2-cc8d5c5489de9f20595417b8b029702f_b.png)
(5)ShadowMap
或者叫ShadowMask,主要是对直接光进行遮蔽,我前面有文章详细介绍了它
传送门:ShadowMap
除此之外Unreal在4.20的时候还加入了距离场阴影。
(6)AO
AO环境遮蔽在引擎里有好几种。MaterialAO是由美术师提供的。SSAO屏幕空间AO,由引擎计算。PreCaculatedAO,在烘焙光照的时候烘焙计算出来的。这些AO又可以根据用途细分为SkyLightAO,SpecularAO,ReflectionAO。总地来说这些AO会加入到引擎渲染的各个阶段去做遮蔽(trick!)。
(7)Light Probe
对于静态物体可以使用LightMap来预先烘焙间接光照,但是对于动态物体就没办法烘焙了,所以动态物体使用LightProbe。把静态灯光或者周围的环境的光线反弹烘焙到LightProbe里,然后人物走过去的时候采LightProbe里的值来制造间接光照的效果。
![v2-3284c86ed5b120821243ad5eebf1e808_b.jpg](https://pic1.zhimg.com/v2-3284c86ed5b120821243ad5eebf1e808_b.jpg)
Unreal的LightProbe会自己根据周围物体的表面布上去,Unity的相对来说就要简陋点,需要人工自己去拖拽(或者自己撸工具布)。不过原理都是一样的。
可以看到这些光都是静态光但是仍然对动态物体生效
![v2-527b44e1d8328bb2733aa5859d3c805d_b.jpg](https://pic2.zhimg.com/v2-527b44e1d8328bb2733aa5859d3c805d_b.jpg)
值得注意的是,不管是烘焙的LightMap还是LightProbe的IndirectLight都只计算了Diffuse项,没有计算Specular项,Specular项的Indirect是通过各种Reflection模拟的,但是都没有算多次反弹。
(8)BXDF Shading
Unreal这一步就是在算各种光照模型,使用ComputeShader在屏幕上分割Tile然后分Tile计算直接光。
![v2-20506e50113a94c612a2055b7edc7dad_b.jpg](https://pic2.zhimg.com/v2-20506e50113a94c612a2055b7edc7dad_b.jpg)
迭代计算这个Tile中的所有直接光(动态光)。我们把动态光关闭可以看到下图的画面中有如下几项:
![v2-6b3488cec016190133f2632f1e12c981_b.jpg](https://pic2.zhimg.com/v2-6b3488cec016190133f2632f1e12c981_b.jpg)
(1)LightMap Diffuse Indirect lighting,(2)Screen Space Reflection,(3)Light Probe Indirect Lighting,(4)Sky Light Direction Lighting (5)只计算了Reflection Probe的BXDF
加入一盏方向光动态光和三盏动态点光源后可以看到方向光的BRDF和三盏动态点光的BRDF。红框为他们的高光点。除此之外还有动态光的ShadowMap
![v2-4caa72dccd8953b1a641ffe5fad60f07_b.jpg](https://pic4.zhimg.com/v2-4caa72dccd8953b1a641ffe5fad60f07_b.jpg)
除了上面的还有很多如Fog,Atmosphere等。
Enjoy it.