光线遍历
光线遍历过程识别并处理光线与加速结构中几何体之间的交点。
光线遍历不能由 Vulkan API 命令直接启动 - 着色器 必须 执行 OpRayQueryProceedKHR
或 管线追踪光线 指令。 当启用 rayTracingPipeline
功能时,OpTraceRayKHR
可以用于 光线追踪 在 光线追踪管线 中。 当启用 rayQuery
功能时,OpRayQueryProceedKHR
可以在任何着色器阶段使用。
光线相交候选确定
一旦开始追踪,光线首先针对顶层加速结构中的实例进行测试。与实例相交的光线将被转换为实例的空间,以便继续在该实例内进行遍历;因此,存储在实例中的变换矩阵必须是可逆的。
如果光线与多个实例相交,则光线变换到实例空间中时,在顶层加速结构中遇到这些实例的顺序是不变的。
对光线应用多个正向和反向变换以从一个实例过渡到另一个实例可能会导致累积误差。因此,实现应表现为光线是独立地从每个实例的原点变换的。 |
接下来,将光线与底层加速结构中的几何体进行测试,以确定它们之间是否发生碰撞,最初仅基于它们的几何属性(即它们的顶点)。该实现执行与光栅化类似的操作,但有效视口由光线的参数确定,并且几何体被变换到由该视口确定的空间中。
每个图元的顶点根据光线原点和方向从加速结构空间 as 变换到光线空间 r,如下所示
交点候选项是光线与几何图元之间唯一的交点。对于任何在其边界内具有位置
(其中
三角形图元边界包括由三个顶点形成的平面上的所有点,并且在顶点之间边的边界内,但须遵守以下水密性约束。AABB 图元边界包括在实现定义的边界内的所有点,该边界包括指定的框。
AABB 的边界包括边界内的所有点,这意味着在 AABB 内开始的光线将击中该 AABB。 |
此条件的确定以实现特定的方式执行,并且可以使用浮点运算执行。由于涉及的操作的复杂性和数量,预计会出现不准确的情况,特别是当涉及的值的比例开始发散时。实现应该努力保持尽可能高的精度。
一个非常常见的情况是,当几何体在加速结构空间中距离原点一定距离时彼此靠近,此时可能会观察到类似于“z 冲突”的效果。应用程序可以通过确保其详细几何体保持靠近原点来缓解这种情况。 另一个可能的情况是,当光线的原点设置为先前相交的表面上的位置时,其 tmin 为零或接近零;可能会在发射表面上检测到交点。这种情况通常可以通过稍微偏移 tmin 来缓解。 |
对于运动图元或运动实例,交点的位置是在 OpTraceRayMotionNV
的 time
参数中指定的时间,通过在给定运动类型的两个端点之间进行插值来计算的。如果使用 OpTraceRayKHR
跟踪运动加速结构,它的行为类似于 OpTraceRayMotionNV
,但 time
值为 0.0。
对于 AABB 几何体,为了缓解精度问题,实现可能会在加速结构中增加它们的大小。这可能会导致向应用程序报告误报的交点。
对于三角形交点候选项,满足上述条件的三角形上的 b 和 c 重心坐标 将提供给后续着色。如果光线是通过 管线跟踪光线 指令跟踪的,这些值将以 HitAttributeKHR
存储类中 2 个 32 位浮点值的向量形式提供。
一旦确定了一个交点候选项,它将按顺序执行以下操作:
以下各节详细描述了这些测试的具体细节。在对不同的交点候选项执行操作之间没有顺序保证。
水密性
对于单个实例中具有相同变换的一组三角形
-
任何两个或多个三角形的集合,其中所有三角形都有一个具有相同位置值的顶点,该顶点是一个共享顶点。
-
任何两个具有两个共享顶点的三角形,如果在每个三角形中以相同的绕序指定,则由这些顶点定义一个共享边。
一个闭合扇形是一组三个或更多三角形,其中
-
该集合中的所有三角形都有一个相同的共享顶点作为它们的一个顶点。
-
所有包含上述顶点的边都是共享边。
-
所有上述共享边都正好由集合中的两个三角形共享。
-
集合中没有两个三角形相交,除非在共享边处。
-
集合中的每个三角形都通过一系列上述共享边连接到集合中的其他每个三角形。
当光线与共享边或闭合扇形的共享顶点相交时,实现应该避免重复命中或遗漏。
光线交点剔除
候选交点在确认为实际命中之前会经过几个阶段的剔除。不同的剔除操作之间没有特定的顺序依赖关系。
光线图元剔除
如果启用了 rayTraversalPrimitiveCulling
或 rayQuery
功能,则在跟踪光线时可以指定 SkipTrianglesKHR
和 SkipAABBsKHR
光线标志。SkipTrianglesKHR
和 SkipAABBsKHR
是互斥的。SkipTrianglesKHR
也与 CullBackFacingTrianglesKHR
和 CullFrontFacingTrianglesKHR
互斥。
如果光线跟踪指令的 Ray Flags
操作数中包含 SkipTrianglesKHR
,并且交点是与三角形图元相交,则该交点将被删除,并且不会对该交点进行进一步处理。如果管线中包含 VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR
,则使用 管线跟踪光线 指令进行的遍历都将表现得好像在其 Ray Flags
操作数中包含了 SkipTrianglesKHR
一样。
如果光线跟踪指令的 Ray Flags
操作数中包含 SkipAABBsKHR
,并且交点是与 AABB 图元相交,则该交点将被删除,并且不会对该交点进行进一步处理。如果管线中包含 VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR
,则使用 管线跟踪光线 指令进行的遍历都将表现得好像在其 Ray Flags
操作数中包含了 SkipAABBsKHR
一样。
光线掩码剔除
根据用于将该实例添加到顶层加速结构的 VkAccelerationStructureInstanceKHR::mask
的值和用于跟踪光线的 Cull Mask
参数,可以使实例对特定的光线不可见。
对于相交的实例,如果 mask
& Cull Mask
== 0,则该交点将被删除,并且不会进行进一步处理。
光线面剔除
与 多边形光栅化 中一样,光线遍历的阶段之一是确定三角形图元是背面还是正面,并且可以基于该面来剔除图元。
如果交点候选项是与 AABB 图元相交,则此操作将被跳过。
当光线与三角形图元相交时,为多边形指定顶点的顺序会影响光线是与正面还是背面相交。正面或背面的确定方式与光栅化中相同,基于多边形面积的符号,但使用光线空间坐标而不是帧缓冲坐标。计算此面积的一种方法是:
其中,
默认情况下,如果 a 为负数,则交点是与三角形的正面相交,否则是与背面相交。如果 VkAccelerationStructureInstanceKHR::flags
中包含 VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR
,则包含相交三角形的实例的此判定将反转。此外,如果 a 为 0,则无论符号如何,交点候选项都被视为与任何面都不相交。
在左手坐标系中,如果三角形的顶点(按索引顺序定义)从光线的角度来看以顺时针旋转顺序出现,则交点将与三角形的正面相交。 |
如果光线是用 管线跟踪光线 指令跟踪的,则对于考虑此交点的着色器阶段,如果交点是与正面几何图形相交,则 HitKindKHR
内置函数设置为 HitKindFrontFacingTriangleKHR
,如果交点是与背面几何图形相交,则设置为 HitKindBackFacingTriangleKHR
。
如果光线是用 OpRayQueryProceedKHR
跟踪的,则对于与正面相交的交点候选项,OpRayQueryGetIntersectionFrontFaceKHR
将返回 true,对于背面则返回 false。
如果 CullBackFacingTrianglesKHR
包含在光线跟踪指令的 Ray Flags
参数中,并且交点被确定为与三角形图元的背面相交,则会丢弃该交点,并且不会对该交点进行进一步处理。
如果 CullFrontFacingTrianglesKHR
包含在光线跟踪指令的 Ray Flags
参数中,并且交点被确定为与三角形图元的正面相交,则会丢弃该交点,并且不会对该交点进行进一步处理。
如果相交几何图形所属的实例的 VkAccelerationStructureInstanceKHR::flags
中包含 VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR
,则会禁用此剔除。
未与任何面相交的交点候选项 (a == 0) 将被无条件剔除,无论光线标志和几何图形实例标志如何。
CullBackFacingTrianglesKHR
和 CullFrontFacingTrianglesKHR
Ray Flags
是互斥的。
光线不透明度剔除
加速结构中的每个几何图形可能被视为不透明或不透明。不透明几何图形像往常一样继续遍历,而非不透明几何图形需要由着色器代码确认或丢弃。还可以根据交点的透明度剔除交点候选项。
如果构造相交几何图形时 VkGeometryNV::flags
或 VkAccelerationStructureGeometryKHR::flags
中包含 VK_GEOMETRY_OPAQUE_BIT_KHR
,则每个单独的交点候选项最初都被确定为不透明,否则将被视为非不透明。
如果几何图形包含不透明度微型映射,则此时交点的不透明度将改为按照 光线不透明度微型映射 中的描述推导得出。
如果交点候选项是由 相交着色器 生成的,则该交点最初被认为具有与生成它的 AABB 候选项相匹配的不透明度。
然而,当不透明度被构建到实例中时,这种不透明度可以被覆盖。在 VkAccelerationStructureInstanceKHR::flags
中设置 VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR
将强制实例中的所有几何体都被视为不透明。类似地,设置 VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR
将强制实例中的所有几何体都被视为非不透明。
当追踪射线时,在 Ray Flags
参数中包含 OpaqueKHR
或 NoOpaqueKHR
可以再次覆盖这种行为。OpaqueKHR
强制所有几何体的行为如同它们是不透明的,而不管它们的构建参数如何。类似地,NoOpaqueKHR
强制所有几何体的行为如同它们是非不透明的。
如果射线是通过 OpRayQueryProceedKHR
追踪的,要确定 AABB 相交候选的不透明度,可以 使用 OpRayQueryGetIntersectionCandidateAABBOpaqueKHR
。对于不透明的相交候选,该指令将返回 true
,对于非不透明的相交候选,该指令将返回 false
。
如果在追踪射线时,Ray Flags
参数中包含 CullOpaqueKHR
,则与被认为是不透明的几何体的相交将被丢弃,并且不会发生进一步的处理。
如果在追踪射线时,Ray Flags
参数中包含 CullNoOpaqueKHR
,则与被认为是非不透明的几何体的相交将被丢弃,并且不会发生进一步的处理。
OpaqueKHR
、NoOpaqueKHR
、CullOpaqueKHR
和 CullNoOpaqueKHR
Ray Flags
是互斥的。
射线不透明度微映射
加速结构中的 VK_GEOMETRY_TYPE_TRIANGLES_KHR
几何体可能具有与其关联的不透明度微映射,以提供更精细的不透明度信息。
如果相交候选与具有关联不透明度微映射的几何体相交,并且其实例中未设置 VK_GEOMETRY_INSTANCE_DISABLE_OPACITY_MICROMAPS_EXT
,则使用微映射来确定几何体的不透明度,而不是几何体中的 VK_GEOMETRY_OPAQUE_BIT_KHR
标志。
微映射对象中的不透明度信息使用候选相交的 u 和 v 坐标访问。整数 u 和 v 从 ⌊u⌋ + ⌊v⌋ 计算得出,根据需要钳制 ⌊u⌋ 以保持总和小于或等于 1 << subdivisionlevel。这些值使用空间填充曲线映射到线性索引,该曲线通过递归地遍历到最近的顶点 0 的子三角形,然后是顺序翻转的中间三角形,然后是最近的顶点 1,最后是最近的顶点 2 来定义。
这种编码在空间上是连贯的,纯粹是分层的,并允许在重心地址和索引值之间进行位并行转换。 请参阅附录以获取实现此映射的参考代码。 |
不透明度微映射查找和操作的结果是将相交视为不透明、非不透明或忽略。值的解释取决于候选相交的实例中的 VK_GEOMETRY_INSTANCE_FORCE_OPACITY_MICROMAP_2_STATE_EXT
或射线上的 ForceOpacityMicromap2StateEXT
射线标志。如果设置了其中任何一个,则不透明度微映射信息将在 2 状态覆盖模式下解释。如果微映射查找的结果是将相交候选视为忽略,则不会对该候选执行进一步的处理。
如果关联的不透明度微映射的格式为 VK_OPACITY_MICROMAP_FORMAT_2_STATE_EXT
,则微映射的每个元素由上面导出的索引处的单个位表示。
如果关联的不透明度微映射的格式为 VK_OPACITY_MICROMAP_FORMAT_4_STATE_EXT
,则每个元素由上面导出的索引处的两位值表示。
4 状态值 | 2 状态值 | 特殊索引值 | 2 状态覆盖 | 结果 |
---|---|---|---|---|
0 |
0 |
|
Y |
忽略 |
0 |
0 |
|
N |
忽略 |
1 |
1 |
|
Y |
不透明 |
1 |
1 |
|
N |
不透明 |
2 |
|
Y |
忽略 |
|
2 |
|
N |
非不透明 |
|
3 |
|
Y |
不透明 |
|
3 |
|
N |
非不透明 |
射线相交确认
根据相交几何体的不透明度以及它是三角形还是 AABB,候选相交会进一步处理以确定最终的命中结果。从 AABB 相交生成的候选者会像三角形命中一样经过相同的确认过程。
AABB 相交候选
对于由 射线相交候选确定 生成的与 AABB 几何体的相交候选,会执行着色器代码以确定是否应向遍历基础设施报告任何命中;不会发生对此相交候选的进一步处理。AABB 相交候选的发生并不能保证射线与图元边界相交。为避免传播错误的相交,应用程序应该在报告任何命中之前验证相交候选,并且仅报告 AABB 范围内的相交。在 AABB 之外报告相交,无论是通过实现给出保守的边界,还是报告超出范围的 t,都是合法的,但可能会导致不可预测的最近命中结果。
如果射线是通过 管道跟踪射线 指令跟踪的,则会根据相交几何体的着色器绑定表,从 相交着色器 中调用一个 指定索引。如果此着色器调用 OpReportIntersectionKHR
,则会如下文所述生成一个新的相交候选。如果相交着色器为 VK_SHADER_UNUSED_KHR
(这仅允许用于零着色器组),则不会发生对此相交候选的进一步处理。
由于此处理而生成的每个新候选都是从与 AABB 几何体的相交生成的相交候选,其 t 值等于 OpReportIntersectionKHR
指令的 Hit
参数。然后,新的生成候选会作为生成相交,独立地通过 射线相交确认。
如果使用 OpRayQueryProceedKHR
追踪光线,控制权将返回到执行 OpRayQueryProceedKHR
的着色器,并返回 true
。生成的射线查询具有 RayQueryCandidateIntersectionAABBKHR
的候选相交类型。可以调用 OpRayQueryGenerateIntersectionKHR
来提交一个新的相交候选,其提交的相交类型为 RayQueryCommittedIntersectionGeneratedKHR
。可以通过执行带有相同射线查询的 OpRayQueryProceedKHR
来继续进一步的射线查询处理,或者可以使用 OpRayQueryTerminateKHR
终止相交。与使用管道追踪射线指令追踪的光线不同,以这种方式生成的候选会跳过生成的相交候选确认;应用程序应该在生成相交之前做出此决定。
对于同一个相交候选,此操作可能会被执行多次。
三角形和生成的相交候选
对于三角形和生成的相交候选,可能会根据相交的不透明度执行额外的着色器代码。
如果相交是不透明的,则该候选会立即被确认为有效的命中,并传递到下一个处理阶段。
对于非不透明的相交候选,会执行着色器代码以确定是否发生了命中。
如果光线是通过管道追踪射线指令追踪的,则会根据指定的索引从着色器绑定表调用任意命中着色器。如果此着色器调用 OpIgnoreIntersectionKHR
,则该候选将被丢弃,并且不会对该候选进行进一步处理。如果识别出的任意命中着色器是 VK_SHADER_UNUSED_KHR
,则该候选会被立即确认为有效命中,并传递到下一个处理阶段。
如果使用 OpRayQueryProceedKHR
追踪光线,控制权将返回到执行 OpRayQueryProceedKHR
的着色器,并返回 true
。由于只有三角形候选参与射线查询的此操作,因此生成的候选相交类型始终为 RayQueryCandidateIntersectionTriangleKHR
。可以在射线查询上调用 OpRayQueryConfirmIntersectionKHR
,以将该候选确认为命中,其提交的相交类型为 RayQueryCommittedIntersectionTriangleKHR
。可以通过执行带有相同射线查询的 OpRayQueryProceedKHR
来继续进一步的射线查询处理,或者可以使用 OpRayQueryTerminateKHR
终止相交。如果未执行 OpRayQueryConfirmIntersectionKHR
,则该候选将被丢弃,并且不会对该候选进行进一步处理。
对于同一个相交候选,此操作可能会被执行多次,除非为相交的几何体指定了 VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR
。
射线最近命中确定
除非使用 TerminateOnFirstHitKHR
射线标志追踪光线,否则实现必须跟踪最近的已确认命中,直到测试完所有几何体,并且已确认或丢弃这些几何体。
在确认相交候选后,将其 t 值与 tmax 进行比较,以确定哪个相交更近,其中 t 是相交发生时沿射线的参数距离。
-
如果 t < tmax,则 tmax 设置为 t,并且该候选被设置为当前最近的命中。
-
如果 t > tmax,则该候选被丢弃,并且不会对该候选进行进一步处理。
-
如果 t = tmax,则该候选可能会被设置为当前最近的命中或丢弃。
如果在用于追踪射线的 射线标志
中包含了 TerminateOnFirstHitKHR
,则一旦确认第一次命中,射线追踪就会终止。
射线结果确定
一旦所有候选都完成了先前阶段的处理,或者如果射线被强制终止,则会确定射线追踪的最终结果。
如果通过射线最近命中确定识别出了最近的命中结果,则发生了最近命中,否则最终结果是未命中。
对于通过管道追踪射线指令追踪的光线,该指令可以调用最近命中着色器,如果识别出了最近命中结果,则会根据相交的几何体的指定索引,从着色器绑定表调用最近命中着色器。一旦此着色器返回,控制权将返回到执行管道追踪射线指令的着色器。如果射线标志包含了 SkipClosestHitShaderKHR
,或者如果识别出的最近命中着色器是 VK_SHADER_UNUSED_KHR
,则会跳过此着色器。
对于通过管道追踪射线指令追踪的光线,如果没有识别出命中结果,则会调用指令的 未命中索引
参数识别的未命中着色器。一旦此着色器返回,控制权将返回到执行管道追踪射线指令的着色器。如果识别出的未命中着色器是 VK_SHADER_UNUSED_KHR
,则会跳过此着色器。
如果使用 OpRayQueryProceedKHR
追踪光线,控制权将返回到执行 OpRayQueryProceedKHR
的着色器,并返回 false
。如果通过射线最近命中确定识别出了最近的命中,则射线查询现在将具有 RayQueryCommittedIntersectionGeneratedKHR
或 RayQueryCommittedIntersectionTriangleKHR
的提交的相交类型。如果没有识别出最近的命中,则提交的相交类型将为 RayQueryCommittedIntersectionNoneKHR
。
在此结果确定后,不会对射线查询进行进一步的处理。