今天起,我们就开始学习第三本书了

  

这本书主要讲的是蒙特卡罗渲染,以及相关的数学、术语概念等

这本书相较于前面两本有着什么不同,承担着什么样的任务,尚涉书未深,姑妄言之:

第一本书,带领我们初探光线追踪技术,感受一下

第二本书,篇幅页目最多,带着我们一步一步,构建了一个“真正”的光线追踪器,这里真正指的是,第二本书的内容较广,涉及纹理、光照、烟雾,随机初步等,所谓麻雀虽小,五脏俱全,此所谓“真正”

第三本书,让我们更加走进了实际的光线追踪器,偏向工业级的,所以,作者前言即讲到,如果你想要从事光线追踪相关的行业,这本书为你准备。学过第二本书,我们知道,越往后面,渲染效果越不尽人意,这里指的是如果采样点过少(例如几百),根本无法渲染出真实的效果,比如光照相关的Cornell box例子就有很多噪声干扰,这些,玩玩还可以,但是,离专业还有距离,也就是它只是一个五脏俱全的劣质品,并不能称得上是真正的光线追踪器。

而这本书承担的任务只有一个,就是利用Monte Carlo(MC)方法优化我们第二本书中的渲染效果,也就是为第二本书中的光线追踪机器装一个高端的引擎驱动内核零件,让它更好。

我们先来一个简单的开胃菜

chapter 1:A Simple Monte Carlo Program

蒙特卡罗方法(MC)是一种统计模拟方法,是一类很重要的数值计算方法,它是一种使用随机数解决好很多实际问题的方法。

先来看一个很简单的例子:估计π

有很多经典的方法,其中之一是

假设你扔了很多随机的点到方框中,那么有一部分在圆内,其中圆内点和方框点的比例应该就是圆的面积和方框面积的比例,由此:

比例 = (π * R * R)/((2R)*(2R)) = π/4

所以上式和R无关,我们任意取R = 1,圆心位于原点,则

#include <iostream>
#include <lvgm\randfunc.hpp>
#define stds std::
using namespace lvgm; void estimate_π(const size_t points)
{
int inside = ;
for (int i = ; i < points; ++i)
{
double x = * rand01() - ;
double y = * rand01() - ;
if (x*x + y*y < )
inside++;
}
stds cout << "Estimate of π by" << points << "test points is " << * double(inside) / points << stds endl;
}

int main()
{
  estimate_π(1000);
  estimate_π(10000);
  estimate_π(100000);
  estimate_π(1000000);
  estimate_π(10000000);
  estimate_π(10000000 / 2);
}

模拟结果为

当然我们可以利用下面的程序使结果迅速逼近π

void lawDiminishingReturns()
{
int inside = ;
int runs = ;
while (true)
{
runs++;
double x = * rand01() - ;
double y = * rand01() - ;
if (x*x + y*y < )
inside++;
if(runs % == )
stds cout << "Estimate of π by" << runs << "test points is " << * double(inside) / runs << stds endl;
}
}

结果:

.

一开始非常快速的逼近π,之后变化就比较缓慢了,这是一个收益递减法(Law of Diminishing Returns)的例子

即每一个样本对结果的收益少于后面一个,这个是MC的一个缺点,我们可以通过对样本进行分层来减轻这种递减收益,此法通常称为抖动

我们进行网格划分,并在每个网格中选取一个样本:

我们采用边长为1e4的方框进行测试

void stratify()
{
size_t inside{ };
size_t circle_stratified{ };
size_t sqrtAll = 1e4;
for (int i = ; i < sqrtAll; ++i)
for (int j = ; j < sqrtAll; ++j)
{
double x = * rand01() - ;
double y = * rand01() - ;
if (x*x + y*y < )
inside++;
x = * ((i + rand01()) / sqrtAll) - ;
y = * ((j + rand01()) / sqrtAll) - ;
if (x*x + y*y < )
circle_stratified++;
}
stds cout << "Regular Estimate of π by 1e8 test points is " << * double(inside) / 1e8 << stds endl;
stds cout << "Stratified Estimate of π by 1e8 test points is " << * double(circle_stratified) / 1e8 << stds endl;
}

图片渲染运算读写文件的时候慢。。如今控制台运算输出也整不动了。。。。

有意思~

分层方法能更好地收敛于渐近率。不足之处是,这个优势随着问题的维度而降低(例如,对于3D球体积版本,差距会更小)。 这被称为维度诅咒(=.=)。 我们的工程将是非常高的维度(每个反射增加两个维度),所以我不会在本书中进行分层。

但是,如果你做的是单反射或阴影或某些严格的2D问题,分层是个很好的选择

感谢您的阅读,生活愉快~

