一个光线追踪器中实现景深的参考资料?

6

我有一个基本的光线追踪器,想要实现景深效果。请问您能推荐一些可以使用的资源、书籍和代码吗?

谢谢!

1个回答

17

我从这个页面上的一点信息中弄清楚了: http://cg.skeelogy.com/depth-of-field-using-raytracing/,特别是底部附近的图表。我认为我的方法略有不同,但概念相当简单。

我可以解释一下大致的思路和如何实现它(我会尽量简洁明了)。光线从任意给定点反射出来,向所有方向扩散(一般而言),因此在渲染点和眼睛之间并不是单个射线,而是从渲染点离开的光锥向眼睛扩散。你眼睛/相机的镜头会弯曲这些光线,使得光锥停止扩散并开始收缩。为了使物体完全清晰,光锥应该收缩到视网膜/帧上的一个点,但这只适用于与镜头的一个特定距离:参考页面中所示的“焦平面”(虽然我认为它应该真正成为以眼睛为中心的球体,而不是平面)。

对于焦平面前的任何东西,光锥将被弯曲得更多:它将聚焦到视网膜/帧的前面一个点,然后开始再次扩散,因此当它到达帧时,它不再是一个点,而是一个圆圈。同样,对于焦平面后的点,光锥将被弯曲得更少,并且在到达帧时还没有汇聚到一个点。在这两种情况下,效果是场景中的单个点会在多个像素上被涂抹开来。

对于实现,可以将这个想法反过来:不是将场景中的每个点渲染到多个像素,而是将几个附近的点渲染到单个像素,当然这正是实际发生的情况,因为相邻点的“涂抹开”的光圈最终会重叠,因此每个点都会对像素产生贡献。

所以这就是我如何实现它的方式:

首先,定义一个“光圈”:它是平面区域,以眼睛为中心并平行于视网膜/框架。光圈越大,景深效果就越明显。光圈通常只是圆形,因此可以根据其半径轻松定义。其他形状可能会导致不同的光照效果。
还要定义一个“焦距”。我不认为这实际上是正确的术语,但它是物体在眼前完全聚焦的距离。
为了渲染每个像素:
1. 首先像往常一样从眼睛向外投射一条光线穿过像素进入场景。然而,与在场景中的物体相交不同,您只需要找到沿着该光线距离眼睛等于所选焦距的点。将此点称为像素的焦点。 2. 现在在光圈上选择一个随机起点。对于圆形光圈,这很容易,您可以选择一个随机极角和一个随机半径(不超过光圈的半径)。您需要在整个光圈上均匀分布,不要试图偏向中心或其他任何东西。 3. 从光圈上选择的点开始通过焦点投射一条光线。请注意它不一定会穿过同一像素,这没问题。 4. 以通常的方式渲染此光线(例如,路径追踪或仅查找最近的交点等)。 5. 重复步骤2、3和4若干次,每次使用光圈上的不同随机起点,但始终通过焦点进行投射。将来自所有光线的渲染颜色值相加,并将其用作此像素的值(如果必要,像往常一样除以一个常数衰减因子)。

每个像素使用的光线数量越多,显然质量会越好。我通常使用大约150条光线来得到不错但并非十分出色的效果。您可以使用更少的光线(例如50或60条)来看到效果,但是较少的光线会使图像产生颗粒状纹理,尤其是对于那些非常模糊的物体。您需要的光线数量还取决于光圈大小:较小的光圈不需要那么多光线,但您将无法获得太多的模糊效果。

显然,这样做会极大地增加您的工作量,实际上是将工作量乘以每个像素使用的光线数,因此,如果您在光线跟踪器中有任何优化剩余的工作,现在是一个很好的时机。好消息是,如果您有多个可用的处理器,一旦为像素找到了焦点,这个过程就可以轻松地并行处理。

更详细的解释

下面的图片应该能够让您了解发生了什么以及为什么这等价于眼睛或相机中真正发生的事情。它显示了两个正在被渲染的像素,一个用红色表示,另一个用蓝色表示。从眼睛通过每个像素延伸到焦点“平面”的虚线是您在开始时投射的光线,以确定像素的焦点。半透明的锥体表示可以随机选择来渲染每个像素的完整光线集(像素1的红色锥体,像素2的蓝色锥体)。请注意,由于所有光线都通过焦点,因此每个锥体都会收敛到焦点处的一个点。

锥形的重叠区域代表场景中可能被渲染到像素1和像素2的点,换句话说,会模糊不清。由于每个锥体都是焦点“平面”上的一个点,在这里锥体之间没有重叠,因此在这个距离上的点只被渲染到一个像素:它们完全清晰。与此同时,离焦点“平面”越远(向前或向后),锥体就会更加分散,因此在任何给定点处,重叠的锥体就越多。因此,非常接近或非常远的点往往会被渲染到许多不同的像素,因此它们会变得非常模糊。 光线追踪中深度效果实现的模型。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接