本期作者

WebGL高质量实时人物烘托

WebGL高质量实时人物烘托

布景

随着图形图画烘托技能的快速开展,如何在移动端呈现出高质量的数字人烘托作用,是实时烘托范畴最干流的技能研究方向之一。关于B站移动端App而言,假如运用干流的实时烘托引擎如Unreal/Unity等,都会带来100-130M左右的安装包体积增量,从而增加运用安装和版本更新的成本。

针对该问题,咱们选择了更为灵敏轻量的WebGL烘托计划,将包体增量大幅降低至1M以内,一起凭借Web天然的开箱即用特性,加速了事务需求在移动端落地的整体节奏。经过对Web烘托才能的职业调研,咱们终究从很多的Web3D烘托引擎中选择了Three.JS。Three.JS作为一款轻量级的JavaScript 3D烘托库,具有强大的图形才能和广泛的社区支撑,在数字人烘托方向能够给予咱们必定的根底才能支撑。

但假如仅仅运用Three.JS自带的PBR(Physically-Based Rendering)烘托,在偏CG和写实方向的数字人烘托作用上,很难达到令人满意的品质感。为了能够进一步还原商业实时烘托引擎Unreal的人物作用,一起兼顾好WebGL在移动设备上的功用和发热问题,咱们在人物皮肤,瞳孔,抗锯齿,半通明等方向上做了深化的二次研制,提出了一套完整的高质量人物移动端WebGL烘托处理计划。本文将共享咱们在探究和完结该计划的过程中遇到的挑战及终究的处理思路。

PBR优化

PBR(Physically-Based Rendering)是一种核算机图形学中的烘托技能,旨在模仿(近似)光线在现实国际中的物理行为,以完结更实在、传神的烘托作用。因此咱们的美术资产的制造选用了全套PBR流程,Three.JS内置的MeshPhysicalMaterial也对PBR做了原料支撑,但咱们发现Three.JS的PBR完结在移动端上仍然存在功用瓶颈。所以针对以上问题咱们给出了如下处理计划:

首要咱们来看Cook-Torrance的BRDF模型:

WebGL高质量实时人物烘托

其中Cook-Torrance镜面反射如下:

WebGL高质量实时人物烘托

D标明法线散布函数(Normal Distribution Function)

G标明几许函数(Geometry function)

F标明菲尼尔函数(Fresnel function)

n标明法线方向,l标明灯火方向,v标明视线方向,h标明l与v的中间方向(halfway)

首要,咱们运用 UE4 粗糙度的界说,将它用于以下所有方程中的:

WebGL高质量实时人物烘托

散布函数:

WebGL高质量实时人物烘托

几许函数:

WebGL高质量实时人物烘托

咱们运用史密斯办法(Smith’s method)将G_GGX作为子函数G_sub:

WebGL高质量实时人物烘托

菲尼尔函数:

WebGL高质量实时人物烘托

F0标明标明的根底反射率,一般咱们选用vec3(0.04)

咱们还能够将镜面反射分母与几许函数进行兼并得到可见性项(Visibility):

WebGL高质量实时人物烘托

终究咱们得到了:

WebGL高质量实时人物烘托

咱们发现几许函数里有除法和求平方根,写成代码为:

WebGL高质量实时人物烘托

有没有办法简化呢?依据SIGGRAPH 2015 Optimizing PBR for Mobile有关简化VF项:

WebGL高质量实时人物烘托

终究咱们的表达式:

WebGL高质量实时人物烘托

加和乘,仅有一次除法。

与Three.JS内置PBR功用比照

WebGL高质量实时人物烘托

咱们规划了一个测验场景,仅烘托一个人物,一起去除了其他干扰,为了能体现本次功用距离,选用了3款机器进行测验帧生成时刻(SOC因为发热等因素可能是一个区间):

机型 (处理器) ThreeJS PBR 优化 PBR 提高比例
iPhone 6 (A8) 20-22ms <16ms 20-33%
Redmi 6 Pro (骁龙625) 52ms 32ms 62%
华为 P20 (麒麟970) 10ms 7-8ms 25-42%

较好的机器在该场景下一般能跑上百帧,两者距离相对较小,这儿就不一一列举。

皮肤优化

为了营造皮肤的通透感,咱们调研了市面上干流的皮肤烘托计划,例如屏幕空间次外表散射(Screen Space Subsurface Scattering Skin Rendering)、可分离次外表散射(Separable Subsurface Scattering)、预积分次外表散射(Pre-Integrated Skin Shading)

以上计划除了预积分次外表散射,其它两种计划都要运用实时卷积含糊,开支十分高。而预积分次外表散射计划,依据SIGGRAPH 2011 Pre-integrated Skin Shading的共享,在完结LUT贴图和曲率贴图烘培的情况下,仅运用两次贴图采样即可模仿较好的次外表散射作用。

WebGL高质量实时人物烘托

LUT贴图烘培

WebGL高质量实时人物烘托

曲率贴图烘培

考虑到移动端功用和作用平衡取舍,所以选用了预积分次外表散射的计划:

WebGL高质量实时人物烘托

WebGL高质量实时人物烘托

左:未敞开SSS 右:敞开SSS

瞳孔优化

眼睛烘托一大难点是模仿瞳孔的一个自然的洼陷,假如没有处理好,从人物侧面观察瞳孔会杰出,人物将失去神采。

瞳孔处理一般有两种办法,一种是将瞳孔和眼角膜分开建模,瞳孔向下洼陷,另一种做法是用视差办法模仿瞳孔洼陷。

WebGL高质量实时人物烘托

Tda式初音ミク・アペンドVer1.10

考虑到美术制造流程上的杂乱度,咱们选用了后者,需求把眼球的前向量传递给Shader,然后把视线转换到切线空间对贴图进行采样,终究运用一张Mask贴图决议整个瞳孔的洼陷程度。

WebGL高质量实时人物烘托

左:未敞开瞳孔优化 右:敞开瞳孔优化

烘托管线规划

咱们遇到一些移动设备高分屏的问题,在IPhone13Pro上,内部分辨率高达11701992,依据咱们的经验,这会形成手机发热与功用问题。

WebGL高质量实时人物烘托

为了处理上述问题咱们规划了一套离屏烘托管线,运用Threejs的EffectComposer申请了与屏幕分辨率不同的RenderTarget,并且在RenderScale=0.5的情况下,在大部分高分屏手机上取得了还不错的作用,兼顾了作用与功用。

具体管线如下:

WebGL高质量实时人物烘托

与Three.JS默认直接画到画布上的管线做比照,咱们的计划完结的功用更杂乱,因为能够操控离屏烘托分辨率,功用与质量之间可配置的灵敏度也更高。

抗锯齿

Three.JS支撑硬件抗锯齿MSAA和屏幕空间抗锯齿SMAA,在最开端咱们觉得这两种抗锯齿是够用的,但随着美术需求逐渐杂乱,咱们发现上述两种抗锯齿关于一些边际光照产生的高频像素无能为力,并且在完结头发等作用时,发现MSAA仅对几许走样(Geometry Aliasing)有较好的作用,但对上色走样(Shading Aliasing)根本无效。

WebGL高质量实时人物烘托

MSAA上色走样

咱们测验运用SMAA处理,但终究成果仍不理想。依据经验,上色走样需运用超采样(Super-Sampling)抗锯齿处理,但这样无疑又增加了烘托像素,导致功用问题。

有没有即不需求超采样,又能够处理上色走样的抗锯齿技能呢?答案是有的,咱们选用时域抗锯齿(Temporal Anti-Aliasing),接下来简称为TAA。

在实践中发现,Three.JS上并没有直接可用的TAA,官方内置的TAA本质是个超采样,这并不契合咱们的预期。依据上述布景,咱们决议从零开发TAA。

开麦拉颤动

TAA的中心思想是将屡次采样的过程散布到每一帧当中,这儿咱们除了空间上均匀散布,还期望能在时刻上均匀散布。这儿依据SIGGRAPH2014 Unreal Engine 4 TAA的共享,咱们运用低差异序列Halton(2, 3)作为子像素颤动偏移:

WebGL高质量实时人物烘托

然后咱们将这个颤动(Jitter)偏移调整到开麦拉的投影矩阵上:

WebGL高质量实时人物烘托

运动向量

尽管咱们将采样散布到了每一帧上,可是保存多帧关于移动渠道来说是不实际的,这时咱们需求简化为只保存两帧,当时帧和前史帧。咱们经过指数混合的办法将当时帧和前史帧进行不断累积。假如咱们仅仅简略的将当时帧和前史帧混合,一旦开麦拉或物体产生运动就会呈现残影问题,咱们还需求知道当时像素在上一帧所处的方位,这个过程称为重投影(Reprojection),咱们运用运动向量(Motion Vector)重建上一帧当时像素的方位。

烘托运动向量:

WebGL高质量实时人物烘托

这儿需求留意的是,核算上一帧裁剪空间(Clip Space)方位时咱们除了要传递上一帧的MVP矩阵给Shader外,咱们还需求将上一帧的蒙皮骨骼矩阵一并上传(Three.JS运用的是GPU蒙皮)。为了节省功用,运动向量的RT咱们运用了RGBA8格式,在输出时,还需求将两个Float打包进RGBA8中,在运用运动向量时,咱们还需求进行相应的Unpack操作。

当然,在移动端烘托运动向量需求将场景中物体再次烘托一遍,这样开支在低端机上仍然无法接受,所以在低端机上咱们运用深度图进行方位重建:

WebGL高质量实时人物烘托

具体思路是用逆VP矩阵将方位转换到国际空间,然后再算出上一帧的方位。当然这个办法的缺点是无法重建蒙皮动画的运动。

核算颜色围住盒

尽管进行了上述操作后,残影问题处理了一大部分,可是咱们发现在平移物体的时分,仍然会在布景上呈现很多的鬼影(Ghosting)。

WebGL高质量实时人物烘托

这是因为当时像素在上一帧并没有呈现(被遮挡),在速度向量上也不会有记录。这儿咱们的处理办法是核算当时帧像素周围8个采样点的颜色,核算出最大最小颜色,形成一个颜色围住盒。咱们还能够在YCoCg空间中取得愈加准确的成果。然后咱们就能够将前史帧的颜色约束在这个颜色围住盒规模之内。

方差裁剪

在高端设备或PC渠道上,咱们还参阅了Nvidia GDC 2016上提出的方差裁剪(Variance Clipping)

WebGL高质量实时人物烘托

这儿咱们的gamma值取2将会取得一个比较稳定的成果。

WebGL高质量实时人物烘托

左:gamma 1.0 右:gamma 2.0

深度扩张

到目前为止,咱们已经得到了比较好的作用,但咱们移动开麦拉会发现,物体边际会有锯齿。

WebGL高质量实时人物烘托

这儿咱们需求对当时像素的深度周围8个像素进行采样,得到一个最小值(离开麦拉最近),然后得到该采样点的纹路坐标偏移。然后对速度向量采样时,运用这个偏移。这样相当于对速度向量离开麦拉最近的部分进行扩张,这样就处理了物体边际锯齿的问题。

抗闪耀

终究一个问题,也是最难处理的问题,就是TAA颤动的时分,形成一些像素当时帧被光栅化了,但到了下一帧又消失了,这就导致之前核算颜色围住盒时,前史帧的颜色与当时帧颜色距离过大,被裁剪掉了,这时就会呈现十分显着的闪耀问题。

WebGL高质量实时人物烘托

这儿咱们的处理办法是再多申请一张RT,记录上一帧的颜色,然后依据速度向量的差值混合当时帧和上一帧颜色。这个办法初衷是运用两帧颜色,尽可能还原更多高频信息。

WebGL高质量实时人物烘托

左:单帧 右:2帧混合

WebGL高质量实时人物烘托

咱们能够观察到头发丝的成果也愈加稳定,改进了发丝时断时续的情况。尽管目前画面仍有一些闪耀问题,但已经能够被接受。

WebGL高质量实时人物烘托

左:TAA 中:MSAA 右:SMAA

颤动半通明

半通明烘托一直是光栅化烘托中的难题,纯半通明烘托又和烘托次序休戚相关,要处理次序问题,咱们能够在美术资产制造的时分严厉按照次序进行分组与拆分,但这样无疑对美术制造负担过重。假如咱们运用相似深度剥离、权重混合等OIT技能,作为移动渠道开支又太高了。至于像链表OIT WebGL不支撑,咱们即期望开支足够低,又能够无视排序问题,还能够取得不错的半通明作用,那有没有这样的处理计划呢?答案是有的:颤动半通明(Dithering Transparency)。值得一提的是,目前市面大多数3A游戏也在运用这个技能。

WebGL高质量实时人物烘托

但请留意,这个技能需求配合TAA一起运用,假如单纯运用颤动技能并不能取得很好的作用。

此外关于颤动的pattern,规则颤动能够取得较平滑的成果,可是因为其原理没法保存背面的半通明信息,相当于掩盖掉了。咱们的处理办法是在规则颤动中参加一些随机颤动:

WebGL高质量实时人物烘托

*左:半通明裁剪 中:规则颤动 右:规则颤动 随机颤动*

软暗影

一个好的暗影作用,将会大大提高画面的实在度,Three.JS内置4种暗影类型:

WebGL高质量实时人物烘托

  1. 未过滤,锯齿感严峻,无法运用
  2. PCF比较上面多了几次采样,但仍然有锯齿感
  3. VSM关于平面投影作用十分不错,可是关于杂乱曲面物体,瑕疵较多
  4. PCF Soft尽管消除了锯齿感,可是半影规模无法调整

综上所述Three.JS内置的暗影均不契合预期作用,咱们的诉求是不要有显着锯齿感,且能够有较大的半影规模。

泊松散布

咱们运用泊松盘(Poisson Disc)对暗影贴图进行采样,并且每次会随机旋转一个角度,来消除规则pattern。终究咱们配合TAA消除噪点:

WebGL高质量实时人物烘托

左:旋转泊松盘 右:泊松盘 TAA

泛光

一般来说咱们的显现设备一般不支撑HDR(高动态规模),所以咱们需求模仿光线在薄膜中的次外表散射(胶片、镜头滤光片、视网膜等)。在PBR管线下,镜面反射的动态规模一般十分高,此技能能够协助物体表现相对亮度,或给LDR图画增加实在感。

WebGL高质量实时人物烘托

Three.JS中包含多个内置的Bloom、Glow作用,但作用往往是一种简略的含糊,不契合咱们对高动态规模亮度泛光作用的预期。

根据物理的泛光

(Physically Based Bloom)流程如下:

WebGL高质量实时人物烘托

首要对原画面图做一个阈值处理,过滤出亮度超过阈值的颜色,然后对这个颜色进行降采样并进行含糊,每次下采样的纹路尺寸将是之前的一半,一般咱们迭代7-8次,因为迭代次数越多,终究Bloom能溢出的规模将越大。达到最低的mip等级后,咱们就能够进行上选用,这儿需求留意,所有mip等级都需求耐久保存,将当时等级和前一级含糊的图画进行混合,混合因子也决议了溢出规模。

泛光通明穿透

完结上采样以后,终究一步是和原图颜色混合,一般来说在Linear颜色空间下运用加法即可。

因为咱们的项目还需求通明布景,仅仅对Alpha通道进行含糊处理仍然会有光晕黑边问题。

这儿咱们将终究Bloom颜色转换到HSV颜色空间,将V值保存为Alpha,然后将V值设为1。

WebGL高质量实时人物烘托

总结

经过上述的技能计划重构和优化,咱们在Web上完结了契合预期的3D数字人烘托作用。横向比照头部的移动端数字人竞品,在CG和仿真风格范畴,咱们具有较大的竞赛优势,特别是在人物要害特征的还原和光影作用的复现上。在未来的迭代中,咱们将持续在捏脸换装,人物面部/身体动画,互动特效方向上持续深耕作用优化,打造更具职业竞赛力的数字人个性化动态烘托处理计划。

参阅文献

Zioma, R. (2015). Optimizing PBR [PowerPoint slides].community.arm.com/cfs-file/__…

Jimenez, J., & von der Pahlen, J. (2013). Next Generation Character Rendering [PowerPoint slides].www.iryoku.com/stare-into-…

Penner, E. (2011). Pre-Integrated Skin Shading [PowerPoint slides].advances.realtimerendering.com/s2011/Penne…

Karis, B. (2014). High Quality Temporal Supersampling [PowerPoint slides].de45xmedrsdbp.cloudfront.net/Resources/f…

OpenGL Tutorial. Tutorial 16 : Shadow mapping.www.opengl-tutorial.org/intermediat…

Christensen, A. P. (2022). Physically Based Bloom.learnopengl.com/Guest-Artic…