# 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
- 最终是使用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