【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-1 蒙特卡罗 (一)的更多相关文章

  1. 【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-7 混合概率密度

     Preface 注:鉴于很多网站随意爬取数据,可能导致内容残缺以及引用失效等问题,影响阅读,请认准原创网址: https://www.cnblogs.com/lv-anchoret/category ...

  2. 【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-5 random direction & ONB

     Preface 往后看了几章,对这本书有了新的理解 上一篇,我们第一次尝试把MC积分运用到了Lambertian材质中,当然,第一次尝试是失败的,作者发现它的渲染效果和现实有些出入,所以结尾处声明要 ...

  3. 【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-4 基于重要性采样的材质初探

     Preface 我们今天来把第三本书从开局到现在讲的一大堆理论运用到我们的框架中,那么今天我们首先将原始的材质改为基于重要性采样原理的材质 这一篇是代码工程中进行MC理论应用的初步尝试篇  Read ...

  4. 【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-6 直接光源采样

    Chapter7 Sample Lights Directly  Preface 今天我们来讲这个还算牛逼的技术——直接光源采样 之前我们提到过,在2-7 前两篇我们也提到要减少噪点,就是图片上的黑点 ...

  5. 【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-3 蒙特卡罗 (三)

    开学人倍忙,趁着第二周周末,我们继续图形相关的博客  Preface 今天我们来介绍一些理论方面的东西,为Monte Carlo 应用到我们的光线追踪器做铺垫 我们今天会介绍两章的东西,因为有一章内容 ...

  6. 【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-2 蒙特卡罗(二) 重要性采样

    书本内容:见相册 preface 还记的我们上一篇说的Monte Carlo 维度诅咒吗 上一篇算是二维的例子吧,大家看了之后是否想着写一个一维的Monte Carlo模拟积分?(我想了,没写出来) ...

  7. html5的float属性超详解(display,position, float)(文本流)

    html5的float属性超详解(display,position, float)(文本流) 一.总结 1.文本流: 2.float和绝对定位都不占文本流的位置 3.普通流是默认定位方式,就是依次按照 ...

  8. HTML中DOM核心知识有哪些(带实例超详解)

    HTML中DOM核心知识有哪些(带实例超详解) 一.总结: 1.先取html元素,然后再对他进行操作,取的话可以getElementById等 2.操作的话,可以是innerHtml,value等等 ...

  9. Mysql超详解

    Mysql超详解 一.命令框基本操作及连接Mysql 找到Mysql安装路径,查看版本 同时按快捷键win+R会弹出一个框,在框中输入cmd 点击确定后会出现一个黑框,这是命令框,我们的操作要在这命令 ...

随机推荐

  1. Remaiten-一个以路由器和IoT设备为目标的Linux bot

    Remaiten-一个以路由器和IoT设备为目标的Linux bot ESET的研究人员正在积极地检测以嵌入式系统为攻击目标的木马,受影响的有路由器,网关和无线访问点.近期,我们已经发现了一个相关的b ...

  2. android logger 日志工具

    https://github.com/orhanobut/logger 基础使用:https://blog.csdn.net/github_33304260/article/details/54799 ...

  3. maven阿里云镜像

    <mirrors> <mirror> <id>nexus-aliyun</id> <mirrorOf>central</mirrorO ...

  4. [Fedora 20] 设置Terminal快捷键 + 设置桌面快捷方式 + Terminal透明解决方案

    一.设置Terminal快捷键 刚安装Fedora的时候,习惯性的按Ctrl+Alt+T可是终端怎么都不出来,这才意识到Fedora和Ubuntu是不一样的,于是自己设置快捷键 1.进入All set ...

  5. 函数前加static与不加static的区别

    1:加了static后表示该函数失去了全局可见性,只在该函数所在的文件作用域内可见 2:当函数声明为static以后,编译器在该目标编译单元内只含有该函数的入口地址,没有函数名,其它编译单元便不能通过 ...

  6. 数据库的连接使用——使用ADO.NET连接数据库

    一.ADO.NET简介 ADO.NET是由很多类组成的一个类库,这些类库提供了很多对象,用来完成数据的连接.查询.插入.更新和删除等操作.其中主要包括以下对象: 1.Connection对象:用来连接 ...

  7. 根据条件返回相应值 decode(条件,值1,翻译值1,值2,翻译值2,...值n,翻译值n,缺省值)

    decode(条件,值1,翻译值1,值2,翻译值2,...值n,翻译值n,缺省值) [功能]根据条件返回相应值 [参数]c1, c2, ...,cn,字符型/数值型/日期型,必须类型相同或null 注 ...

  8. LeetCode(5):最长回文子串

    Medium! 题目描述: 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 长度最长为1000. 示例: 输入: "babad" 输出: "bab&quo ...

  9. Luogu P4945 【最后的战役】

    本来以为做法一样,就是少带个$log$,结果发现看不懂出题人的题解(我好菜啊) 那就自己写一篇吧 比较简单的$DP$思路 状态定义: 前两个转移很好处理,第三个好像就不好办了 不妨暴力定义进状态里 设 ...

  10. SPOJ-SERVICE 线性dp+维度压缩

    还是线性dp,有点感觉了,另外这个问题也可以用滚动数组 /* 依然是先按照阶段i划分, dp[i][j][k]表示完成第i个请求时,两个员工分别在j位置和k位置的费用(还有一个员工一定在位置p) dp ...