作业要求
相比于作业5,将光线封装起来 修改Render()
for (uint32_t j = 0; j < scene.height; ++j) {
for (uint32_t i = 0; i < scene.width; ++i) {
// generate primary ray direction
float x = (2 * (i + 0.5) / (float)scene.width - 1) *
imageAspectRatio * scale;
float y = (1 - 2 * (j + 0.5) / (float)scene.height) * scale;
// TODO: Find the x and y positions of the current pixel to get the
// direction
// vector that passes through it.
// Also, don't forget to multiply both of them with the variable
// *scale*, and x (horizontal) variable with the *imageAspectRatio*
Vector3f dir = Vector3f(x, y, -1);
dir = normalize(dir);
//封装
Ray ray(eye_pos,dir);
framebuffer[m++]= scene.castRay(ray,0);
}
UpdateProgress(j / (float)scene.height);
}
判断光线射进包围盒情况
inline bool Bounds3::IntersectP(const Ray& ray, const Vector3f& invDir,
const std::array<int, 3>& dirIsNeg) const
{
// invDir: ray direction(x,y,z), invDir=(1.0/x,1.0/y,1.0/z), use this because Multiply is faster that Division
// dirIsNeg: ray direction(x,y,z), dirIsNeg=[int(x>0),int(y>0),int(z>0)], use this to simplify your logic
// TODO test if ray bound intersects
//光线与包围盒相交有三种情况:1.光从包围盒里面射出,则沿着光的射线有一个交点。2.光的反向延长线射向包围盒,此时t没有正数解。3.光与包围盒相交
//这里使用乘以invDIr,乘法比除法快很多
float t_Min_x = (pMin.x - ray.origin.x)*invDir[0];
float t_Min_y = (pMin.y - ray.origin.y)*invDir[1];
float t_Min_z = (pMin.z - ray.origin.z)*invDir[2];
float t_Max_x = (pMax.x - ray.origin.x)*invDir[0];
float t_Max_y = (pMax.y - ray.origin.y)*invDir[1];
float t_Max_z = (pMax.z - ray.origin.z)*invDir[2];
//dirIsNeg判断光线正方向
// dirIsNeg: ray direction(x,y,z), dirIsNeg=[int(x>0),int(y>0),int(z>0)],判断光线朝向
if(!dirIsNeg[0])
{
auto t = t_Min_x;
t_Min_x = t_Max_x;
t_Max_x = t;
}
if(!dirIsNeg[1])
{
auto t = t_Min_y;
t_Min_y = t_Max_y;
t_Max_y = t;
}
if(!dirIsNeg[2])
{
auto t = t_Min_z;
t_Min_z = t_Max_z;
t_Max_z = t;
}
// enter取max tmin exit取min tmax
float t_enter = std::max(t_Min_x,std::max(t_Min_y,t_Min_z));
float t_exit = std::min(t_Max_x,std::min(t_Max_y,t_Max_z));
if(t_enter<t_exit&&t_exit>=0)
return true;
else
return false;
}
这里我们先要搞清楚BVH递归是如何实现的
Intersection BVHAccel::getIntersection(BVHBuildNode* node, const Ray& ray) const
{
// TODO Traverse the BVH to find intersection
// 用IntersectP中注释的思路
Vector3f invDir=ray.direction_inv;
std::array<int, 3> dirIsNeg;
dirIsNeg[0] = (ray.direction[0]>0);
dirIsNeg[1] = (ray.direction[1]>0);
dirIsNeg[2] = (ray.direction[2]>0);
Intersection inter;
//判断是否在包围盒里
if(!node->bounds.IntersectP(ray,invDir,dirIsNeg)){
return inter;
}
//找到了
if(node->left == nullptr && node->right == nullptr){
return node->object->getIntersection(ray);
}
//寻找左子树 右子树
Intersection l = getIntersection(node->left,ray);
Intersection r = getIntersection(node->right,ray);
//找到更近的子树
return l.distance<r.distance?l:r;
}
运行结果
SAH
引用老师给的网站:当物体分布不是很均匀的时候,BVH的分割效果就会很差