Games101作业7

1.解决报错

导入代码以后会出现两个函数需要返回值,这里先随便构造一个对应的返回类型解决报错。然后解决fopen的不安全问题,解决办法跟上个作业一样。然后是修改c++语言标准。

之后还有这个错误,应该是模型路径的问题。

修改代码如下:

string obj_path = "\\..\\..\\models\\cornellbox\\";
    char pathBuf[MAX_PATH];
    char* p;
    if (GetModuleFileNameA(NULL, pathBuf, 1000))
    {
        p = strrchr(pathBuf, '\\');
        if (p)
        {
            *p = '\0';
            string exe_path = pathBuf;
            obj_path = exe_path + obj_path;
        }
    }
    MeshTriangle floor(obj_path + "floor.obj", white);
    MeshTriangle shortbox(obj_path + "shortbox.obj", white);
    MeshTriangle tallbox(obj_path + "tallbox.obj", white);
    MeshTriangle left(obj_path + "left.obj", red);
    MeshTriangle right(obj_path + "right.obj", green);
    MeshTriangle light_(obj_path + "light.obj", light);

之后代码就可以跑通了,并且生成了一张纯白色的图片

2.castRay(const Ray ray, int depth)

完成这个函数的时候需要先将上次作业的几个函数移植到这次作业里

有一个需要修改的地方是在判断inline bool Bounds3::IntersectP时,需要写成t_enter<=t_exit,对浮点数处理,否则会导致部分地方是黑的:

另外在渲染的时候最好使用多线程处理,会极大缩短渲染时间

启用OpenMP第一步,在项目设置中启用OpenMP。

第二步,在 Render 函数的最外层for循环前添加一行:

#pragma omp parallel for

 修改代码如下

#pragma omp parallel for
        for (int j = 0; j < scene.height; ++j)
        {
            for (int 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;

                Vector3f dir = normalize(Vector3f(-x, y, 1));
                for (int k = 0; k < spp; k++)
                {
                    //framebuffer[m] += scene.castRay(Ray(eye_pos, dir), 0) / spp;
                    framebuffer[j * scene.width + i] += scene.castRay(Ray(eye_pos, dir), 0) / spp;
                }
                //m++;
            }
            //UpdateProgress(j / (float)scene.height);
            UpdateProgress(m++ / (float)scene.height);
        }
    UpdateProgress(1.f);

然后castray函数主要参照作业里给的伪代码

// Implementation of Path Tracing
Vector3f Scene::castRay(const Ray& ray, int depth) const
{
    // TO DO Implement Path Tracing Algorithm here
    Vector3f L_dir;
    Vector3f L_indir;

    // 从像素发出的光线与物体的交点
    Intersection obj_inter = intersect(ray);
    if (!obj_inter.happened)
        return L_dir;

    // 打到光源
    if (obj_inter.m->hasEmission())
        return obj_inter.m->getEmission();

    // 打到物体
    Vector3f p = obj_inter.coords;//交点坐标
    Material* m = obj_inter.m;//交点材质
    Vector3f N = obj_inter.normal.normalized();//交点法线
    Vector3f wo = ray.direction; // 像素到物体的向量

    // 有交点,对光源采样

    Intersection light_inter;
    float pdf_L = 1.0; //可以不初始化
    sampleLight(light_inter, pdf_L);    // 得到光源位置和对光源采样的pdf

    Vector3f x = light_inter.coords;
    Vector3f ws = (x - p).normalized(); //物体到光源
   
    Vector3f emit = light_inter.emit;
    Vector3f NN = light_inter.normal.normalized();
    float d = (x - p).norm();
    // 再次从光源发出一条光线,判断是否能打到该物体,即中间是否有阻挡

    Ray Obj2Light(p, ws);
    float d2 = intersect(Obj2Light).distance;
    // 是否阻挡,利用距离判断,需注意浮点数的处理
    if (d2 - d > -0.001) {
        Vector3f eval = m->eval(wo, ws, N); // wo不会用到
        float cos_theta = dotProduct(N, ws);
        float cos_theta_x = dotProduct(NN, -ws);//ws从物体指向光源,与NN的夹角大于180
        L_dir = emit * eval * cos_theta * cos_theta_x / std::pow(d, 2) / pdf_L;
    }

    // L_indir
    float P_RR = get_random_float();
    if (P_RR < RussianRoulette) {
        Vector3f wi = m->sample(wo, N).normalized();
        Ray r(p, wi);
        Intersection inter = intersect(r);
        // 判断打到的物体是否会发光取决于m
        if (inter.happened && !inter.m->hasEmission()) {
            Vector3f eval = m->eval(wo, wi, N);
            float pdf_O = m->pdf(wo, wi, N);//1/2PI
            float cos_theta = dotProduct(wi, N);
            L_indir = castRay(r, depth + 1) * eval * cos_theta / pdf_O / RussianRoulette;
        }
    }
    //4->16min
    return L_dir + L_indir;
}

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值