|
一,光线追踪
1,光线投射
光线投射提出了光线追踪算法的基本理论,即从当前屏幕的每一个像素发射光线,然后进入场景中追踪,直到找到第一个Target Object求交同时向光源发射一条Shadow Ray,计算光照并依据属性进行着色。Arthur Appel在1968年提出了这种反向追踪光线传播的方法,不过当时的思路还比较朴素,无法计算环境光照,也没办法模拟复杂材质的物理光照传输过程。
2,递归式光线追踪
1979年,Turner Whitted基于光线投射的思想提出了一种新的算法思路——递归式光线追踪(Recursive Ray Tracing)或者Whitted-style 光线跟踪方法。
在Whitted Style Ray Tracing中引入了四类光线:View Ray, Refelction Ray,Refrection Ray, Shadow Ray。其过程如下:
如下图所示,从视点出发向屏幕上每一个像素发出一条主光线Ray,光线穿越像素点后继续向场景中运行,直到遇到Object求交然后在交点处向光源方向发出一条阴影射线(Shadow Ray),这条辅助射线主要用于判断主光线-网格交点与光源间是否存在第三方遮挡。
如果没有遮挡,那么该点发生的就是直接光照;如果有遮挡,那么该点发生的就是所谓的环境光照,同时光线与Object相交时会根据Object自身的属性确定是发生折射,反射还是漫反射【Tips:显然该模型中光滑物体被简化为了绝对光滑,粗糙物体被简化为了绝对粗糙】。如果是漫射面则直接计算颜色;如果是镜面或者折射面,则主光线会在交点处重新产生次级光线继续追踪直到找到第二个Object交点,然后重复上述过程,直到阴影射线可以直接定位光源或者主光线递归次数达到保险起见而预先设定的一个最大深度,或者直接射向cube而结束。
很显然上述方法虽然考虑了环境照明,但是网格求交的过程对光线与物质表面作用的过程还是表述的不够细腻,且只被允许生成反射光线或者折射光线,因此只能模拟粗糙度很高或者非常光滑的材料。今天我们通过前人的研究得以知道光线在物料表面的反馈是及其复杂的,可能同时存在散射,吸收与反射。
3,分布式光线追踪
1984年,Cook将蒙特卡洛计算的思想引入给光线追踪的研究中,提出了分布式光线追踪算法(Distributed Ray Tracing),又称为随机光线追踪(stochasticray tracing)。
引入蒙特卡洛运算后,在交点处view Ray被拆分为射向不同方向,分布呈现随机但整体有序的多条次级光线继续追踪。物料表面不再被简单的认为是绝对光滑或者粗糙的,集中的高光与相对均匀的漫光模拟使得材质表现更为丰富,真实。但这带来了一个新的问题——光线在追踪过程中会呈几何增加,逐渐形成树状结构。真实的代价是更为庞大的运算量。
4,重要的转折点
1986年,Kajiya在前人研究的基础上建立了统一的光照传输理论,并给出了其具体的数学表述,也就是后来的渲染方程:
同时给出了物体表面某个方向上的出射Radiance与入射Irrandiance的关系:
二,路径追踪
同年,Kajiya提出了路径追踪的概念,为了解决分布式光线追踪庞大的光线分支运算量以及针对漫反射几乎无解的困境,他决定从数学入手。
1,渲染方程的面积积分形式
首先渲染方程是一个隐式方程,为了计算某一点的出射辐射率一个潜在条件是必须获得所有射入该点的入射辐射率,这个次级光线投射的过程正是分布式光线追踪难以计算的来源。如果使用t(p.w_i)表示光线投射函数所获得的交点p',即从p点出发沿着w_i反方向发射一条光线的得到的第一个交点p`,那么渲染方程就可以改写为:
既然无法显示的表示t,就只能接受一个无穷递归的事实。问题的关键还是在方向积分上,入射辐射率可以理解为每单位立体角的辐照度到达物料表面,出射辐射率可以理解为每单位投影面积的辐射强度离开表面,如果能将方向积分转变为面积积分,就可以把辐射点的路径关系显示的表示出来。为了完成这一数学变换,首先要去掉方向w_i与w_o,改写f项,
上图所示的三点式路径法是将方向转化为面积积分的关键,从场景中点p'到点p(或者说单位面积p'到单位面积p)的辐射度可以表示为:
那么w_o = p - p', w_i = p' - p'',则对应的BRDF就可以表示为:
其次是去掉式子中的dw_i, 根据Solid Angle的定义也很容易将方向微分dw转化为dA,即:
考虑微表面理论,则实际应该按照垂直与半径方向的投影面积进行计算,因此关系式被修正为:
再处理完上述两步后,为了简化方程将上述立体角的转换式,原始渲染方程中的cosθ项,还有一个可见性函数V(两个点相互可见时V=1,否则V=0)组合成一个单一的几何项G(p<->p&#39;)
则渲染方程的面积积分形式为:
这个方程与方向积分形式的方程在数学上是等效的,并且在追踪场景光照时每次迭代的项直接显式地使用场景中某个表面点进行表述
当跌代次数累加时,面积积分方程可以进行递归展开:
上式中的每一项可以表示为一条由多个顶点组成的路径,如果继续追踪,对于L(p3,p2)则是一份二重积分的自发光项和三重积分的反射项..... 归纳总结法可以得出结论,对于一条由n+1个顶点组成的路径P_n来说,其总的辐射亮度贡献为:
路径顶点即采样点的顺序为p0,p1,.....pn(p0为摄像机位置),BRDF函数累乘可以理解为整条光路上的光吞吐量,可以用T(pn)表示:
方程可以进一步简写为:
这是一个n-1维的高维积分,而路径追踪就是计算所有路径辐射亮度贡献的和:
对于每一个长度为n的路径来说,可以使用蒙特卡洛方法来计算其对应的高维积分,路径样本对应的概率密度就是T决定的
2,路径追踪
在把方向积分转换为面积积分后,某一个像素的颜色值计算就由原来对辐射亮度递归式积分求解的过程变成了对若干顶点组成路径的采样与过滤的过程。因此路径追踪算法需要解决两个基本问题:
- 当路径比较长时,BRDF的累乘结果会变得非常小,对照明贡献来说就不那么重要,因此怎样以不引入偏差的方式结束对路径的追踪是一个问题;
- 如何对路径进行采样,这是路径追踪渲染器的算法核心,决定了渲染质量与渲染速度。
2.1,渐进式俄罗斯轮盘
为了解决第一个问题,需要引入一种叫做俄罗斯轮盘的算法,一条路径有q的概率被终止(q被设计为一个递增数列来保证越往后的项截断概率越大),1-q的概率被继续追踪,但考虑到终止系数是与路径贡献度没什么必然关系的,为了避免一些有着重要光照特性的路径被终止,因此使用前一般先设置一个临界值,然后再使用俄罗斯轮盘来终止路径追踪
2.2,路径采样
为了避免暴力追踪,将采样分为了三种不同类型的采样:
初始光线就是由摄像机沿屏幕空间向场景发出的第一条光线。那么什么是直接光源采样呢?对于路径上的某一点P_i来说其直接光照可以由该顶点向光源方向发射Shadow Ray来获得,这一部分应该有自己的采样方式,因为它是有别于路径递归所提供的间接光照的。
对于P_i来说可能不止有一盏光源提供贡献,因此直接光应该同样满足重要性采样,对于那些贡献度较高的光源应该被分配更多采样分布。同时考虑所谓的PBL,对于单个光源其几何形状也应当被考虑进去。
路径采样则提供了所谓的环境照明,它占据了诺大场景中打亮物体主要的贡献,同时提供了很多非常有趣的光照特性,例如实时体焦散。那么如何拾取出最有价值的光路均衡收敛速度与画面质量(更少的噪声,更真实的几何光学特性)就成为了各家渲染器的独门绝技,非常多的采样方案被提了出来比如双向路径追踪(BDPT),光子映射(PM),梅特波利斯光线传输(MLT),顶点连接与合并(VCM)等等,会在其他文章中详细展开叙述。
当然上述只是一个大概过程,还有很多细节需要讨论。比如阴影问题,UV,纹理过滤,Anti-Aliasing,抗锯齿,降噪技术,景深,负载均衡等等,光线追踪的算法研究有着
三,DXR概述
1,双层加速架构
为了加速光线相交,DXR内置了一个基于BVH的双层加速结构
Bottom-Level-Acceleration-Structure(BLAS)定义了几何体的基本组成。如果Object是网格形式就是三角面的顶点索引,也支持其他组织形式比如体素,曲线等,但要自行构建加速方式。Top-Level-Acceleration-Structure(TLAS)定义了场景实例层的相关属性例如包围盒,变换矩阵等数据。
当追踪开始时,View Ray会先与AABB包围盒做一个粗略的预判断进一步缩小相交范围,当与几何面片相交时会依据对应Object id的Local Root Signature从Shader Table找到对应的Shader Recard。如下图所示每一个Shader Recard都包含一个唯一的着色器标识符——定义了具体的着色器命中组,是使用哪类Shader,以及配套的shader实参
那么不同的着色器类型在DXR中承担着怎样的职责呢?
2,着色器分类与ShaderTable
DXR将shader大概分为了5类
- Ray Generation Shader :光线生成着色器,使用TraceRay()函数指定启动哪些光线
- Intersection Shader:相交着色器,负责光线与三角面的相交处理
- AnyHitShader:调用IgnoreHit函数来判定是否忽略这次相交,主要用于处理半透明
- ClosestHit Shader:当光线追踪到距离光源最近点时执行该shader进行渲染
- MissShader:如果光线没有与任何物体相交则调用该shader(直接射向天空盒)
其中InterSectionShader,AnyHitShader,CloseetHitShader共同组成一个命中组(Hit Group),每一个几何面片都可以有自己的Hit Group,这是与光栅化管线在硬件层面以Batch为单位非常大的一个不同。
3,DXR管线
Ray Tracing Gems上给出的DXR渲染流水线如下图所示:
与光栅化Pipline的Render Technology类似,RTX Pipeline也有一套自己的RTPSO,DXD12的RTPSO包含了很多subobject,包括RT Shader, root signature,以及一系列配置数据。下面这张图更清晰的展示出整套管线中哪些部分是可编程的(绿色部分),哪些部分是固定管线:
可以看到虽然DXR提供了相关API接口,但BVH的底层实现对于开发者来说依旧是透明的,各家硬件厂商应该有自己的解决方案。
四,RTX在UE4中的工程应用
1,在UE4中集成DXR来支持RTX
UE4.22试验性的集成了实时光线追踪,但早在开放给用户前他们就做了大量的试验性工作,2018年与Nivida和ILMxLab合作推出了“星球大战”试验性短片,UE4集成了微软同年发布的DXR来支持Nividia的RTX技术,它们之前的关系大概如下图所示[11]:
最下层是硬件平台的支持,拿典型的Turing架构来说,依据白皮书的内容[12],每个流式多处理器都包含一个RT Core用于硬件层的BVH加速处理光线/三角形相交等环节,另外Nividia维护了一个私有的仓库用于为UE4集成DLSS(深度学习超采样)https://github.com/NvRTX/UnrealEngine,同样在硬件层有专门的Tensor Core用于处理这部分内容。
在往上层走,到了API这一层,受Nvidia OptiX的影响在扩展RHI层时简化抽像出了三个类,rtScene,rtObject, rtGeometry。顾名思义,一个rtScene实际上就相当于一个封装的TLAS(顶层加速结构),而一个rtGeometry相当于一个BLAS(底层加速结构),Hit Group与对应的跟签名是以rtObject为单位工作的。在实际工作的时候,对于静态网格体BLAS只需要构建一次,但是对于Particle,骨架网格体等来说,BLAS要不断更新来refit。为了让硬件能准确识别这些特殊的rtGeometry,UE4选择把动态物体的图元更新存储在GPUSkinCache。这个基于计算着色器的系统可以将每一帧的蒙皮执行到临时的GPU缓存中,这也就是为什么编辑器中启动Ray Tracing会自动启用GPUSkinCahce的原因!
应该说“星球大战”短片是一次尝试性试验以找到在延迟渲染管道中集成光线追踪的理想方式,需要考虑很多东西:多平台API,RHI层的变化,与光栅化管线的兼容,性能问题,着色架构统一以及尽可能减少对上层(逻辑层)的影响来降低用户学习成本等等。
2,混合渲染管道
为了支持光线追踪,UE4的MeshDrawPipeline进行了非常大的修改[13],最终实现了与延迟渲染管道的统一,也就是混合渲染管道(Hybrid Rendering Pipeline)架构。充分发挥光栅化,光线追踪与Compute Shader的优势针对性的解决场景GI,后处理,反射,阴影与AO以及特殊光学现象的模拟,同时避免纯光线追踪所带来的运算量问题[14]。
以SIG 2019 EA SEED分享的Hybrid Rendering Pipeline为例说明何谓混合渲染
对于UE4,其内部支持两套光线追踪系统:
- Hybrid Ray Tracer Mode:混合渲染模式,也就是所谓的实时光线追踪
- Path Tracer Rederence Mode: 无偏的蒙特卡洛路径追踪渲染器,一般用于Ground Truth的静帧渲染或者Sequencer电影,无法满足实时动态的要求
对于实时光追,目前已经包含如下特性:
如果要在场景中使用实时光线追踪需要在Post Process Volume中控制光线,这是因为UE4把所有的光追效果都看成了后处理的一部分,这样可以尽可能多沿用延迟管线原有的功能,对于那些对画面影响非常大因素,如反射,阴影【例如大面积区域光下的软阴影是光栅化很难解决的问题】,AO以及Transparency和Translucency的处理则使用光线追踪来获得更真实的照明效果,最后将光追特性渲染至RT再与场景信息混合到一起完成着色。在官方文档中可以找到这些照明特性在光追模式与传统光栅化模式下的区别[15]。
3,着色框架的改变与统一
原则上来说,UE4所使用的着色模型必须能够准确的支持光线追踪。但是光删化渲染管线的shader类型为Vertex Shader,Pixel Shader,Hull Shader, Domain Shader,Geometry Shader,Pixel Shader这些(UE4使用hlslcc实现跨平台编译),与光线追踪管线的5类shader完全不一样。
这个问题怎么解决呢?改Microsoft DirectX Compiler!【该工具已开源】,支持了一个从VS与PS的预编译DXIL表示中生成ClosesetHitShader与AnyHitShader的机制,将VS代码,Input Assembly以及PS代码作为输入生成最佳代码来执行索引缓存取值,顶点的Attributes取值以及格式转换。然后使用相交时的质心坐标对VS输出进行插值,再输入给PS。通过这样能够在不影响原有ush与usf开发的前提下,让整套着色体系支持光线追踪。
引擎中重构的shader数量非常多,细节的内容可以在Engine/Shaders/Private/RayTracing与Engine/Shaders/Private/PathTracing中找到光线追踪与路径追踪对应的着色文件
4,区域照明的支持
在另外一个实验短片“Speed of Light”中展示了巨型区域光源构建的影棚照明,为了能尽可能还原矩形光的物理特性,使用LTC(线性变换余弦)处理高光项,这项技术来源于2016年[16],沿用了线性变换球面分布(Linearly Transformed Spherical Distributions (LTSDs))的思路,使用一个3X3的矩阵将原本的BRDF分布变换为余弦分布,再以“梯度求解”的方法拟合出变换矩阵,然后将逆矩阵的参数预计算存储到LUT中。这样在实际运行时,shader中采样逆矩阵执行逆变换就能将原本复杂难以解析的BRDF分布转变为可解析的余弦分布,并保证高光形状的不变性。
图片来自论文,非UE4中测试
原始球面分布D0是用于替代D(BRDF)分布的,因此数学模型要便于解析积分,UE4参考了paper中的方案使用余弦分布。正变换的目的是为了找到合适的矩阵。经过变换后的立体角需要乘上一个Jacobian项来进行缩放,立体角的缩放值为 w/w_o【雅可比行列式J的推导可以在论文中找到】
红色区域原始立体角w_o投影区域,绿色区域为变换后得到的立体角w的投影区域
很显然变换前后的立体角积分是不变的:
如果假设D0为:
带入上面式子就有:
接下来只需要使用梯度下降法拟合出矩阵M就可以了,然后把逆矩阵存入一张LUT就可以在shader中精确,实时的还原矩形光的物理照明
BRDF与LTC的对比
这里只是简述线性变换余弦处理区域高光的核心思想,关于BRDF的处理,各向异性的支持以及LUT编码细节等暂不做详细展开,另外使用LTC对矩形照明方程进行变换有非常多巧妙的数学思想贯穿其中【个人认为是与球谐函数解决IBL卷积难题具有同等重要启发意义的方案】,深究可以阅读文末给出的引用论文或者去翻UE4源码。
5,Denoise方案
6,RTAO
7,RTGI
8,透明的处理
(肝不动了,先鸽~~,后面补,逃了)
Reference:
[1] 《全局光照技术》第五章
[2]https://yiwei.dev/path-integration/
[3] 《The Path to Path-Traced Movies》:https://graphics.pixar.com/library/PathTracedMovies/paper.pdf
[4] 《BI-DIRECTIONAL PATH TRACING》https://www.cs.princeton.edu/courses/archive/fall03/cs526/papers/lafortune93.pdf
[5] 《Rendering Participating Media with Bidirectional Path Tracing》
http://luthuli.cs.uiuc.edu/~daf/courses/rendering/papers/lafortune96rendering.pdf
[6] DXR SDK https://microsoft.github.io/DirectX-Specs/d3d/Raytracing.html
[7] 《Ray Tracing Gems》https://github.com/slongle/ray-tracing-gems-cn
[8] https://developer.nvidia.com/blog/introduction-nvidia-rtx-directx-ray-tracing/
[9] https://www.cnblogs.com/timlly/p/11366199.html
[10] https://www.openimagedenoise.org/
[11] https://www.codenong.com/s1190000038400421/
[12] 《NVIDIA TURING GPU ARCHITECTURE》白皮书
https://images.nvidia.cn/aem-dam/en-zz/Solutions/design-visualization/technologies/turing-architecture/NVIDIA-Turing-Architecture-Whitepaper.pdf
[13] UE4.22渲染系统设计浅析 https://lijiankuan.github.io/ue4/final-chapter1/
[14] SIGGRAPH 2019 EA SEED 《Are we done with Ray Tracing?》http://www.realtimerendering.com/raytracing/siggraph2019/Are_We_Done_with_Raytracing.pdf
[15] https://docs.unrealengine.com/4.27/zh-CN/RenderingAndGraphics/RayTracing/
[16] 《Real-Time Polygonal-Light Shading with Linearly Transformed Cosines》
https://eheitzresearch.wordpress.com/415-2/
对应的git仓库:
https://github.com/AngelMonica126/GraphicAlgorithm/tree/master/010_RealTimePolygonalLightShadingWithLinearlyTransformedCosines
[17] https://blog.csdn.net/xiewenzhao123/article/details/80709968 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|