一周内实现光线追踪,thenextweek,理解BVH
这一周拜读了雪莉的这个一周内实现光线追踪,收获颇丰,尤其是对于games101的光线追踪框架,我似乎知道他是怎么一步步改过来的了,之前对于那个共享指针到底指到哪儿其实心里还是没有谱的,只是知道进行纹理映射就行了,而这个一周内实现光追特意实现了一些高级的特性(雾效,对焦相机,motion blur)
对于之前101的框架更加认识了一步,尤其是101的框架其实没有教我们最开始的whitted风格,而是直接强上了path-tracing(虽然框架是whitted,但是那时候没有好好研究,而是只是实现bvh之后就放下了)
感谢这个项目,让我见识到了ray tracing的巨大力量,而且对于之前spp数以及ppm格式,这里面的一堆细节,做完之后就有了印象了。
尤其是从第一周,到第二周,一步步的前进,简直是震撼。
特意记录一些东西,作为感想。
首先自然是最重要的bvh的实现,在这里,我更加加深了对于bvh的理解
(步步分治,在最终的时刻进行合并box,牛逼),注意time0和time1 代表(移动物体(比如那个移动的球)的位置移动时间),这里做一个纪念。
而且在此过程中了解了反射,折射,雾效,纹理映射,牛逼,无以言表,强烈建议自己打一遍代码,理解会非常深刻
1 #ifndef BVH_H 2 #define BVH_H 3 4 #include "rtweekend.h" 5 #include "hittable.h" 6 #include "hittable_list.h" 7 #include <algorithm> 8 9 class bvh_node : public hittable { 10 public: 11 bvh_node() {}; 12 bvh_node( 13 const std::vector<shared_ptr<hittable>>& src_objects, 14 size_t start, size_t end, double time0, double time1); 15 16 bvh_node(const hittable_list& list, double time0, double time1) 17 : bvh_node(list.objects, 0, list.objects.size(), time0, time1) 18 {} 19 20 21 22 virtual bool hit( 23 const ray& r, double t_min, double t_max, hit_record& rec) const override; 24 25 virtual bool bounding_box(double time0, double time1, aabb& output_box) const override; 26 27 public: 28 shared_ptr<hittable> left; 29 shared_ptr<hittable> right; 30 aabb box; 31 }; 32 33 bool bvh_node::bounding_box(double time0, double time1, aabb& output_box) const { 34 output_box = box; 35 return true; 36 } 37 38 inline bool box_compare(const shared_ptr<hittable> a, const shared_ptr<hittable> b, int axis) { 39 aabb box_a; 40 aabb box_b; 41 42 if (!a->bounding_box(0, 0, box_a) || !b->bounding_box(0, 0, box_b)) 43 std::cerr << "No bounding box in bvh_node constructor.\n"; 44 45 return box_a.min().e[axis] < box_b.min().e[axis]; 46 } 47 48 49 bool box_x_compare(const shared_ptr<hittable> a, const shared_ptr<hittable> b) { 50 return box_compare(a, b, 0); 51 } 52 53 bool box_y_compare(const shared_ptr<hittable> a, const shared_ptr<hittable> b) { 54 return box_compare(a, b, 1); 55 } 56 57 bool box_z_compare(const shared_ptr<hittable> a, const shared_ptr<hittable> b) { 58 return box_compare(a, b, 2); 59 } 60 61 bool bvh_node::hit(const ray& r, double t_min, double t_max, hit_record& rec) const { 62 if (!box.hit(r, t_min, t_max)) 63 return false; 64 65 bool hit_left = left->hit(r, t_min, t_max, rec); 66 bool hit_right = right->hit(r, t_min, hit_left ? rec.t : t_max, rec); 67 68 return hit_left || hit_right; 69 } 70 71 bvh_node::bvh_node( 72 const std::vector<shared_ptr<hittable>>& src_objects, 73 size_t start, size_t end, double time0, double time1) 74 { 75 auto objects = src_objects; // Create a modifiable array of the source scene objects 76 77 int axis = random_int(0, 2); 78 auto comparator = (axis == 0) ? box_x_compare 79 : (axis == 1) ? box_y_compare 80 : box_z_compare; 81 82 size_t object_span = end - start; 83 84 if (object_span == 1) { 85 left = right = objects[start]; 86 } 87 else if (object_span == 2) { 88 if (comparator(objects[start], objects[start + 1])) { 89 left = objects[start]; 90 right = objects[start + 1]; 91 } 92 else { 93 left = objects[start + 1]; 94 right = objects[start]; 95 } 96 } 97 else { 98 std::sort(objects.begin() + start, objects.begin() + end, comparator); 99 100 auto mid = start + object_span / 2; 101 left = make_shared<bvh_node>(objects, start, mid, time0, time1); 102 right = make_shared<bvh_node>(objects, mid, end, time0, time1); 103 } 104 105 aabb box_left, box_right; 106 107 if (!left->bounding_box(time0, time1, box_left) 108 || !right->bounding_box(time0, time1, box_right) 109 ) 110 std::cerr << "No bounding box in bvh_node constructor.\n"; 111 112 box = surrounding_box(box_left, box_right); 113 } 114 115 #endif // !BVH_H