ray tracing
1.Ray Tracing Overview
光线追踪是一种渲染技术,通过渲染物理上精确的反射、折射、阴影和间接照明,可以真实地模拟场景及其对象的照明。光线追踪通过跟踪光线从视点相机(决定人对场景的视图)经过2D查看平面(像素平面),进入3D场景,然后回到光源的路径来生成计算机图形图像。当光线穿过场景时,光线可能会从一个对象反射到另一个对象(造成反射),被对象阻挡(造成阴影),或者穿过透明或半透明对象(造成折射)。所有这些相互作用结合起来,产生像素的最终颜色和照明,然后显示在屏幕上。选择这种从眼睛/相机到光源的反向追踪过程,因为它比追踪从光源发出的所有光线在多个方向上的效率要高得多。
另一种理解光线追踪的方法是,现在环顾四周。你看到的物体是由光束照射的。现在,从你的眼睛开始,沿着这些光束的路径向后看,直到看到与光线相互作用的物体。这就是光线追踪。
光线追踪的主要应用是在计算机图形学中,包括非实时(电影和电视)和实时(视频游戏)。其他应用包括建筑、工程和照明设计。
在游戏中的实际表现,猜猜哪个是路径追踪(Path tracing)/光追(Ray tracing)/光栅化(Rasterization)
结果:
以下部分将介绍渲染和光线追踪的基础知识以及常用的术语。
2.Ray Tracing Fundamentals
光线投射(Ray casting)是光线追踪算法中的一个过程,它从相机(眼睛位置)通过图像平面中的每个像素发射一条或多条光线,然后测试这些光线是否与场景中的任何图元(三角形)相交。如果穿过像素并进入3D场景的光线击中了一个图元,那么就可以确定从原点(相机或眼点)到图元的沿光线的距离,并且图元的颜色数据会影响像素的最终颜色。光线也可能反弹并击中其他对象,并从它们那里获取颜色和光照信息。
路径跟踪(Path Tracing)是一种更密集的光线跟踪形式,它通过每个像素跟踪数百或数千条光线,并在到达光源之前跟随光线在物体上多次反弹或穿过物体,以收集颜色和照明信息。与Ray tracing相比,传统ray tracing每个像素只有1个光线(ray),而path tracing每个像素有多个光线(multiple ray)。
Bounding Volume Hierarchy(BVH)是一种流行的光线追踪加速技术,它使用基于树的“加速结构”,该结构包含多个分层排列的包围盒(包围体),这些包围盒包含或包围不同数量的场景几何体或图元。对场景中的每个图元交点测试每条光线效率低下且计算成本高昂,BVH是可用于加速它的众多技术和优化之一。BVH可以以不同类型的树结构组织,每条光线只需要使用深度优先树遍历过程对BVH进行测试,而不是对场景中的每个图元进行测试。在首次渲染场景之前,必须从源几何体创建BVH结构(称为BVH构建)。下一帧将需要新的BVH构建操作或基于场景变化的BVH重新拟合。
去噪滤波(Denoising Filtering)是一种先进的滤波技术,可以在不需要额外光线的情况下提高性能和图像质量。去噪可以显著提高噪声图像的视觉质量,这些图像可能由稀疏数据构成,具有随机伪影、可见量化噪声或其他类型的噪声。去噪滤波在减少光线追踪图像渲染时间方面特别有效,并且可以从光线追踪器中生成高保真图像,这些图像在视觉上看起来没有噪声。去噪的应用包括实时光线追踪和交互式渲染。交互式渲染允许用户动态地与场景属性进行交互,并立即在渲染图像中看到其更改的结果。
3.Ray Tracing Pipeline
对于传统的光栅化(rasterization)pipeline,其通过在commandbuffer中提交关于vertex、index的信息,最后通过"vkCmdDrawIndexed" 确定绘制的图元,最终由
vkQueuePresentKHR 进行展示。 对于ray tracing的pipeline,则不会涉及具体的vertex信息,因为已经在加速结构中进行处理。不需要直接暴露在render loop的过程中。同时在descriptor set中已经提供了足够的信息,所以对于ray tracing pipeline采用“vkCmdTraceRaysKHR”的方法进行绘制。 对于渲染完成后的cleanup两者大同小异,这里不再赘述。所以抽象下来,ray tracing pipline的流程可以抽象为:作为对比,光栅化(rasterization)的pipeline为:
能看到,两者在setup application, set pipeline, render loop, offscreen render等阶段都有所不同,尤其是setup application和set pipeline阶段。
4. New Concepts Compared with Rasterization
4.1 Acceleration Structures
加速结构(AS)的目的是提高ray tracing的计算效率,我们可以将其与soft ray tracing render(就是CPU端实现的ray tracing)中的实现方式进行对比。 Ray tracing需要对于vertex构成的物体进行更高效的组织,以提高计算速度并避免不必要的计算。在面向大量三角形的场景中,相交测试计算可能非常耗时,而加速结构的目的就是解决这个问题。 在soft ray tracing render 中有许多实现方式,例如:BVH(Bounding volume hierarchy)、八叉树(Octree)和kd-树(kd-tree)等多种数据结构可供选择。在硬件实现中,我们无需亲自管理底层数据结构,因为硬件提供了其他方式。 硬件将这个问题分为多个层次的架构,对于软件开发者而言,有两个层次是可编程的:一个是顶层加速结构(Top-Level Acceleration Structures,TLAS),另一个是与之配合的底层加速结构(Bottom-Level Acceleration Structures,BLAS)。这种分层架构有助于简化开发过程,同时充分利用硬件资源以提高光线追踪性能。
4.2 Pipeline Difference
Pipeline部分是rasterization pipeline 和 ray tracing pipeline之间的核心区别所在。 对于光线追踪,有两种管线可供选择:Ray Query 和Ray Tracing。 Ray Query更接近soft render的工程结构并且理解起来更容易,通过使用Compute shader进行处理,更适用于通用计算任务,如视频编解码和图像处理。 Ray Tracing管线在实际工程中使用更广泛,更适合成像任务。 Ray tracing的一个挑战在于,与光栅化不同,无法根据不同的材质划分不同的渲染顺序来选择着色器。 但是对于ray tracing 是不可能根据intersect的情况选择的,在tracing的过程中,所有的shader都必须随时可用。这部分的功能会通过 Shader Binding Table(SBT)功能来实现,SBT将在后续进行解释 为解决这个问题,引入了Shader Binding Table( SBT )的概念,后续将对SBT进行详细解释。 光线追踪管线主要由三个部分组成:shader stage、fix-function、layout;与rasterization有明显区别的部分在shader部分。Ray tracing shader stage 中涉及到多个shader:
- Ray generation shader
在图像中的每一个像素都需要通过 tracing来获取,在soft render中,光线的生成涉及到相机位置和FOV(Field of View)配置。同样在光线追踪管线中,需要使用着色器内置函数
traceRayEXT进行处理。- Miss shader
光线生成后,需要在场景中进行相交测试,判断光线与哪些物体相交。这里的光线不受材质限制,会检测所有可能的交点。当加速结构(AS)判断没有交点时,Miss着色器开始工作。通常需要多个Miss着色器,因为hadow ray 和primary ray需要分开处理。
- Closest hit shader
根据上一个着色器的相交测试结果,生成距离光线起点最近的交点,并计算光线的radiance;类似rasterization pipeline中fragment shader的作用,控制最终的图像结果。
- Intersection shader
对于特定的图元进行intersect test,因为有些特殊的图元可能不在blas中,所以需要自定义判断相交的条件
- Any hit shader
通常用于透明场景,用于判断多个点中哪个点走Closest Hit shader,从而构建一些风格化效果。
而在descriptor set方面,ray tracing 还需要一些额外的信息,例如TLAS就需要通过descriptor set 以告知shader,大部分descriptor set的配置与rasterization pipeline类似,不再展开赘述。
4.3 Shader Binding Table
ray tracing pipeline中包含多个shader stage,因此需要一种机制进行调度和管理。
这个机制就是Shader Binding Table (SBT),它包含了所有的着色器以及一些附加参数。这样,在光线追踪过程中,可以调用各种着色器及其参数。这整套结构作为SBT的基本单元 - Shader Record。
Shader Record包含一个或多个着色器以及一些附加数据。这些附加数据会在运行时传入着色器中。
每个Shader Record都需要作为一组function handle才能写入SBT中,因此,涉及到GPU中句柄对齐(Handle Alignment)的问题。为了提高GPU的效率,通常需要进行对齐处理。在同一个组中,两个handle的地址差距必须是shaderGroupHandleAlignment的整数倍。
Shader Record包含一个或多个着色器以及一些附加数据。这些附加数据会在运行时传入着色器中。每个Shader Record需要作为一组函数句柄才能写入SBT。因此,涉及到GPU中句柄对齐(Handle Alignment)的问题。为了提高GPU的效率,通常需要进行对齐处理。在同一个组中,两个句柄的地址差距必须是shaderGroupHandleAlignment的整数倍。
解决了着色器的组织管理问题后,还有一个调度问题:
当光线与一个几何体相交时,该如何知道哪一个着色器应被调用?
如果是soft rendering的情况下,反正geometry和material的信息都在CPU侧,通常在判断交点时可以直接获取对应的geometry和material了,自然可以选择对应的方式来计算radiance。
但是在GPU环境下,具体的geometry的排列顺序、BLAS中的信息、光线的相交判断都在不同的shader、甚至可能在不同的pipeline中,这问题就变得难以解决。
因此,需要一种机制,能让shader与BLAS中的geometry进行联动,定位到底需要哪一个shader,在BLAS中由于有各种geometry的reference,可以提供一个index用于定位,类似每个geometry分配一个ID。这样可以提供给SBT一个offset,让SBT的hit group获得起始位置。
可以将SBT的hit group records类比为一个array,我们知道SBT的地址头,也知道剩下的shader是对齐排列的,但是如何知道所需的着色器在哪里,就需要一个公式:
其中
HG就是地址,所需要的地址就是: 地址头 + (预设的offset + SBT hit group recoreds的步长 + geometry的ID + sub-table的hit group recored所开始地方的offset ) 通过这种方式,最终构建出着色器的索引。在着色器中,对应的代码如下:
void traceRayEXT(accelerationStructureEXT topLevel,uint rayFlags,uint cullMask,uint sbtRecordOffset,uint sbtRecordStride,uint missIndex,vec3 origin,float Tmin,vec3 direction,float Tmax,int payload);
(sbtRecoredOffset对应公式中的 、sbtRecordStride 对应公式中的 ) 通过这种方法,可以完成对着色器的调度。假设是miss shader,首先确保所有的Hit Group经过
shaderGroupBaseAlignment处理后,每个着色器的入口再经过shaderGroupHandleAlignment的对齐处理,就可以通过公式获得着色器组的handle5.Memory in Ray Tracing
5.1 same memory part in Rasterizatgion
vao, vbo
5.2 Ray tracing specific memory
5.2.1 shader binding table
shader handle, 包括ray generation shader, miss shader, closest hit shader, intersection shader, any hit shader
5.2.2 acceleration structures
TLAS, BLAS
5.2.3 ray tracing API(vkCmdTraceRaysKHR...)
None
浙公网安备 33010602011771号