文章 | 机核 GCORES ( ) • 2024-03-15 13:29

前言

实时渲染中的“实时(Realtime)”,指的是满足每帧能完成画面渲染任务,更多是一个性能指标概念,和是否真实没直接关系。由于传统渲染管线总归是用一系列技术来近似真实世界的光照,所以如果出了Bug或全局光照设置不得当,就会出现标题画面中的脸黑问题。
如果把物体表面直接着色称为“直接光照”,与之对应的就是“间接光照”,两者可以合称全局光照。狭义的来划分可以认为光线从光源直接照到物体表面并反射到摄像机的是直接光照,而弹射大于一次的光传播效果都是间接光照。
次表面或一定体积的光照可以认为介于两者之间,因为一定程度上已经需要模拟光线弹射几次的结果了。
虽然概念上看着都是几个字,但如果物体表面光照的实现难度好比温顺的小猫,次表面、体积光照的实现难度可能像是华南虎——而间接光照的实现就像是克苏鲁里的古神一样,只提几个概念就能产生大脑过载的感觉。
这篇文章可以认为是放在“游戏中还原真实世界”的这个系列中,只是标题太长写不下了。
大部分人包括我自己都还是宁可全局光照是一个黑盒,偶尔打开看一眼也要匆忙的关上,使其退化为引擎中不起眼的几个选项和小按钮。尽管如此,非光追渲染管线中能做到的全局光照特性还是不多,所以这次我会反着介绍——即先从光线追踪的全局光照开始谈起(先把大脑干超载了,把课题提出来,再逐步回收)。
(图中对比了只有直接光照和计算了一次弹射的全局光照的效果,后者会显得明亮很多,因为计算中损失的能量更少)

1 基于光线追踪的全局光照

一般认为光线追踪(Ray Tracing)是一整套现代光传播模式的渲染策略的集合,这里面大部分还是只能在离线渲染中使用。其基本思想其实已经反复提到了,但是实际技术方案中由于算力和采样精度问题还是有一些优化点。
较好实现的光追可以覆盖全局光照中的几乎所有课题,因为已经尽可能模拟了物理世界中的光传播——虽然精度可能永远只能无限趋近。
1)光线追踪—— Ray tracing [1979]
与后来的现代光线追踪不同,最初的方案也被称为Whitted style ray tracing
(图中展示了1980年这一方案实现的折射和反射效果)
其基本策略仍是以射线的方式来计算,而不是以能量的方式来考虑衰减和光传播。这一方案认为光线在光滑表面会弹射,在漫反射表面会停止弹射;由于在光滑表面弹射的原因,可以实现光滑表面的反射效果。
2)路径追踪—— Path tracing [1986]
基于辐射度量学(Radiometry)的思想,计算过程考虑能量在微表面的传播与衰减。基于光路的可逆性,追踪的既可能是光路也可能是摄像机视线。
基础思想是从摄像机发射出射线,并基于蒙特卡洛积分方法(Monte Carlo integration)进行采样——简单的说就是把积分问题转化为离散采样问题,采样策略和精度决定了结果的近似程度。
使用这种方法时,视线在每个物体表面还是只弹射出一次(这里与实际物理世界不完全一致),直到与光源连接或达到一定弹射次数。
这也是光线追踪模式中的光源需要有体积的主要原因。
(图中是Wiki中Path Tracing实现的效果)
基于优化视线命中光源的效率问题,后续又提出了双向路径追踪(Bidirectional Path Tracing)等方案。
3)其它更现代的光传播计算策略
这里列举一下,每个概念都不展开了。例如:光子映射(Photon mapping)、梅特波利斯光照传输(Metropolis light transport ),基本都是在光线追踪的基础上进行改进和特化。
(图中展示了光子映射用来解决酒杯的焦散渲染问题)
*从最早提出时间看,其实在离线渲染领域这些技术方案早就有了,只是迟迟无法应用到实时渲染领域。

2 实时渲染管线的全局光照技术概述

传统渲染管线的全局光照,主要是基于预运算和屏幕空间的,后期还有一些基于3D空间体素化的方案(体素化后面的节会提到)。
由于是对物理世界的归纳和近似,对于物理世界中的一个特性都往往需要多种技术组合实现。
1)整体颜色问题——环境光、烘焙光照贴图
传统的环境光指按一定策略为范围内的物体统一叠加某种颜色,可以动态调整(室内、室外切换之类)。烘焙则顾名思义不可动态变化。
(图中展示了Unity中的烘焙光照贴图)
2)明暗问题——包括实时阴影、烘焙阴影、实时AO、烘焙AO(关于AO下一节会谈到)等
阴影和环境光遮蔽(AO)更多的是人为划分,因为传统管线里无法为所有物体都计算所有光源的实时光照明暗。
可以简单认为直接光照未能照亮的部分称为阴影(包含软阴影自阴影问题),这部分主要是通过阴影贴图(ShadowMap)的一系列技术来实现。对于多光源的阴影还引入了反射阴影贴图(RSV——Reflective Shadow Mapping)技术,这里不展开了。
间接光照渲染时,环境中中较暗的部分则被称为AO。实际实现中往往通过不同物体表面连接处的接近闭合程度来近似计算。
3)反射问题——主要思路是实时反射(摄像机或Ray Marching)和从预渲染图中反射(之前一篇讲镜面反射的文章中写了很多)
4)间接光照问题——在非光追管线中想实时的来模拟光线弹射后照到物体的效果,主要包含屏幕空间和3D空间这两大方向
5)其它辅助效果——每项都是对物理世界中一类效果的还原,属于对光照系统的补充。例如镜头光晕(Lens flare)效果、雾效果、水体焦散(Caustics)、体积光照(典型的如丁达尔效应 The Tyndall effect )等。

