
Evergine 中的光线追踪
简介
光线追踪是一项能够提升渲染真实感的技术。目前更普及的实时渲染技术是光栅化,长期以来我们一直致力于模拟世界的所有细节,如不同的表面、光线、阴影、反射等。另一方面,光线追踪一直是一项能够以最佳近似度模拟现实世界所有这些细节的技术,但它在实时渲染中的使用成本非常高。
2018年,Nvidia 推出了搭载 RTX 技术的新系列显卡,该技术利用硬件来降低光线追踪技术的计算成本。这使我们能够在实时渲染中使用光线追踪,并为我们提供了传统光栅化技术的一个良好替代方案。
一些视觉效果,如柔和阴影、实时反射或全局光照,用传统光栅化技术实现起来很困难,而使用光线追踪则能以相对更简单的实现方式获得这些效果。
在随后的2019、2020和2021年,光线追踪正在通过 AMD 或 Intel 等其他显卡厂商普及,因此目标是光线追踪将成为未来的标准技术。
Evergine 在其低级 API 中支持光线追踪技术。低级 API 是一个通用接口,涵盖了最重要的图形 API,如 DX12、DX11、Metal、Vulkan 或 OpenGL。不过,目前光线追踪支持仅在 DirectX12 和 Vulkan 后端可用。
Evergine 团队已将 DirectX12 DXR 和 Vulkan 光线追踪 API 统一到一个单一且通用的 API 中。因此,您可以使用 Evergine 低级 API 编写项目,之后在 DX12 或 Vulkan 后端上运行。
为了展示 Evergine 光线追踪低级 API 的可能性,在 Evergine 发布之际,我们创建了一个路径追踪演示,您可以从 Github 下载。此演示包含了一些使用光线追踪技术实现的有趣效果,如柔和阴影、环境光遮蔽、全局光照和抗锯齿。
下一节将解释这些效果各自是如何实现的:

首先,相机将为每个像素投射一条射线,每条射线可能击中或不击中表面。如果射线击中表面,颜色结果将从表面材质获取;如果射线未击中,结果将是背景色。
柔和阴影
要实现光线追踪阴影,需要从每个表面击中点向光源投射一条新射线。如果这条新射线在到达光源之前与某物发生碰撞,则返回“在阴影中”的值,否则返回“在光照中”的值。

这是最简单的情况,会产生硬阴影,但要产生柔和阴影,则需要添加更多内容。我们的实现是从每个表面点向光源投射多条射线(在此演示中我们仅使用一个光源)。为简单起见,光源是球形的,射线将从表面击中点向光源投射,形成一个锥体。
然后,阴影颜色取决于每条射线组合的结果。当一些射线返回“在阴影中”而另一些返回“在光照中”时,就产生了半影区域。

在下图中,通过比较使用不同光源半径产生的阴影,可以看到半影区域。

环境光遮蔽
环境光遮蔽模拟的是那些因附近有物体而倾向于阻挡或遮蔽光线的区域,因此这些区域显得更暗。
我们的环境光遮蔽实现是从表面击中点,在与表面法线对齐的半球内投射多条短射线。与阴影射线类似,这些射线会检测点附近是否有物体并遮蔽光线反弹。

在下图中,可以看到使用不同环境光遮蔽射线长度的结果:

全局光照
现实世界中光的行为可以通过从光源发射射线来模拟,这些射线会击中表面。射线的一部分能量被表面吸收,另一部分被反射,从而产生一条新射线,如此递归进行,直到初始射线的所有能量都被吸收。

通过反弹参数,我们可以模拟光线在表面上反射的次数。每次反弹产生的颜色会叠加到表面颜色上,例如,一个红色物体靠近另一个物体时,会使邻近物体染上红色调。
在下图中可以看到全局光照的输出效果,其中一些区域被邻近物体的颜色所染色。

抗锯齿
抗锯齿旨在消除图像中的锯齿状边缘。这些锯齿是由于输出图像的像素网格有限而产生的。
为了实现这一目标,我们需要从相机为每个像素投射多条光线,并取平均颜色作为结果。当每个像素只投射一条光线时,相机为每个像素投射一条对准像素中心的光线。为了实现抗锯齿,我们在每个像素内以随机方向投射多条光线。在我们的实现中,我们使用了常用于此目的的Halton序列。

每个像素结合多条光线的结果如下图所示:

未来工作
如今,光线追踪是一项持续演进的技术,但其当前效果已非常出色,且优于光栅化渲染结果。所有现代图形引擎都在更新其渲染器以使用光线追踪,但集成成本高昂,且为了继续支持旧款显卡,光线追踪的使用仅作为一种替代方案。许多现代引擎正在其渲染器中实现光栅化与光线追踪相结合的混合渲染。
Evergine是首个集成光线追踪的C#引擎。我们的目标是为用户提供最新的图形技术,用于他们的工业项目或产品。
根据我们的路线图,我们将继续在光线追踪方面努力,将其用于我们的高级API,并提供与Evergine Studio集成的光线追踪功能。

