全球图形学领域教育的领先者、自研引擎的倡导者、底层技术研究领域的技术公开者,东汉书院在致力于使得更多人群具备内核级竞争力的道路上,将带给小伙伴们更多的公开技术教学和视频,感谢一路以来有你的支持。我们正在用实际行动来帮助小伙伴们构建一套成体系的图形学知识架构,你在我们这里获得的不止于那些毫无意义的代码,我们这里更多的是代码背后的故事,以及精准、透彻的理解。我们不会扔给人们一本书或者给个思路让人们去自学,我们是亲自来设计出好的课程,让人们明白到底背后还有哪些细节。

这里插播一个引擎大赛的消息,感兴趣的同学可以看一眼,这也是东汉书院的立项使命:

大赛官方主页东汉书院-自己动手写游戏引擎​edu.battlefire.cn

简介

我们终于来到了跟渲染有一点点关系的部分了,这部分我们看完之后就可以去改进我们的多重采样部分的代码了。我们应该抽象的看待我们之前获取到的那些数学公式:

这里实际上相当于 。然后S就相当于是概率,我们应该想起来我们先前推导来推导去的那些公式:pdf、cpdf、r、e、f。

动机与初心

还记得不记得我们在渲染的时候碰到的是啥问题?我们碰到的问题是不知道如何去给一个光线权重的问题,我们如果对某一个像素进行渲染的时候,只发射一根光线去计算这个像素点的颜色的话,会有很大的噪声。

为了解决这个问题,我们引入了多重采样,但是在多重采样后,我们又面临了曝光度过大的问题,所以我们需要给每一根光线一个权重,来缩放它们最终生成的颜色在最终画面里的比重。这样一来,我们在光线追踪学习的时候直接采用的是平均值的方式,我们先把所有光线生成的颜色加起来,然后除以光线的总数量。这种方法简单粗暴,但是不是最好的办法,我们其实更期望能根据光线自身的特性来给予光线一个权重,于是乎我们开始了蒙特卡洛方法的研究之旅。

有些人学着学着就把初心给丢了,我们一次又一次的帮助同学们捡起这个玩意。

回归初心

在故事的开始,我们是要计算面积的:

年轻的我们写下了这样的代码来解决这个问题:

#include #include #include float randf() {

return float(rand()) / float(RAND_MAX);

}

float srandf() {

return randf()*2.0f - 1.0f;

}

int main(int argc, char **argv) {

int count = 1000000;

float sum = 0.0f;

for (int i=0;i

float x = randf()*2.0f;

sum += x * x;

}

printf("area is %f\n", 2.0f*sum /float(count));

return 0;

}

此时我们可以把后来我们捣腾的这些东西塞进之前的代码里去了,当我们采用蒙特卡洛方法来计算面积的时候,x的取值采用的是随机数,而不是像黎曼和里一样采用左柱子的高度或者采用右柱子的高度。

所以这样的算法就有一个特点就是:你随机的次数越多,得到的结果就越逼近真实的值。所以我们在这里做一个代码到理论的思路映射:

我们这里使用蒙特卡洛方法来计算面积,所以代码里的那个x实际上是随便拿过来的一个东西,这个东西既可以是随机数r本身,也可以是r经过某个函数f处理后的结果,最重要的是,我们要通过这个x知道这个x的pdf和cpdf之类的东西。于是乎,我们想起来之前给同学们推了半天的那些pdf和cpdf、r以及e。我们来修改代码一下,如果pdf为

,那么:

#include #include #include float randf() {

return float(rand()) / float(RAND_MAX);

}

float srandf() {

return randf()*2.0f - 1.0f;

}

int main(int argc, char **argv) {

int count = 1000000;

float sum = 0.0f;

for (int i=0;i

float r=randf();

float e=sqrtf(4*r);

sum += e * e;

}

printf("area is %f\n", 2.0f*sum /float(count));

return 0;

}

上面这部分就是for循环里面的代码,所以我们把之前的代码与先前我们捣腾的一系列公式练习起来了。同样的在这里r的范围是0~1,e的范围是0~2,这样求出来的东西也是满足我们条件的。与先前的代码相比,唯一不一样的地方就是,我们使用了一个f函数对我们的随机数进行了处理,即便进行了处理,我们依然可以把e看成一个随机数,且它的范围满足我们的代码需求,在0~2的范围内。

