光线追踪技术解析与程序实现

在各种网站上,看到了很多人对光线追踪技术的讨论,但许多人似乎并不了解光线追踪的真正含义。光线追踪与蒙特卡洛方法有关,包括重要性采样,并且显然与光学有关,认为这将是一个不错的项目补充。这个项目不是关于Nvidia如何实现它的,他们必须使用一些“技巧”来实现实时渲染,例如大幅度减少反射次数,限制每像素的光线数,光线追踪的场景可能比普通场景小,通过使用“AI”消除噪声,模型是混合的,使用光栅化和光线追踪等。这个项目是关于常规光线追踪的。

程序在行动

通常,会录制一个显示程序执行过程的电影,但现在改变了代码,以逐帧录制动画,所以展示的是那个:

这是如何使用gstreamer生成电影的:

gst-launch-1.0 multifilesrc location="c:\\temp\\frame%06d.jpg" caps="image/jpeg,framerate=30/1" ! jpegdec ! x264enc pass=quant ! avimux ! filesink location="out.avi"

对于程序执行,需要自己编译代码,希望UI不是大问题,它允许生成“一个周末”的场景,一个康奈尔盒子或一些其他场景,允许指定一个天空盒子和一些obj文件来加载。生成的图像可以保存在几种图像格式文件中。

一些理论

这次,在开始实施项目之前,先寻找文章、博客文章等,知道互联网上有很多关于它的信息。的确有很多,所以不会在这里重复,相反,会指出一些有用的信息链接。

最重要的是,发现了一些免费的书,作者是Peter Shirley,非常有帮助。可能会发现他的GitHub仓库非常有用。没有在实施项目时查看那些,但可能发现的相似之处并非巧合,必须解析这些书来找出为什么。

如果想查看项目,这里有一些其他可能想要检查的链接:

Michael Ashikhmin和Peter Shirley的《各向异性Phong BRDF模型》

Osada等人的《形状分布》

Tomas Möller和Ben Trumbore的《快速,最小存储光线-三角形相交》

当然,这些只是一个开始,应该从这些链接开始找到大量信息。

一些生成和测试时的图像

代码

一般性

非常仔细地遵循了这些书,尽管跳过了一些对来说更无聊的部分,如纹理生成和运动模糊,它们是直接实现的。选择了一些不同的类层次结构和命名,也有实现上的变化。有时选择了更快的东西,如光线与边界框的相交,有时出于方便选择了较慢的实现,如矩形的旋转。选择了一个不同的颜色类,使用了已经在博客的一些项目中使用的向量类实现,并且使用了double而不是float作为值。它在速度上没有太大的区别,更好的精度的优势更重要。也使用了很多智能指针和C++随机数生成器。唯一使用的库是UI:

wxWidgets。超越了“余生”的书,首先添加了三角形到对象,然后添加了一个obj文件加载器。考虑使用tinyobjloader库,但更喜欢自己实现。随着一些变化,可能会在未来的某个时候在其他使用OpenGL的项目中使用它。也许还会随着时间的推移增强它,因为它有各种问题,最大的一个是它不能正确加载凹多边形。

命名空间和类

为了理解代码,必须查看它以及Peter Shirley的书和参考文章。将在这里非常简要地描述命名空间和类。

Camera类与在使用OpenGL的项目中使用的类类似,但简化了,增加了getRay函数。Vector3D与其他项目中的相同,Color是一个非常简单的类,包含r、g、b组件。ObjLoader类显然用于加载obj文件。它不是可移植的,远非完美,写得很匆忙,但在许多情况下都能工作。它不仅可以加载对象,还可以加载材料,包括颜色和纹理。

OrthoNormalBasis用于局部正交正交基。要了解它的用途,请查看例如AnisotropicPhongPDF::Generate函数。PointInfo和ScatterInfo用于一些对象,包含有用的信息。Random用于名称所暗示的内容,它可以生成各种随机数分布。它使用std::mt19937_64。

Ray代表,正如所猜测的,一个光线,并包含原点和方向,以及用于加速计算的方向的倒数。Scene实现了场景,它派生自Objects::VisibleObjectComposite,其主要功能是光线投射,RayCast。

项目中有几个命名空间,根据它们的目的将类分开。BVH命名空间用于边界体积层次结构类,包含AxisAlignedBoundingBox类和BVHNode类。Materials包含材料类,如Dielectric、Metal、Isotropic、Lambertian和AnisotropicPhong。Objects包含对象,如Triangle、Sphere、Box等。PDFs包含概率密度函数类,如CosinePDF和AnisotrophicPhongPDF。Textures包含纹理类,如ColorTexture和ImageTexture。Actions包含一些可以应用于某些对象的转换类,如TranslateAction或FlipNormal。

还有一些其他类是用于UI实现、选项等,会让在项目中发现那些。

一些资源

从这里获得了一些用于测试和显示的obj文件:

free3d。从这里下载了天空盒子:

这里。用于一些生成图像的“地球”纹理与在牛顿引力项目中使用的相同,所以可以访问那个页面以获取下载链接。

结论

这样一个程序可以无限扩展。首先会尝试提高其性能。它可能会从更好的边界体积层次结构构建中受益。如果有耐心和时间,也会寻求其他性能提升。例如,使用了向量实现中已经内置的旋转,一遍又一遍地计算它,而不是像书中那样缓存余弦和正弦。那并不完全优化。敢打赌,程序可以从许多这样的优化中受益。由于随机数生成使用得很多,可能更快的数字生成器会有帮助,但想找到一个比使用的更好的更快的数字生成器相当困难。如果找到了,请告诉。

也会切换到光谱渲染,这样就可以有真正逼真的折射,例如。这里是一个很好的开始:

Peter Shirley的博客上的Lazy光谱渲染。光谱渲染是在项目中有一个Color类而不是像书中那样使用向量类的原因之一。在开发过程中,还发现了最后一本书和相关项目中的一个问题,所以发出了信号:

重要性采样问题。可以在书中看到这个问题,它表现为图像中的那些黑点,它需要deNaN清理,这也在书中描述了。这就是热爱开源的原因,人们可以贡献,他们免费得到一些东西,然后回报一些东西。感谢Peter Shirley分享他的经验!

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485