GAMES101-Assignment7

一、问题总览

在之前的练习中,我们实现了Whitted-Style Ray Tracing 算法,并且用BVH等加速结构对于求交过程进行了加速。在本次实验中,我们将在上一次实验的基础上实现完整的Path Tracing算法。

二、代码框架

2.1 修改内容

相比上一次实验,本次实验对框架的修改较大,主要在以下几方面:

  • 修改了main.cpp,以适应本次实验的测试模型CornellBox
  • 修改了Render,以适应CornellBox 并且支持Path Tracing 需要的同一Pixel多次Sample
  • 修改了Object,Sphere,Triangle,TriangleMesh,BVH,添加了area属性与Sample方法,以实现对光源按面积采样,并在Scene中添加了采样光源的接口sampleLight
  • 修改了Material 并在其中实现了sample, eval, pdf三个方法用于Path Tracing变量的辅助计算

2.2 需要迁移的内容

你需要从上一次编程练习中直接拷贝以下函数到对应位置:

  • Triangle::getIntersection in Triangle.hpp: 将你的光线-三角形相交函数粘贴到此处,请直接将上次实验中实现的内容粘贴在此。
  • IntersectP(const Ray& ray, const Vector3f& invDir, const std::array<int, 3>& dirIsNeg) in the Bounds3.hpp: 这个函数的作用是判断包围盒BoundingBox 与光线是否相交,请直接将上次实验中实现的内容粘贴在此处,并且注意检查t_enter = t_exit 的时候的判断是否正确。
  • getIntersection(BVHBuildNode* node, const Ray ray)in BVH.cpp: BVH查找过程,请直接将上次实验中实现的内容粘贴在此处.

三、代码框架

在本次实验中,只需要修改这一个函数:

  • castRay(const Ray ray, int depth)in Scene.cpp: 在其中实现Path Tracing算法

可能用到的函数有:

  • intersect(const Ray ray)in Scene.cpp: 求一条光线与场景的交点
  • sampleLight(Intersection pos, float pdf) in Scene.cpp: 在场景的所有光源上按面积uniform 地sample 一个点,并计算该sample 的概率密度
  • sample(const Vector3f wi, const Vector3f N) in Material.cpp: 按照该材质的性质,给定入射方向与法向量,用某种分布采样一个出射方向
  • pdf(const Vector3f wi, const Vector3f wo, const Vector3f N) in Material.cpp: 给定一对入射、出射方向与法向量,计算sample 方法得到该出射方向的概率密度
  • eval(const Vector3f wi, const Vector3f wo, const Vector3f N) in Material.cpp: 给定一对入射、出射方向与法向量,计算这种情况下的f_r值

可能用到的变量有:

  • RussianRoulette in Scene.cpp: P_RR, Russian Roulette 的概率

四、参考答案

4.1 castRay(const Ray ray, int depth)in Scene.cpp

按照本次实验给出的框架(wo定义与课程介绍相反),我们进一步可以将伪代码改写为:
在这里插入图片描述

  • 如果严格按照上述算法实现,你会发现渲染结果中光源区域为纯黑。这是因为在计算渲染方程时,没有加上自身释放的光
  • 不同于以往从观察点射出光线,上述代码是从光源射出光线。此举是为了解决光线浪费的问题(从观察点产生光线时,受光源大小的影响有些光线可能永远都不会打到光源上,导致这些光线浪费了)
  • 根据以上代码,可以将各个参数的关系画出来,如下图。黄线是 path tracing 的方向,和课上定义相反。(参考:https://zhuanlan.zhihu.com/p/488882096)
    在这里插入图片描述
// Implementation of Path Tracing
Vector3f Scene::castRay(const Ray &ray, int depth) const
{// TO DO Implement Path Tracing Algorithm hereIntersection intersection = Scene::intersect(ray);if(intersection.happened) {Material *m = intersection.m;//MatiralVector3f L_dir(0.0), L_indir(0.0);// sampleLight(inter, pdf_light)Intersection inter;float pdf_light;sampleLight(inter, pdf_light);// Get x, ws, NN, emit from interVector3f X = inter.coords;Vector3f P = intersection.coords;Vector3f ws = (X - P).normalized();Vector3f N = intersection.normal; Vector3f NN = inter.normal;Vector3f emit = inter.emit;// Shoot a ray from p to x(inter)Ray ray_p_x(P + EPSILON * N, ws);Intersection intersection_p_x = Scene::intersect(ray_p_x);// If the ray is not blocked in the middleif((intersection_p_x.coords - inter.coords).norm() < EPSILON) {L_dir = emit * m->eval(ray.direction, ws, N) * dotProduct(ws, N) * dotProduct(-ws, NN) / std::pow(intersection_p_x.distance,2)/ pdf_light;}// 使用俄罗斯轮盘赌判断反射光线是否应停止继续反射if(get_random_float() <= RussianRoulette) {// Trace a ray r(p, wi)Vector3f wi = m->sample(ray.direction, N).normalized();Ray r(P, wi);Intersection intersection_r = Scene::intersect(r);// If ray r hit a non-emitting object at qif(intersection_r.happened && !intersection_r.m->hasEmission()) {L_indir = castRay(r, depth+1) * m->eval(ray.direction, wi, N) * dotProduct(wi, N) / m->pdf(ray.direction, wi, N) / RussianRoulette;}}return m->getEmission() + L_dir + L_indir;} return this->backgroundColor;
}

4.2 多线程加速

  • 在Render.cpp中使用多线程加速
  • 多线程会影响部分变量的值(如变量m),所以需要修改下函数
  • 使用#pragma omp parallel for, 然后在CMakeLists.txt中加上set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp")
void Renderer::Render(const Scene& scene)
{std::vector<Vector3f> framebuffer(scene.width * scene.height);float scale = tan(deg2rad(scene.fov * 0.5));float imageAspectRatio = scene.width / (float)scene.height;Vector3f eye_pos(278, 273, -800);int m = 0;// change the spp value to change sample ammountint spp = 16;std::cout << "SPP: " << spp << "\n";#pragma omp parallel for shared(m)for (uint32_t j = 0; j < scene.height; ++j) {for (uint32_t i = 0; i < scene.width; ++i) {// generate primary ray directionfloat 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);m++;}UpdateProgress(1.f);// save framebuffer to fileFILE* fp = fopen("binary.ppm", "wb");(void)fprintf(fp, "P6\n%d %d\n255\n", scene.width, scene.height);for (auto i = 0; i < scene.height * scene.width; ++i) {static unsigned char color[3];color[0] = (unsigned char)(255 * std::pow(clamp(0, 1, framebuffer[i].x), 0.6f));color[1] = (unsigned char)(255 * std::pow(clamp(0, 1, framebuffer[i].y), 0.6f));color[2] = (unsigned char)(255 * std::pow(clamp(0, 1, framebuffer[i].z), 0.6f));fwrite(color, 1, 3, fp);}fclose(fp);    
}

五、编译

mkdir build
cd ./build
cmake ..
make./RayTracing

附件

作业7压缩包

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/625039.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QT报错记录

Ubuntu22.04安装Qt之后启动Qt Creator报错&#xff1a; Fron 6.5.0, xcb-cursor0 or libxcb-cursor0 is needed to load the Qt xcb platforn plugin. Could not load. This application failed to start because no Qt platforn plugin could be initialized. Reinstalling t…

RSA原理理解以及攻防世界(初识RSA)解题思路-0基础理解

题目 下载附件后&#xff0c;我们看到的是这样一个界面&#xff0c;这里需要理解RSA的构造 RSA原理理解 RSA加密算法是一种非对称加密算法&#xff0c;在公开密钥加密和电子商业中被广泛使用。对极大整数做因数分解的难度决定了RSA算法的可靠性。换言之&#xff0c;对一极大整…

Java SE入门及基础(14)

二重循环 1. 什么是二重循环 二重循环就是一个循环结构中又包含另外一个循环结构 while ( 外层循环条件 ){ //外层循环操作 while ( 内层循环条件 ){ //内层循环操作 } //外层循环操作 } while ( 外层循环条件 ){ //外层循环操作 for ( 循环变量初始化 ; 内层循环条…

【Docker】在容器中管理数据数据卷挂载以及宿主机目录挂载

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是平顶山大师&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《【Docker】在容器中管理数据》。&#x1f3af…

vector容器解决杨辉三角

一、题目描述 118. 杨辉三角 给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 1: 输入: numRows 5 输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]示例 2: 输入: numRo…

蓝桥杯每日一题----货物摆放

题目 分析 上来一看&#xff0c;三个for循环&#xff0c;从1到n&#xff0c;寻找满足lwhn的个数&#xff0c;但是这样根本跑不出来答案&#xff0c;n太大了&#xff0c;1e15的级别&#xff0c;O&#xff08;n&#xff09;的时间复杂度都不行&#xff0c;更何况是O&#xff08;…

科研绘图(六)散点图矩阵

散点图矩阵是一种显示多个变量之间关系的数据可视化工具&#xff0c;特别是当数据集包含三个或多个变量时&#xff0c;这种图表非常有用。这种图通常在探索性数据分析中使用&#xff0c;以便快速理解数据集中变量之间的关系。在散点图矩阵中&#xff0c;每行和每列都代表数据集…

SpringBoot的启动器——spring-boot-starter介绍和常见启动器说明

文章目录 SpringBoot的启动器——spring-boot-starter介绍和常见启动器说明1、Starter是什么2、Starters命名规范3、Spring Boot提供的一些启动器&#xff08;starter) SpringBoot的启动器——spring-boot-starter介绍和常见启动器说明 1、Starter是什么 Spring Boot通过将我…

深入探究Python Collections模块:高效数据结构解决方案

前言 这几天刷leetcode题时&#xff0c;看到题解中有这样一行代码collections.defaultdict(list)&#xff0c;不明白是啥意思&#xff0c;平时开发的脚本中未遇到&#xff0c;借着这个机会&#xff0c;学习一下collections模块的用法。 collections 这个模块实现了一些专门化…

闪存的基础知识1-Vt的定义

系列文章目录 本次系列文章主要分享与存储相关的知识 文章目录 目录 系列文章目录 前言 一、mos管 阈值电压是什么&#xff1f; 二、详细分析 1.通俗理解 2.读入数据 总结 前言 阈值电压(Vt) 阈值电压(Vt或Vth)的概念是从MOS管来的。 一、mos管 阈值电压是什么&#xff1f; …

结构化流(Structured Streaming)

结构化流介绍 有界和无界数据 有界数据: 指的数据有固定的开始和固定的结束&#xff0c;数据大小是固定。我们称之为有界数据。对于有界数据&#xff0c;一般采用批处理方案&#xff08;离线计算&#xff09;特点&#xff1a;1-数据大小是固定2-程序处理有界数据&#xff0c…

嵌入式学习-网络编程-Day2

思维导图 tcp通信流程 udp通信流程 作业1 写一个基于TCP协议的客户端来控制RobArm机械臂 代码 #include <myhead.h> #define SER_PORT 8888 #define SER_IP "192.168.122.71" #define CLI_PORT 6666 #define CLI_IP "192.168.122.36"int main(int…

分布式搜索引擎ElasticSearch——搜索功能

分布式搜索引擎ElasticSearch——搜索功能 文章目录 分布式搜索引擎ElasticSearch——搜索功能DSL查询文档DSL查询分类全文检索查询精确查询地理查询复合查询Function Score QueryBoolean Query 搜索结果处理排序![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/37d…

Qt 使用vs2019制作Qt静态库( *.lib )并使用

一 .创建静态库 1.创建Qt Class Library(Qt静态类库)项目 2.设置项目名以及项目路径(注意:不能有中文字符) 点击next 3.选则需要的模式以及Qt 模块 然后点击next,Finish完成创建 4. 然后手动添加Qt Widget Form File (.ui)并对设计ui 5. tpendialog.h #pragma once #includ…

书生.浦语大模型实战一

从专用模型到通用大模型 数据 书生.万卷1.0 文本图像-文本视频数据 OpenDataLab开放平台 图像&#xff1a;ImageNettokens语料&#xff1a;WikiQA音频视频&#xff1a;MovieNet3D模型 预训练 微调 增量续训 使用场景&#xff1a;让基座模型学习到一些新知识&#xff0…

Ubuntu 20.04 Intel RealSense D435i 相机标定教程

下载编译code_utils mkdir -p ~/imu_catkin_ws/src cd ~/imu_catkin_ws/src catkin_init_workspace source ~/imu_catkin_ws/devel/setup.bash git clone https://github.com/gaowenliang/code_utils.git cd .. catkin_make报错&#xff1a;sumpixel_test.cpp:2:10: fatal err…

vivado 使用IP Integrator源

使用IP Integrator源 在Vivado Design Suite中&#xff0c;您可以在RTL中添加和管理IP子系统块设计&#xff08;.bd&#xff09;项目或设计。使用Vivado IP集成程序&#xff0c;您可以创建IP子系统块设计。IP集成程序使您能够通过实例化和将Vivado IP目录中的多个IP核互连。可…

改进YOLOv8:添加CBAM注意力机制(涨点明显)

1、计算机视觉中的注意力机制 计算机视觉中的注意力机制是一种聚焦于局部信息的机制&#xff0c;其基本思想是让系统学会忽略无关信息而关注重点信息。这种机制在图像识别、物体检测和人脸识别等任务中都发挥了重要作用。 注意力机制的实现方法有多种&#xff0c;其中包括空间…

亲手打造一个本地LLM语音助手来管理智能家居

经历过 Siri 和 Google 助手之后&#xff0c;我发现尽管它们能够控制各种设备&#xff0c;但却无法进行个性化定制&#xff0c;并且不可避免地依赖于云服务。出于对新知识的渴望以及想在生活中使用一些酷炫的东西&#xff0c;我下定决心&#xff0c;要追求更高的目标。我的要求…

【RTOS】快速体验FreeRTOS所有常用API(2)任务管理

目录 二、任务管理2.1 任务创建&#xff08;三种方式&#xff09;1&#xff09;动态内存分配方式创建任务2&#xff09;静态内存分配方式创建任务3&#xff09;带有任务参数方式创建任务 2.2 任务删除2.3 两种delay 二、任务管理 该部分在上份代码基础上修改得来&#xff0c;代…