只不过e与r不一样的地方就在于,我们有关于e的pdf和cpdf。如果我们把这里for循环的次数看成是对某一个东西的采样次数,我们在通过蒙特卡洛方法去估算一个目标结果的时候,采样次数越多,那么估算的精度就越高。而在以往的算法里,每一次随机出来的数据的权重都是1,我们认为这么干是不科学的,我们要给每次采样出来的数据给一个大概的权重,那么这个就可以通过pdf来获取。当我们能够给出每一次采样数据的权重了,之后,我们最终的结果就可以用sum直接除以count,而不必非得采用黎曼和进行面积积分的公式来算了。意思就是说,最后的面积可以直接等于:

因为我们在for循环中会给每次采样的样本一个权重了。而每个样本的数据权重是多少呢?这是我们要思考的问题了,现在我们列举一下我们知道的东西:一个随机数r,它的范围是0~1

一个函数f,它是根据pdf推导出来的

一个数值e,它是f把它变换出来的

一个pdf,它的全称叫:概率密度函数(probability density function)

一个cpdf,它的全称叫:累积分布函数(cumulative probabilitydistribution function)

我们知道这里的推导顺序是,先有个r,然后我们捏造一个合适的pdf,然后就可以推导出cpdf,进而能推导出f函数。因为f函数跟cpdf是一个互为反函数的关系。这里这个pdf的选择就是一个经验性问题,在渲染里面也叫做importance sampling。

综上所述,我们r是随机数,pdf是自己选择出来的一个importance sampling函数,然后其他的东西都是通过这俩家伙推导出来的,那么这到底与咱们的多重采样有个毛儿的关系呢?法克,怎么这么绕,我女朋友手里的蚕豆都掉地上了好吗。

多重采样

作为程序员,我们始终要知道从哪里输入,以及从哪里输出。我们的输入就是r和你自己选的一个pdf,然后输出是e、cpdf以及那个把r转换成e的函数f。

我们现在关注的核心是如何给你一个r,然后这个r输入给f函数,然后生成一个e,然后你要给e多大的权重的问题。实际上这个非常简单,你就给e与它出现的概率相关的权重不就完事了嘛。这也是pdf做的事情,它能影响你最终的采样结果数据中,你更重视哪一块的数据,要不然你叫他概率密度函数干啥,既然是概率密度,那么就意味着有的地方概率大,有的区域的数据的概率小。数值如果概率大,那么它的影响权重当然就大,如果它的概率小,那么它的影响权重当然就小啦。

对应到代码咱们怎么处理呢?我们可以直接让权重等于

,他喵的为啥?为鸟个啥它的权重可以这么玩?

还是前一段话我们描述的问题,如果某数据出现的概率大,那么它的权重就高,我们就采样它的数据更多一点,如果它出现的概率小,那么就让它的权重低,我们就采样它的数据更少一点。

如果作为一个码农,实在是抽象不到那个级别,那么我们就采用特殊法来带入看看对不对,我们用数学归纳法来证明,也就是先给出结论,然后你自己弄几个特例去试试就完事了,比如说,我令权重为

,那么我们for循环里的代码应该这么写:

float r=randf();

float e=sqrtf(4*r);

float weight=

sum+=e*e*weight;

然后我们举几个特殊的例子就知道了,当

的时候,我们有

那么这个图中,我们可以看到的是,越靠近左边,概率越低,因为概率是积分面积嘛。所以这里就有,当e的值越小的时候,概率越低,e的值越大的时候,概率越高。

辣么,我们举个例子扔进去试试:

当r=0.25的时候,e=1.0,此时weight=2

当r=1.0的时候,e=2.0,此时weight=1

此时与我们的预期是相符合的,因为

这样的pdf会让0~1之间的数值在进行平方操作了之后更靠近0。所以靠近0的部分的概率会更大一定。

因此这里的pdf作为importance sampling函数,它代表了我们的采样意愿,我们更愿意采样哪里的数据来作为我们的画面颜色。

当我们选用

的时候,我们的代码应该是下面这样

当我们的pdf选用

