利用包围盒加速的光线追踪实现图形渲染
欢迎关注公众号:sumsmile, 图像视觉、移动开发~~
接上一篇《图形渲染5-光线追踪》,对求交算法进行优化.
实现效果
下图中兔子模型是由4968个三角形拼接而成
忽略背景。vscode预览3d模型,默认有个背景,去不掉.
注:bunny是儿语化的“兔子”
BVH加速
光线追踪的渲染中,每一个像素,实际上是光线打到物体表面反射到场景中。(实际还有自发光的情况,本章节简化模型,仅考虑漫反射)
为什么要加速
场景中可能存在很多物体,单个像素的光线需要和这些物体挨个求交,最后比较得出最近的交点,其他交点处于被遮挡的情况,忽略不计。
上图中兔子模型有4968个三角形,一帧图像中一个点就需要求交近5千次,1280 * 720的窗口渲染一次需求交 4968 * (1280 * 480)次,这还是比较简单的模型场景。
很容易就想到,使用一个立方体,将单个模型包围起来,先对立方体求交,条件成立之后,再考虑与里面的几何模型求交。当然了,可以将模型进一步拆分成n个三角形,包裹在立方体中。
包围盒有多种形式,最常用的包围盒长、宽、高分别与x、y、z平行,方便计算。
什么是BVH
BVH:Bounding Volume Hierarchy。包围盒层级。
将场景中的所有模型做拆分,分成一块一块的,最常见的有基于空间和基于物体拆分两种形式。本篇中基于物体做拆分,持续迭代,拆成一个二叉树,中间节点存放包围盒,子节点存放真实的物体。
BVH的使用
-
创建包围盒:遍历场景中的物体,按照一定规则拆分包围盒。可以沿着最长的轴方向切割,另外拆分有个限制,就是拆到什么程度不再拆了,可以自己定义,比如一个包围盒少于5个三角形就不再拆分了。
-
光线求交:从上往下,按照树的遍历方式,对每个节点进行遍历,当然了,先判断父节点的包围盒是否和光线相交,满足条件再遍历子节点,如此,很大程度的优化了光线追踪的算法复杂度。
代码核心逻辑
虽然只是个demo,有软渲染器的核心逻辑,有面向对象的封装,有渲染的算法。
- Scene(场景)
- Light(光照)
- Renderer(渲染器)
- Model(几何模型)
- 工具类
完整代码:
github.com/summer-go/g…
补充
- 判断光线与包围盒相交的算法
- 轻量级的3D加载工具OBJ-Loader
- 模型只有漫反射,用冯氏光照计算颜色,兔子本身没有颜色,写死成(0.0, 0.5, 0.0)绿色
欢迎关注公众号:sumsmile, 图像视觉、移动开发~~
参考资料:
[1] 完整代码: github.com/summer-go/g…
[2] ray-box-intersection: www.scratchapixel.com/lessons/3d-…
[3] OBJ-Loader: github.com/Bly7/OBJ-Lo…
推荐阅读