3 环境光遮蔽概述

环境光遮蔽(AO—— Ambient Occlusion)在美术上也被称为闭合阴影。基本设想是物体表面越接近越封闭的部分受光越少,因此可以基于物体之间的接近和封闭程度来推算间接光照的明暗。
(图中是Large Scale Ambient Occlusion的中间件效果展示,第二行是开启了AO的效果。右边的屋内也是一类典型的间接光照场景)
看图基本能理解为什么需要AO。这里介绍两类实时AO的方案:
1)屏幕空间AO(SSAO——Screen Space Ambient Occlusion)
SSAO指运用帧缓冲中的有效数据进行AO推算的一类技术,其主要计算依据是缓冲区中的深度法线贴图。结合这两者,通过一些采样策略来近似估计得到某个着色点的AO值。
(Wiki中SSAO的传统流程,对于一些极限值是需要引入偏移量来修正的)
后续还迭代出了改进版本的HBAO( Horizon-Based AO),这里不展开了。
2)体积AO(AO Volume)
其基本思想是为动态计算AO的物体预计算其各方向的遮挡采样情况,存储为一个空间贴图(Volume Texture)。其中的指可以预览为空间中环绕物体的很多锥体,包含——方向、位置、锥立体角度几个信息维度。
渲染时,空间中的任何一个接近物体AO计算范围的着色点,都可以带入这个预存储数据计算,得到一个近似的AO值。当然实际应用中还需要调一些魔鬼数字的函数偏移量(Bias),毕竟这是一个trick。
(图中展示了这一方案预存储数据的预览效果)
(图中显示了这一方案添加了Bias后的实时渲染效果)
这个方案可以解决的典型的一类问题就是人物爬墙过程的实时AO计算(这里指的不是阴影,而是间接光照产生的AO)。

4 球谐函数及其应用

球谐光照是一种基于球谐函数(Spherical Harmonics, SH)的着色算法,它用于模拟低频的环境光照明。实时渲染中通常使用低阶球谐函数来编码存储光照信息,这些函数可以查询球面上不同方向(位置)的光照颜色值。
实际执行时先对复杂光源进行预采样,把结果保存到一些球谐光采样器中,在实时渲染时就可以通过着色点在空间中的位置带入函数得到颜色值——多个采样点之间可以通过权重和插值之类方式混合。
采样为球谐光照数据的过程可以视为进行了一次有损压缩,但优势是实际要存的值相对很少(RGB共27个系数)。
这个方案对于低频信号近似效果较好;而反射光高光属于高频,无法被涵盖在这个方案中。
在我比较熟悉的Unity中,就有光探针(Ligth Probe)方案:
(图中的动态物体在运行时可以依据光探针组改变其表面的光照着色)

5 体素及其应用

体素(Voxel)是实时渲染中一种常用的中间结构,是一种把空间中物体颜色插值归纳成“大颗粒”的立方体——体素,便于做实时近似采样的技术。体素准确的说是一种颜色查找结构,只是预览时会表现为大的立方体。对于静态场景,相关的体素查找结构都是可以预计算的。
(图中的颜色方块就是体素的预览效果)
这里列举2种在利用体素思想在3D空间中实现全局光照的方案:
1)光传播体积(LPV ——Light Propagation Volutions)
核心思路就是将空间网格(体素)化,把计算过直接光照的表面作为一次弹射起点,然后发出射线在击中的体素上采样计算,作为间接光照的结果。
由于存储和查找时是需要通过球谐函数(SH),所以速度相对快;但这个方案只能处理好漫反射表面的间接光照,并由于其精度的损失会带来漏光问题。
(图中的间接光照部分采用的就是LPV方案)
2)体素全局光照(VXGI—— Voxel Global Illumination)
与前者不同是这套方案是把几何物体网格(体素)化。预计算时将网格体素离散化为树状结构并存储光照计算相关信息,在渲染时通过锥体追踪(Cone Tracing)来计算光照 。
由于有了多层树状结构和锥体追踪,因此用更多存储空间和性能消耗换来了相对更高的精度。这2个方案的对照也可以近似理解为一层纹理和多层Mipmap之间的关系(虽然有一些查找策略等细节完全不同)。
(图中展示了这一方案通过2个Pass实现预运算和查找的思路)
相关的更学术化的讲解都可以从Games202系列课中找到,这里只是粗略的介绍了这套方法的概念联系。

结语

本文粗浅地介绍了一下全局光照,可以看出这个概念是由一堆不断迭代的技术方案来组成的。即便游戏有很高的渲染精度,也用上了虚幻引擎,并不意味着这种需要一事一议的全局光照就能一劳永逸的快速搞定了。引擎的好效果只是其上限,至于如何发挥出上限还需要积累漫长的优化和美化经验。
很多全局光照技术如果需要用在风格化渲染(如卡通渲染)中,都需要定制化的进行改进;而且光线追踪也不是风格化渲染的通解。
另外还是一个老生常谈的问题,就是即使在几年后的次时代主机上,只用光追管线的时代还远远无法到来。类似《堕落之主》《奇唤士》这类画风偏写实的准3A游戏,还是必须打开全局光照这个愁人的潘多拉魔盒。
最后是一些资料链接: