GDC2016 Global Illumination in Tom Clancy's The Division

# brief
- 最终是使用irradiance volume做realtime rendering
- 用烘焙好的PRT参数来计算irradiance volume:这个过程叫做relighting
- PRT参数是用ambient cube存的,觉得比SH2好
- relighting的过程是算每个probe收到的radiance = 被遮蔽的天光+(周围surfel的exit radiance通过PRT对这个probe的影响)


# introduction
- precomputed radiance transfer probes
    - 说是支持动态light source、area light、bounce、great accuracy
- high frequency dynamic light sources
- fast, GPU-friendly
    - low memory requirement
- production
    - 快,修改后很快能反馈
    - 需要处理漏光
    - 室内外都用同样的方法
- open world
    - 地图极大,objects极多
    - lightmap不可能,probes essential to manage production complexity
    - light probe或者irradiance volume不需要UV,如果只是改个小模型不需要rebake
- Day-night cycle
    - ambient lighting quality is important
        - 由于sun direction一直在变,所以也就不能cheat了
        - 有些地方总是在shadow里(被高楼挡住)
    - prt使得artists可以tweak lighting for any time of day
        - 难道不同时刻用不同的probe?
    - 说是completely dynamic and editable,no rebake required
        - 难道这些probe本身不用bake?
- interior lighting
    - 大量用dynamic light
    - 有些室内也是被time of day影响的
    - prevent probe bleeding
- dynamic weather
    - 各种环境参数
    - prodedural snow


# precomputed radiance transfer
- prt原理
    - figure out the light transported between surfaces for a fixed scene
    - 信息可以存在vertex、texture或者probe上
    - only support distant light sources
        - hdr probe,directional lights
        - farcry3有develop support dynamic local light(too heavy and inaccurate, 最终没用)
        - high frequency shadow(目前没人用,因为shader complicated)
- our approach
    - brutal force
    - 存每个probe能看到的surfel信息(实际烘焙时我感觉就是去raytrace cubemap上的各个方向)
    - similar to G-buffer cubemap,也就是说可以存各种数据,包括snow buildup
    - 对于trace不到东西的,那就算是碰到sky了,所以probe还可以存个东西,那就是sky visibility(天光者遮蔽度)
        - spherical shadow term(这啥?天光shadow?)
        - long range AO
    - transfer basis
        - 实际存的信息是cosine convolution,频率够低
        - 2 candidate
            - SH2(rotation invariance),说是相当于有1个principal direction light + 1个ambient value,这搞就是如果有2个非常强的光源的时候,这个模型就完全对不上了    - 4 float
            - ambient cube(最终获选。。。。我猜是因为你总共可以handle有6个强光源的情况)
                - 6 floats
                - 连orthogonal basis都不是
                - rotate light source的时候只不过是在不同direction间blend


    - probe placement
        - automatic probe locations
        - raycast grid: 4m spacing, spawn probe on ray hit
        - 避免intersect objects
        - automaticly spawn probe along walls to avoid flat-looking surfaces
            - 这个主要是为了获得sky visibility数据
    - probe storage
        - 地图划分成一个个64mx64m sector,每个sector最多1000个probe。typical 200-300.主要和建筑高度啥的有关
        - 存的就是array(带自己的位置,并不是grid存)
        - runtime最多25个sector同时存在
    - surfel sharing
        - runtime要relight probe(我感觉就是要根据surfel的exit radiance(对于probe来说是source radiance)),需要先算surfel表面的radiance,然后根据PRT数据算出到达probe的光照?
        - PRT涉及到cluster,他们说是急着implement所以用two-level hash grid
            - first level
                - average positions normals, albedo
                - index with position and principal normal direction(使用hash?)
                - cell size 1x1x1m(糙了就搞不出spotlight了)
            - second level
                - combines multiple surfels into irradiance brick
                - cellsize 4x4x4m
                - 问题是:和level1的联系?
        - probe实际reference的是brick而不是surfel
            - 为了降低relight probe时的计算
    - 实际存储
        - probes
            - position
            - sky visibility: HL2 cube coefficient
            - factor range: index into brick factors array
        - brick factors
            - basis weight
            - brick index
        - brick
            - 就是surfel array中的一段
        - surfel
            - position normal albedo(注意这些应该是有真正的surfel average得来的)
    - baking process
        - 对probe生成个gbuffer
        - readback,put surfel into hashgrid,再计算平均值和irradiance brick
        - manhattan有1GB数据,4k个sector,1Million probe, 56Million surfels


# runtime rendering
- relight surfels
    - calculate lighting on surfel
    - average into bricks
- relight probes
    - calc lighting from ksy
    - sum up brick and sky irradiance
        - 用了irradiance volume, volume texture, 1 RGB/1 direction
- shading
    - generate irradiance volume
    - shade pixels