的时候,那么我们的cpdf和f函数都要变化,其中比较重要的是f函数,它的推导方法我们在先前的文章中已经介绍,就不再做解释,f函数求出来应该为

最后的最后,我们把求面积的公式采用非黎曼和的方式,而是采用真实的定积分公式进行积分的话,应该是这样子的:

对应的cpdf为:

积分出来后得到在0~2的区间上为:

所以如此一来,f就可以知道了:

好了,公式推完上代码:

完结、撒花,我们到这里就搞明白了一个问题,怎么把概率密度跟多重采样时每个样本的权重结合起来考虑。所以只要你给我一个定积分的公式,加上一个随机数,我就给你一个权重,而这个不正是咱们光照计算里那些玩意嘛?每个光照有多少被反射、有多少被折射。

经过这篇文章后,你的多重采样模块的代码不再是直接对所有样本的和求平均了,你会给每个样本一个权重,而这里每个样本拿到的权重都是与它自身有关。

参考资料《Ray Tracing_ the Rest of Your Life》电子书​www.realtimerendering.com疯狂的程序员:引擎内核基础技术-极坐标是何物​zhuanlan.zhihu.com疯狂的程序员:引擎内核基础技术-球面坐标是何物​zhuanlan.zhihu.com疯狂的程序员:蒙特卡洛方法-最简单的代码​zhuanlan.zhihu.com疯狂的程序员:基本理论-蒙特卡洛方法与定积分​zhuanlan.zhihu.com疯狂的程序员:蒙特卡洛方法-概率密度函数​zhuanlan.zhihu.com疯狂的程序员:蒙特卡洛方法-练习使用概率密度函数​zhuanlan.zhihu.com疯狂的程序员:蒙特卡洛方法-累积分布函数​zhuanlan.zhihu.com

我们核心关注和讨论的领域是引擎的底层技术以及商业化方面的信息,可能并不适合初级入门的同学。另外官方维护两个公众号,第一个公众号是关于我们企业自身产品的信息与动态的公众号,如果对我们自身信息与动态感兴趣的同学,可以关注图形之心。我们核心关注和讨论的领域是引擎的底层技术以及商业化方面的信息,可能并不适合初级入门的同学。另外官方维护两个公众号,第一个公众号是关于我们企业自身产品的信息与动态的公众号,如果对我们自身信息与动态感兴趣的同学,可以关注图形之心。

除此之外,我们为了更频繁的发布一些咨询与文章,我们维护的第二个公众号是“内核观察”,内核观察提供的主要是一些与我们无关的咨询与文章。

只言片语,无法描绘出整套图形学领域的方方面面,只有成体系的知识结构,才能够充分理解和掌握一门科学,这是艺术。我们已经为你准备好各式各样的内容了,东汉书院,等你来玩。

