项目 - 路径追踪渲染器实现过程

path tracing render

Posted by ZolHo on April 13, 2022

待填坑

  • 建立渲染器框架,调用时自定义采样数、分辨率、输出文件名
  • 实现几何球体轴对齐立方体,以及对应的与光线求交方法
  • 实现材质漫反射镜面反射glossy
  • 将轴对齐立方体完善成任意立方体
  • 实现折射材质
  • 找方法在同等采样数时降噪

前言

出于增加C++代码量和深入理解图形学算法的目的,打算实现一个光线追踪渲染器。框架与算法参考学习了项目Ray Tracing in One Weekend,详细的过程可参考原文,本文仅记录大该概框架和实现过程中的问题。

实现过程

程序框架

  • camera: 照像机需要实现
    • 根据给定坐标、焦距、方向等参数定义一个空间中的照相机
    • 给它屏幕uv坐标可以返回相机原点与对应像素连成的射线
  • ray: 光线/射线需要实现
    • 根据原点和方向定义空间中的一根射线
    • 给定时间t可返回t时射线末端的位置
  • hitable: 几何体需要实现的接口,对于给定光线,几何体应当返回光线与其是否存在交点,以及交点的位置、法线等信息
  • material: 材质接口,其实例通过实现scatter函数表现,scatter函数会在一次入射光线照射中,返回该材质可能的一根反射光线
  • main: 有了上述模块,就可以按以下方式就行渲染
    1. 给世界中放入一些几何体,定义这些几何体的位置、大小与材质属性
    2. 根据分辨率找到每一个像素对应的uv,通过uv获得照相机发出的光线
    3. 对每一个像素采样n次,每次采样根据打到的物体材质的scatter函数,获取下一根光线递归地进行采样
    4. 根据采样结果以某种格式绘制渲染结果

以上便是渲染器的大致的框架,除此之外还需要像向量类等工具支持。

日志

  • 截止至22年4月18日:

对于800采样次数/像素效果如下(随机采样、p=0.8的轮盘赌、光源长宽0.5): 220418效果图

  • 22年5月4日:

尝试使用自己想到的射线与球求交算法,结果是我想到的算法比之前快了90%,应该是计算次数稍微少,常数级别的优化所以并不算快。但是新算法却在渲染结果有差别,也就是错了,下面分别是原来的和新算法的对比图,以及新算法在box中的结果。可以看出hit_pos的结果应该没问题,但是阴影出了问题。搞了好久,下次再看看吧

pre img 新算法img 新算法的应用

理论基础

蒙特卡罗积分

轮盘赌算法

遇到的问题

  • 使用宏函数没有对所有变量加括号,导致射线和AABB包围盒求交的交点判断错误
  • 射线和AABB包围盒求交时的除零问题,一开始没处理好导致渲染画面水平线那一行有白线。实际是由于和包围盒平行,导致误以为能够击中水平线之上的灯。编写代码时,对于除0时候,将结果设置为INF,并在计算是将其排除在外,这时候是有上面说的Bug的,但我想应该是可以对于平行射线的情况分类处理以完美解决。在我的代码中,真正解决办法是减小浮点数误差间隔,不容易出现完全平行的情况(我猜是这样的,不过图形程序找bug真的挺麻烦)。


-->