- relighting
     - relight probes every frame on GPU
        - 先relight surfel,然后累加平均出brick的radiance
        - 然后是对每个probe
            - 6个面上的sky visibility * sky_coefficient叠加
                - render sky to a small texture
                    - sky用了很复杂的技术组合
                        - 有个什么pre sun sky model(听的不太清楚,字幕感觉是错的)
                        - 6个point lighting cloud texture(allow dynamicly light them based on where the sun is)
                    - 大概就是说sky是真的有模型,而且模型由光照的,这样真的能做出动的天空
                - compute cosine convolution, store as ambient cube
            - 所有brick的irradiance * brick对probe的影响系数叠加
     - 每一帧重新relight,而不是在已有结果间差值,这样就能让人看到一些持续时间短暂的GI effect
        - 比如某个东西只在一天中很短的一个时段被直接照射到,用差值就完全插不出来 
- sun shadow
    - surfel计算时会用到shadowmap,远处的东西没有shadowmap,所以远处surfel计算可能出错。比如阴影里的probe亮了
    - 解决方法是:keep track of the last known shadow sample of surfel。cache曾经的正确值结果
- local light irradiance
    - 算surfel时要把brick附近的light考虑进去
    - 对于static light,可以存一下中间结果
- procedure snow
    - 也可以用probe这一套来搞,物体表表面雷加了多少雪
- multiple bounce
     - 在算surfel光照的时候,可以用之前的probe的结果来做环境光,这样形成feedback


# performance
- relight 2 sectors each frame
    - 1 where player is
    - 600-800 probes
    - 用async gpu compute做的
- 典型性能(鬼知道是拿具体哪个位置算的)
    - pc, GTX 760 0.47ms
    - xbox one, 0.95ms
    - 60%是light bricks, 40%是light surfels(PC是50%+50%)


# irradiance volume
- store irradiance in volume texture
    - 所以,实际使用的时候还是用grid来存irradiance。。。。。。 probe上其实只是个中间概念
    - 说是这么做也是为了能有trilinear filtering, in order to support large objects or small objects
    - volume map follows camera, overs 100x50x100m, 32x16x32 voxels per direction....
- interior volume
    - 因为实际的volume texture精度实在低,室外还行,室内漏光啥的
    - 所以用stencil来区分室外、室内(实际上好像是在object级别判断是indoor还是outdoor),感觉是因为用了deferred所以不得已这么做,forward反而简单
    - indoor,outdoor用不同的volume texture 
    - 处理房间之间的bleed
        - determine房间在volume space的extent
        - clamp read to just that AABB(自己都知道只有axis aligned才管用(那也就意味着美术得配合。。。))


# distant shading
- large 2d texture outside irradiance volume(就是摄像机的100x50x100范围外的),感觉是不是就是个2D的,不管高度
- each texel是一个sector probe,就是placed得特别高的probe
- 这个probe只搞天光


# ambient occlusion
- 用AO做ambient light的shadow term
- 这里只想把AO作用到sky light上,brick的贡献不想收AO影响,但是要那样搞就是得把2项分开存就麻烦了,所以还是都影响了
- 说是车底下的AO难做(我想是因为SSAO管不着、probe又管不着这么靠近地面的地方)
    - trick了一下,用了screen-space projected decal(给一张gradient teture,到时候东西只输出到gbuffer的ao通道上)
    - 我不太理解。shadowmap搞不定这个嘛?(也许是指阴天)
    - 想了下,要想在没有直接光阴影的情况下做出东西的立体感,用ambient的阴影来搞,确实有点麻烦。。。


# Volumetric lighting
- volumetric fog
- store average probe irradiance in volume map
- raymarch(simulate participating media)的时候sample volume map
    - 回头看下体积雾到底应该咋搞,用raymarch太耗了吧?每帧要重新计算还是一次就好?


# post mortem
- initial approach
    - 还是用irradiance volume
    - 但是不会offline bake,而是online 生成cubemap
    - 挺好,但是update速度太慢,会看到很明显的poping,也就不好搞day night cycle啥的了
- transfer basis
    - 刚开始用8 vector non-orthogonal basis,美术觉得strreet too dark。查了下发现是因为没有直上直下的vector,直上直下方向都是插值出来的
    - 所以还是换回HL2了
- probe placement
    - 自动摆probe难摆,比如比较细小的(如脚手架)会miss
    - 给artist更多control
    - 房子这种可以根据UV的密度来合理地自动place probe,另外说是只要tangentspace的3个方向而不是6个方向就够
- interior volume
    - sharp transition from outdoor to indoor(indoor门口可能忘了布 probe),因为正好是indoor outdoor irradiance volume的交接
- resolution accuracy
    - improve probe and surfel resolution
        - baking time减少和数据compression
    - multi bounce是coarse approximation(用之前的probe结果做ambient)
        - 没时间做了,觉得之后可以做gpu tracer,offline地烘焙出multi-bounce的prt参数
- bugs
    - 由于snowdrop和division是同时开发,很多bug没法搞,所以就给更多parameter让artist去trick,结果参数老多
    - bug修好后有些参数就直接没用了,所以lighting artists很尴尬


# QA
- 在sector边缘会不会有问题:使用了trilinear filtering,另外在不同的sector间也有filtering。mask了一些问题,但是一直有
- 如何validate accuracy,又没有bug tracer:we just tweak until it looked fine and our director said this is good.


# related
- PRT详细信息:siggraph 2005 course note

猜你喜欢

转载自blog.csdn.net/killer4747/article/details/80865525
tom
今日推荐