《学一辈子光线追踪》 四 重要性采样材料

2024-04-07 20:38

本文主要是介绍《学一辈子光线追踪》 四 重要性采样材料,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

蒙特卡洛光线追踪技术系列 见 蒙特卡洛光线追踪技术

在接下来的两章中,我们的目标是利用我们的程序向光源发送一束额外的光线,这样我们的图片噪声就不会太多了。假设我们可以使用pdf pLight(direction) 向光源发送一束光线。假设我们有一个与s相关的pdf,我们称之为pSurface(direction)。pdf 的一个优点是,可以使用它们的线性混合来形成混合密度,这也是pdf。

例如,最简单的方法是:

p(direction) = 0.5*pLight(direction) + 0.5*pSurface(direction)

只要权重是正的并且加起来是1,任何这种pdf的混合都是pdf。记住,我们可以使用任何pdf-它不会改变我们的答案!所以,目标是要找出当乘积 s(direction)*color(direction) 更大的时候,如何使pdf更大。对于漫反射曲面,这主要是猜测颜色(方向)高的地方。对于镜子来说,s()只在一个方向附近是巨大的,所以它更重要。事实上,大多数渲染器都会将镜面作为一种特殊情况,而只是将s/p隐式化——我们的代码目前就是这样做的。

让我们做一个简单的重构,暂时删除所有不是Lambertian的材质(不想删除也得改改里面继承的函数)。我们可以再次使用康奈尔盒子场景,还是使用之前的视点:

vec3 lookfrom(278, 278, -800);//
vec3 lookat(278, 278, 0);

框架也是我在上本书的最后实现的每次渲染都输出结果的框架。

减少噪音是我们的目标。我们将通过构建一个pdf来实现这一点,它可以向光发送更多的光线。

首先,让我们测试代码,以便它显式地对一些 pdf 进行采样,然后对其进行规范化。记住MC基础:积分 f(x) 大约等于 f(r)/p(r)。对于朗伯材料,让我们像现在这样取样:p(direction)=cos(theta)/Pi。

我们修改材料以启用此重要性采样:

class material {
public:virtual bool scatter(const ray &r_in, const hit_record& rec, vec3& albedo, ray& scattered,float &pdf)const {return false;}virtual float scattering_pdf(const ray &r_in, const hit_record& rec, const ray& scattered)const {return false;}virtual vec3 emitted(float u, float v, const vec3&p)const {return vec3(0, 0, 0);}};class lambertian :public material {
public:lambertian(texture*a):albedo(a){}virtual float scattering_pdf(const ray& r_in, const hit_record& rec, ray& scattered)const {float cosine = dot(rec.normal, unitVector(scattered.direction()));if (cosine < 0)cosine = 0;return cosine / M_PI;}virtual bool scatter(const ray& r_in, const hit_record& rec, vec3& alb, ray& scattered, float &pdf)const {vec3 target = rec.p + rec.normal + random_in_unit_sphere();scattered = ray(rec.p, unitVector(target - rec.p));//r_in.time()alb = albedo->value(rec.u, rec.v, rec.p);pdf = dot(rec.normal, unitVector(scattered.direction())) / M_PI;return true;}texture* albedo;
};

注意修改一些其他代码,因为凡是继承后的类,都需要修改继承的虚函数。

vec3 color(const ray&r, hitable *world, int depth) {hit_record rec;if (world->hit(r, 0.001, MAXFLOAT, rec)) {ray scattered;vec3 emitted = rec.mat_ptr->emitted(rec.u, rec.v, rec.p);float pdf;vec3 albedo;if (depth < 50 && rec.mat_ptr->scatter(r, rec, albedo, scattered,pdf)) {return emitted + albedo* rec.mat_ptr->scattering_pdf(r,rec,scattered) *color(scattered, world, depth + 1);}else {return emitted;}}else {return vec3(0, 0, 0);}
}

结果竟然只显示一个灯,物体和墙都没有了。我们开始调试,首先修改一下color函数:

vec3 color(const ray&r, hitable *world, int depth) {hit_record rec;if (world->hit(r, 0.001, MAXFLOAT, rec)) {ray scattered;vec3 emitted = rec.mat_ptr->emitted(rec.u, rec.v, rec.p);float pdf;vec3 albedo;if (depth < 50 && rec.mat_ptr->scatter(r, rec, albedo, scattered,pdf)) {return emitted + color(scattered, world, depth + 1);}//albedo* rec.mat_ptr->scattering_pdf(r,rec,scattered) *else {return emitted;}}else {return vec3(0, 0, 0);}
}

得到结果:

隐约能看到物体,说明是 albedo* rec.mat_ptr->scattering_pdf(r,rec,scattered) 出了问题。

深入检查,发现

virtual float scattering_pdf(const ray& r_in, const hit_record& rec, ray& scattered)const

的最后一个参数 ray 竟然少了一个const修饰符。改过来以后就可以了。效果和前面的一样。

 

现在,为了体验,尝试不同的抽样策略。让我们从高于表面的半球中随机选择。这就是p(direction) = 1/(2*Pi)

	virtual bool scatter(const ray& r_in, const hit_record& rec, vec3& alb, ray& scattered, float &pdf)const {vec3 direction;do {direction = random_in_unit_sphere();} while (dot(direction, rec.normal) < 0);scattered = ray(rec.p, unitVector(direction), r_in.time());alb = albedo->value(rec.u, rec.v, rec.p);pdf = 0.5 / M_PI;return true;}

得到结果:

 

相同背景物体和光照条件下的对比:

 

再说一遍,我应该得到相同的图片,除了不同的变化幅度,但并没有。第二张照片的长方体非常均匀,这是为什么呢?

它很接近我们的老照片,但有一些差异不是噪声。这个高盒子的正面颜色要均匀得多。所以我有最难在蒙特卡罗程序中找到的一种错误——一种能产生合理外观图像的错误。我不知道这个bug是程序的第一个版本还是第二个版本,甚至两者都是!

让我们建立一些基础设施来解决这个问题。

这篇关于《学一辈子光线追踪》 四 重要性采样材料的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/883615

相关文章

上采样(upsample)的方法

上采样(upsample)的方法   在神经网络中,扩大特征图的方法,即upsample/上采样的方法   1)unpooling:恢复max的位置,其余部分补零   2)deconvolution(反卷积):先对input补零,再conv   3)插值方法,双线性插值等;   4)扩张卷积,dilated conv;

