现代计算机图形学 作业6 解析
这篇文章就是来解析一下作业6的框架,同时让同学们对BVH有一个更加深入的理解
最开始有一个网格的bunny,是加载了一个已有的模型,这里我们就不多看这个了,之后可能会单独写一篇有关于读取obj文件的文章
这里在场景中把bunny添加进去,同时添加了两个光源。
然后我们初始化BVH,因为模型已经加载好了,所以我们就可以利用BVH来划分了
来到buildBVH
中看,可以看到这里有一个划分方法,分别是NAIVE
和SAH
,有关SAH
是这个作业的拓展项,之后我们再讨论。
来到BVHAccel
中,可以看到对maxPrimsInNode
设置的值是1,这里大家应该可以猜测到,就是我们每个节点所包含的primitive
,就是课上讲的叶节点中包含的元件的数量
还是像往常一样,在解读代码含义的过程中我也会关注他的实现,这里传入的p是一个object的vector,作为值传入并将值移动到了scene的primitives中。是不是感觉和copy-and-swap的策略很相似
然后我们来到recursiveBuild
中,在这里大家要把整体的构建流程看做是构建二叉树的过程(本身我们构建的也就是二叉树)
首先对整体的bbox(bbox即boundbox,即包围盒),求并,得到整个节点的bbox(这里求的bbox貌似后面没用),然后我们对当前处理的object数量判断,当object的数量为1的时候,我们就不再继续递归的构建子节点了,当前的节点就作为叶节点。
如果数量为2,我们就平分两个节点,分别作为左右子树,并更新当前节点的bbox
然后看else中,这里首先对每个object的bbox求他的中点,然后用中点拓展出一个包含所有中点的bbox,那么在这里我们就可以知道这些object在哪个方向上的跨越最大
思考一下为什么不用整体的bbox而是用中点,因为我们更希望划分开每个object,而不是划分开bbox。即我们希望得到object之间的差异最大的维度,而不是包围盒跨度最大的维度。
然后我们得到最长的那一维,然后根据那一维排序。之后我们就可以将这些object划分到两个节点中。然后再递归的进行划分,并用两个子节点的bbox更新当前节点的bbox
至此我们构建bbox的过程就结束了。然后来到Render
中
之前讲过的地方这里就不在细说了,进入到castRay
中
首先就是用BVH来和光线求交集,进入到Scene::interSect
中,然后再一直向里,忽略一些边界条件,来到getIntersection
这里其实也就是递归的去查询每个节点的bbox,首先我们会判断当前节点的bbox与当前光线是否有交点,具体体现在IntersectP
中,这里跟着ppt中的图解实现即可
要注意的一个细节是当光线的方向是负数的时候,我们也要把光线对应的参数t反过来
对BVH每个节点查询,如果是叶节点,就使用object中对应的方法进行判断,这里对应球面和三角形都有不同的实现方法,有兴趣的同学可以自己去看一下
对应非叶子节点我们递归的求解bbox,并选取较近的那个交点。
之后剩下的部分在上次的解析中已经提过了,这里就不再细说了。
还有就是在处理全反射的地方,还记的上次我说的那个阴影应该也应用于镜面反射的地方吗,这次的代码已经有了修正
这里还多加了一个areaLight,但是代码中没有具体的用到,可以看到代码中在动态转化后并没有使用area_ptr
,同时我们最开始加的是Light
,所以这里的dynamic_cast也应该不会成功。
文章评论