GAMES101:作业6

这篇博客介绍了GAMES101作业6的内容,重点是实现光线追踪中的Ray-Bounding Volume交集计算和BVH(Bounding Volume Hierarchy)查找。作者详细解释了如何在Bounds3.hpp和BVH.cpp中实现相关函数,并探讨了使用SAH(Surface Area Heuristic)优化BVH构建的过程,包括SAH的成本函数和优化目标。虽然在作者的测试中,SAH与BVH的时间开销相近,但SAH提供了更好的空间划分策略。
摘要由CSDN通过智能技术生成

GAMES101:作业6

附其他所有作业超链接如下:
Games101 作业0:作业0
Games101 作业1:作业1
Games101 作业2:作业2
Games101 作业3:作业3
Games101 作业4:作业4
Games101 作业5:作业5
Games101 作业6:作业6
Games101 作业7:作业7

完整代码获取途径:
https://github.com/liupeining/Games_101_homework

接下来是实现加速的光线追踪,本练习要求实现 Ray-Bounding Volume 求交与 BVH 查找;后文中笔者也实现了SAH(Surface Area Heuristic),并逐段代码讲解了SAH的实现过程。
首先,你需要从上一次编程练习中引用以下函数:
• Render() in Renderer.cpp: 将你的光线生成过程粘贴到此处,并且按照新框架更新相应调用的格式。

    for (uint32_t j = 0; j < scene.height; ++j) {
   
        for (uint32_t i = 0; i < scene.width; ++i) {
   
            //这里的过程实际上相当于把屏幕空间先缩小到左下角为0,0的2*2格子里,然后移动到0,0处。
            //和框架规定有关,作业一直有上下颠倒的问题,这里面可以在y填一个负号来解决。
            //最后乘的系数是生成图片的大小。
            float x =  (2 * (i + 0.5) / scene.width  - 1) * scale * imageAspectRatio; //正常需要减eye_pos的,但这里eye_pos是000向量,就略去不写了。
            float y = -(2 * (j + 0.5) / scene.height - 1) * scale;   
            Vector3f dir = normalize(Vector3f(x, y, -1)); //归一化可以看这个类的声明
            Ray ray(eye_pos,dir);
            framebuffer[m++] = scene.castRay(ray,0);
        }
        UpdateProgress(j / (float)scene.height);
    }
    UpdateProgress(1.f);

这里需要根据框架改动两行:

            Ray ray(eye_pos,dir);
            framebuffer[m++] = scene.castRay(ray,0);

剩下的不需要变化。

• Triangle::getIntersection in Triangle.hpp: 将你的光线-三角形相交函数粘贴到此处,并且按照新框架更新相应相交信息的格式。
需要注意的地方已经注释在下方的程序中。

/*inline 函数仅仅是一个对编译器的建议,所以最后能否真正内联,看编译器的意思,
它如果认为函数不复杂,能在调用点展开,就会真正内联,并不是说声明了内联就会内联,声明内联只是一个建议而已。
为了解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题,特别的引入了 inline 修饰符,表示为内联函数。
栈空间就是指放置程序的局部数据(也就是函数内数据)的内存空间。
*/
inline Intersection Triangle::getIntersection(Ray ray)
{
   
    Intersection inter;
    //如果结果大于0,那么这两个向量的夹角小于90度;
    //这里normal是从三角指向眼的,因此若同方向则不可能穿过三角
    if (dotProduct(ray.direction, normal) > 0)
        return inter; // happen = false;
    /*
    Intersection的定义
        Intersection(){
        happened=false;
        coords=Vector3f();
        normal=Vector3f();
        distance= std::numeric_limits<double>::max();
        obj =nullptr;
        m=nullptr;
    }
    */
    double u, v, t_tmp = 0;
    Vector3f pvec = crossProduct(ray.direction, e2); //S1
    double det = dotProduct(e1, pvec);               //S1*E1(顺便说一句,能推出S1*E1=-D*N)
    if (fabs(det) < EPSILON) //const float EPSILON = 0.00001; 分母特别小将导致t特别大,相当于很远很远,看不见
        return inter;
    double det_inv = 1. / det;                      // 1/S1*E1
    Vector3f tvec = ray.origin - v0;                //S
    u = dotProduct(tvec, pvec) * det_inv;           //b1
    if (u < 0 || u > 1)  
        return inter;
    Vector3f qvec = crossProduct(tvec, e1);         //S2
    v = dotProduct(ray.direction, qvec) * det_inv;  //b2
    if (v < 0 || u + v > 1) 
        return inter;
    t_tmp = dotProduct(e2, qvec) * det_inv;         //t
    if(t_tmp<0) 
        return inter;

    inter.distance = t_tmp;
    inter.happened = true;
    inter.m = m;
    inter.obj = this;
    inter.normal = normal;
    inter.coords = ray(t_tmp);
    return inter;
}

在本次编程练习中,你需要实现以下函数:
• IntersectP(const Ray& ray, const Vector3f& invDir, const std::array<int, 3>& dirIsNeg) in the Bounds3.hpp: 这个函数的作用是判断包围盒 BoundingBox 与光线是否相交,你需要按照课程介绍的算法实现求交过程。
需要注意的内容及公式均已注释在代码内。

inline bool Bounds3::IntersectP(const Ray& ray, const Vector3f& invDir,
                                const std::array<int, 3>& dirIsNeg) const
{
      
    //invDir = 1 / D; t = (Px - Ox) / dx
    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];

    //如果发现射线的方向是反的,调换t_min和t_max的位置。
    if(dirIsNeg[0])
    {
   
        float t = t_Min_x;
        t_Min_x = t_Max_x;
        t_Max_x = t;
    }
    if(dirIsNeg[1])
    
  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值