借助AI快速提高英语听力:如何获得适合自己的听力材料?

英语听力是英语学习中的一个重要组成部分,它对于提高语言理解和交流能力至关重要。可理解性学习(comprehensible input)是语言习得理论中的一个概念,由语言学家Stephen Krashen提出,指的是学习者在理解语言输入的同时,自然而然地习得语言。 Krashen认为,当学习者接触到稍微超出他们当前语言水平的输入时,他们会自然地习得语言。这个稍微超出的部分被称为“i+1”,其中“i

Adaboost集成学习 | Adaboost集成学习特征重要性分析(Python)

目录 效果一览基本介绍模型设计程序设计参考资料 效果一览 基本介绍 Adaboost集成学习特征重要性分析(Python)Adaboost(自适应增强)是一种常用的集成学习方法,用于提高机器学习算法的准确性。它通过组合多个弱分类器来构建一个强分类器。在Adaboost中,每个弱分类器都被赋予一个权重,这些权重根据其在训练过程中的表现进行调整。因此,Adaboost可以通

机器学习在材料预测方面的应用

文章目录 1.机器学习的基本流程2.常见的材料性能3.常见的材料数据库4.机器学习模型及应用5.数据预处理过程6.常用的机器学习模型1.线性回归2.逻辑回归3.支持向量机(SVM)4.随机森林 1.机器学习的基本流程 #mermaid-svg-hAOmlARgRIIiVxQa {font-family:"trebuchet ms",verdana,arial,sans

Python统计实战:一题搞定多元线性回归、共线性、相对重要性分析

为了解决特定问题而进行的学习是提高效率的最佳途径。这种方法能够使我们专注于最相关的知识和技能,从而更快地掌握解决问题所需的能力。 (以下练习题来源于《统计学—基于Python》。联系获取完整数据和Python源代码文件。) 练习题 为了分析影响不良贷款的因素,一家商业银行在所属的多家分行中随机抽取25家,得到的不良贷款、贷款余额、应收贷款、贷款项目个数、固定资产投资等有关数据如下(前3行

第五章重采样方法

目录 第二题 第三题 第四题 ​ 第二题 我们现在将推导一个给定观测值是引导样本一部分的概率。假设我们从n个观测值中获得一个引导样本。 (a) 第一个引导观测值不是原始样本中第j个观测值的概率是多少?请证明你的答案。 (b) 第二个引导观测值不是原始样本中第j个观测值的概率是多少? (c) 论证原始样本中第j个观测值不在引导样本中的概率是(1 − 1/n)^n。 (d) 当n =

【机器学习】基于Softmax松弛技术的离散数据采样

1.引言 1.1.离散数据采样的意义 离散数据采样在深度学习中起着至关重要的作用,它直接影响到模型的性能、泛化能力、训练效率、鲁棒性和解释性。 首先,采样方法能够有效地平衡数据集中不同类别的样本数量,使得模型在训练时能够更均衡地学习各个类别的特征,从而避免因数据不平衡导致的偏差。 其次,合理的采样策略可以确保模型在训练过程中能够接触到足够多的样本,避免过拟合和欠拟合问题,提高模型的泛化能力

springCloudAlibaba之链路追踪组件---skywalking

skywalking skywalking skywalking 介绍 对于一个大型的几十个、几百个微服务构成的微服务架构系统,通常会遇到下面一些问题,比如:如何串联整个调用链路、快速定位问题?如何明确各个微服务之间的依赖关系?如何进行各个微服务接口的性能分析?如何跟踪整个业务流程的通用处理程序?

番外篇 | YOLOv8算法解析和实战应用:车辆检测 + 车辆追踪 + 行驶速度计算

前言:Hello大家好,我是小哥谈。YOLOv8是ultralytics公司在2023年1月10号开源的,是YOLOv5的下一个重大更新版本,目前支持图像分类、物体检测和实例分割任务,在还没有开源时就收到了用户的广泛关注。它是一个SOTA模型,建立在以前YOLO版本的成功基础上,并引入了新的功能和改进,以进一步提升性能和灵活性。本文就对YOLOv8算法进行解析并以车辆检测及速度计算为案例进行

振弦式渗压计在土木工程安全监测中的重要性解析

在土木工程领域中,特别是涉及到坝体、隧道、路基等复杂结构的监测与安全管理时,渗压计作为一种关键的测量工具,发挥着举足轻重的作用。其中,振弦式渗压计以其独特的优点,得到了广泛的应用和认可。本文将对振弦式渗压计的重要性进行深入的解析。   振弦式渗压计在实时监测方面展现出了较高的性能。无论是大坝内部的渗流情况,还是隧道、路基等工程中的水位变化,振弦式渗压计都能进行实时、连续的监测。这种实