多重采样和超级采样哪个流畅_蒙特卡洛方法-多重采样相关推荐

  1. 机器学习笔记之马尔可夫链蒙特卡洛方法(三)MH采样算法

    机器学习笔记之马尔可夫链蒙特卡洛方法--MH采样算法 引言 回顾:马尔可夫链与平稳分布 马尔可夫链 平稳分布 MH采样算法 采样思路 MH采样算法过程 引言 上一节介绍了马尔可夫链(Markov Ch ...

  2. 机器学习笔记之马尔可夫链蒙特卡洛方法(四)吉布斯采样

    机器学习笔记之马尔可夫链蒙特卡洛方法--吉布斯采样 引言 回顾:MH采样算法 基于马尔可夫链的采样方式 细致平衡原则与接收率 MH采样算法的弊端 吉布斯采样方法 吉布斯采样的采样过程 吉布斯采样的推导 ...

  3. 多重采样和超级采样哪个流畅_测试之前你需要做这些功课

    本文约3568字,需6分钟阅读(全文浏览) 如果让你在脑海里以进化的视野回望过去历史的长河中游戏的画面是如何从拙劣慢慢进化到目前的精细,相信大家都有自己的一套历史观,首先当然是随着分辨率的提高.硬件的 ...

  4. 线性插值改变图像尺寸_图像分割--gt;上采样的那些事

    在图像分割中,因为FCN的提出,上采样操作成为了分割中不可或缺的部分.上采样就是将提取到的feature map还原到原始分辨率大小的操作,但是这里要注意的是上采样不是下采样的逆过程,也就是说上采样输 ...

  5. csgo调哪个会流畅_对于游戏卡顿掉帧说不,三步提高游戏流畅性,让你纵享丝滑画面...

    在我们玩游戏的时候,经常会遇到画面掉帧或者卡顿,严重影响玩家游戏体验,所以小编结合自身经历今天给大家带来如何提高画面帧数以及游戏流畅性的小技巧. 一.什么是FPS数值 要想真正理解FPS,我们必须先科 ...

  6. AI算法连载04:数学基础之蒙特卡洛方法与MCMC采样

    相关文章: AI算法连载01:数学基础之线性代数 AI算法连载02:概率论基础 AI算法连载03:数学基础之数值计算 导语:不懂算法的工程师做不了AI,不懂算法的产品经理将把AI带入泥潭. 一.前言 ...

  7. 信号的采样与恢复matlab实验报告,实验七 连续信号的采样与恢复

    一.实验目的 通过MATLAB仿真验证抽样定理,进一步加深对抽样定理的理解. 二.实验原理 1. 连续信号的采样 对某一连续时间信号f(t)的采样原理图为: 由图可知, ,其中,单位冲激采样信号 的表 ...

  8. 采用拉丁超立方采样的电力系统概率潮流计算 拉丁超立方采样属于分层采样,是一种有效的用采样值反映随机变量的整体分布的方法

    采用拉丁超立方采样的电力系统概率潮流计算 (自适应核密度估计,自适应带宽核密度估计) 拉丁超立方采样属于分层采样,是一种有效的用采样值反映随机变量的整体分布的方法. 其目的是要保证所有的采样区域都能够 ...

  9. 采样与保持实验报告计算机控制,计算机控制技术实验--模拟信号采样与保持文库 .doc...

    PAGE 2 PAGE 1 计算机控制技术实验 题目: 模拟信号采样与保持 班级: 电气F1611 姓名: 学号: 学院: 电子信息与工程学院 2019年 12月 28 日 1.1 采样与保持 一.实 ...

最新文章

  1. Thread 同步线程(打印机同步)
  2. SQL语句where,Group By,having order by 的详细使用方法
  3. Tomcat如何将项目发布到webapps目录下
  4. 重磅!神策数据荣获华农保险 2020 年度优秀生态合作伙伴“最佳合作机构”荣誉称号...
  5. laravel改代码没变化_推荐10个优质的Laravel扩展
  6. oracle一条语句递归查询父子关系
  7. lesson3 数码管静态显示及定时器和中断应用
  8. 如何将Java应用程序置于Apache HTTP服务器之后
  9. 『高级篇』docker之安全认证kubernetes命令熟悉(40)
  10. 敏捷开发系列学习总结(11)——Scrum敏捷开发流程的三个角色、四个会议和三个物件
  11. python手机壁纸超清_【原创】Python必应超清壁纸爬虫
  12. 微信公众号API接口调用
  13. Mysql(2)事务
  14. JUC之集合安全问题
  15. golang-文章翻译-go常见的10种错误
  16. tampermonkey自动化学习(持续更新~)
  17. ThinkPad T14、ThinkPadT16 2022款 评测
  18. 数组逆序重放c语言,计算概论(A)/基础编程练习2(8题)/6:数组逆序重放
  19. 浙江大学吴飞:新一代人工智能:The Next——科教融合,科研育人
  20. 51单片机C语言跑马灯,51单片机上实现控制跑马灯

热门文章

  1. 自动化测试的基础概念
  2. 最终版宝宝取名程序,java版,我宝名字已经确定。 HttpURLConnection
  3. Unity 3D游戏——神鬼传说
  4. (JavaWeb笔记)win10+Tomcat8.5.69安装和配置
  5. 程序员被违法辞退?这笔钱你拿到了吗?
  6. 诺基亚大陆行货手机真假查询检查方法?(超级简单实用)
  7. 星愿浏览器扩展程序Win8路径
  8. R如何对表格中某个变量进行统计
  9. 多屏互动到底有几种玩法
  10. 宿主DAW编曲软件 FL Studio 21中文版超过 25 年的持续更新