待填坑
- 建立渲染器框架,调用时自定义采样数、分辨率、输出文件名
- 实现几何
球体
、轴对齐立方体
,以及对应的与光线求交方法 - 实现材质
漫反射
、镜面反射
、glossy
- 将轴对齐立方体完善成任意立方体
- 实现折射材质
- 找方法在同等采样数时降噪
前言
出于增加C++代码量和深入理解图形学算法的目的,打算实现一个光线追踪渲染器。框架与算法参考学习了项目Ray Tracing in One Weekend,详细的过程可参考原文,本文仅记录大该概框架和实现过程中的问题。
实现过程
程序框架
camera
: 照像机需要实现- 根据给定坐标、焦距、方向等参数定义一个空间中的照相机
- 给它屏幕uv坐标可以返回相机原点与对应像素连成的射线
ray
: 光线/射线需要实现- 根据原点和方向定义空间中的一根射线
- 给定时间t可返回t时射线末端的位置
hitable
: 几何体需要实现的接口,对于给定光线,几何体应当返回光线与其是否存在交点,以及交点的位置、法线等信息material
: 材质接口,其实例通过实现scatter函数表现,scatter函数会在一次入射光线照射中,返回该材质可能的一根反射光线main
: 有了上述模块,就可以按以下方式就行渲染- 给世界中放入一些几何体,定义这些几何体的位置、大小与材质属性
- 根据分辨率找到每一个像素对应的uv,通过uv获得照相机发出的光线
- 对每一个像素采样n次,每次采样根据打到的物体材质的scatter函数,获取下一根光线递归地进行采样
- 根据采样结果以某种格式绘制渲染结果
以上便是渲染器的大致的框架,除此之外还需要像向量
类等工具支持。
日志
- 截止至22年4月18日:
对于800采样次数/像素效果如下(随机采样、p=0.8的轮盘赌、光源长宽0.5):
- 22年5月4日:
尝试使用自己想到的射线与球求交算法,结果是我想到的算法比之前快了90%,应该是计算次数稍微少,常数级别的优化所以并不算快。但是新算法却在渲染结果有差别,也就是错了,下面分别是原来的和新算法的对比图,以及新算法在box中的结果。可以看出hit_pos的结果应该没问题,但是阴影出了问题。搞了好久,下次再看看吧
理论基础
蒙特卡罗积分
轮盘赌算法
遇到的问题
- 使用宏函数没有对所有变量加括号,导致射线和AABB包围盒求交的交点判断错误
- 射线和AABB包围盒求交时的除零问题,一开始没处理好导致渲染画面水平线那一行有白线。实际是由于和包围盒平行,导致误以为能够击中水平线之上的灯。编写代码时,对于除0时候,将结果设置为INF,并在计算是将其排除在外,这时候是有上面说的Bug的,但我想应该是可以对于平行射线的情况分类处理以完美解决。在我的代码中,真正解决办法是减小浮点数误差间隔,不容易出现完全平行的情况(我猜是这样的,不过图形程序找bug真的挺麻烦)。