挑战:无绑定光线追踪
2022 年 6 月 9 日
镜子,另一面镜子上的...镜子。在本次挑战中,我们邀请您在 Metal 3 中探索无绑定渲染并在镜面上反射光线。
由于 Metal 3 中引入无绑定增强功能,HybridRendering 示例 App 看起来比以前更好了。它使用 Argument Buffers 为其着色器提供所有场景资源,然后使用 Metal 光线追踪在金属表面上产生反射 (如下所示)。
但是,尽管这款 App 描绘出了完美的场景,但仍然存在局限性:它无法显示反射中的反射,就像镜面地板反射镜面球体一样。
平心而论:镜子反射镜子是很难的!光会在两个表面之间无限反射,造成一种无法通过计算解决的状况。光线追踪 App 可在场景中添加有限数量的光 (或光线)“反射”来增强真实感,从而解决这个问题。
在本次挑战中,我们邀请您添加一个 (或多个) 额外的光线反射,从而扩展该光线追踪代码并增强图像的真实感。
开始挑战
在进入此镜子学堂之前,建议先观看“利用 Metal 3 实现无绑定”。看完之后,下载“Rendering reflections in real time using ray tracing”示例代码,我们将用它来应对本次挑战。
利用 Metal 3 实现无绑定
Watch nowRendering reflections in real time using ray tracing
该 App 有一个专门的计算通道,可以计算来自薄的几何缓冲区 (G-Buffer,其中包含图像中每个像素的位置和法线) 的反射。
光线追踪着色器会读取此数据,并将其与相机的视向相结合来计算反射光线的方向。然后,它将使用 Metal 来追踪这些光线、找到交叉点并对反射进行着色。
raytracing::ray r;
r.origin = positions.read(tid).xyz;
r.direction = normalize(directions.read(tid).xyz);
r.min_distance = 0.1;
r.max_distance = FLT_MAX;
raytracing::intersector<raytracing::instancing, raytracing::triangle_data> inter;
inter.assume_geometry_type( raytracing::geometry_type::triangle );
auto intersection = inter.intersect( r, accelerationStructure, 0xFF );
if ( intersection.type == raytracing::intersection_type::triangle )
{
// Calculate direct reflections
}
这会产生以下图像:
但存在一个问题!球体在地板上的反射中没有了消防车。您需要应对的挑战是,通过修改光线追踪着色器 rtReflection
来添加额外的光线追踪步骤,让失踪的消防车显示出来。
要完成这项挑战,您将:
- 使用反射的法线和相交位置来计算光线的下一次反射。
- 将材质着色逻辑提取到一个辅助函数中,以便对反射中的反射进行着色。
- 将所有反射的颜色相结合并写入
outImage
。
完成后,使用截屏工具 GPU 调试器或 QuickTime 截取解决方案图像,然后使用话题标签 #WWDC22Challenges 在 Twitter 上展示您的作品。如果您想讨论无绑定光线追踪以及其他图形与游戏主题,请加入团队,参加 WWDC22 本周剩余时间举办的活动。