《学一辈子光线追踪》 一 引言和一个简单的蒙特卡洛程序

编程入门 行业动态 更新时间:2024-10-10 23:15:32

《学一辈子光线追踪》 一 <a href=https://www.elefans.com/category/jswz/34/1749188.html style=引言和一个简单的蒙特卡洛程序"/>

《学一辈子光线追踪》 一 引言和一个简单的蒙特卡洛程序

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

引言:

在一个周末的光线跟踪和光线跟踪:下周,你建立了一个“真正的”光线跟踪器。

在本卷中,我假设您将从事与光线跟踪相关的职业,我们将深入研究创建非常严肃的光线跟踪器的数学。完成后,您应该准备好开始处理电影和产品设计行业中许多重要的商业光线跟踪器。在这本小册子中,我没有介绍很多东西;我只探讨了编写Monte Carlo渲染程序的多种方法中的一种。我不做阴影光线(相反,我使光线更有可能朝向灯光)、双向方法bidirectional methods、Metropolis方法或光子贴图photon mapping。我所做的就是用研究这些方法的领域的语言来说话。我认为这本书可以是你以后工作的一个深入的接触,它将装备你的一些概念,数学和术语,你将需要学习其他知识。

一个简单的蒙特卡洛程序:

让我们从最简单的Monte Carlo(MC)程序开始。MC程序给出一个答案的统计估计,这个估计值随着运行时间的延长而变得越来越精确。简单程序产生噪音但得到更好的答案的这一基本特征就是MC的全部内容,它尤其适用于不需要高精度的图形等应用。

作为一个例子,我们来估计Pi。有很多方法可以做到这一点,Buffon针问题是一个典型的案例研究。我们将做一个受此启发的变化。假设你在一个正方形内有一个内接圆:

现在,假设你在正方形内随机选取点。那些最终进入圆内的随机点的分数应该与圆的面积成比例。确切的分数应该是圆面积与平方面积的比值。

Fraction = (Pi*R*R) / ((2R)*(2R)) = Pi/4
因为R被抵消了,我们可以选择任何计算上方便的R。让R=1以原点为中心:

#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include "time.h"double myRandom() {return rand() / (RAND_MAX + 1.0);
}int main() {srand(time(NULL));int N = 1000;int inside_circle = 0;for (int i = 0;i < N;i++) {float x = 2 * myRandom() - 1;float y = 2 * myRandom() - 1;if (x*x + y*y < 1)inside_circle++;}printf("Estimate of PI = %f \n",4*float(inside_circle)/N);system("pause");
}

这给出了pi=3.196的答案估计值

如果我们将程序更改为永久运行并打印出运行估计,我们会得到很接近的估计。

我们很快接近圆周率,然后慢慢地接近它。这是收益递减定律的一个例子,其中每个样本的帮助小于上一个样本,这是MC最糟糕的部分。我们可以通过对样本进行分层(通常称为抖动)来缓解这种递减的回报,在这种情况下,我们不是随机抽取样本,而是在每个样本中抽取一个网格并抽取一个样本:

#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include "time.h"
double myRandom() {return rand() / (RAND_MAX + 1.0);
}
int main() {srand(time(NULL));int inside_circle = 0;int inside_circle_stratified = 0;int sqrt_N = 10000;for (int i = 0;i < sqrt_N;i++) {for (int j = 0;j < sqrt_N;i++) {float x = 2 * myRandom() - 1;float y = 2 * myRandom() - 1;if (x*x + y*y < 1)inside_circle++;x = 2 * ((i + myRandom()) / sqrt_N) - 1;y = 2 * ((j + myRandom()) / sqrt_N) - 1;if (x*x + y*y < 1)inside_circle_stratified++;}}printf("Regular Estimate of PI = %f \n", 4 * float(inside_circle) / (sqrt_N*sqrt_N));printf("Stratified Estimate of PI = %f \n", 4 * float(inside_circle_stratified) / (sqrt_N*sqrt_N));system("pause");
}

得到结果:

有趣的是,分层方法不仅更好,而且收敛速度更快!不幸的是,这一优势随着问题的规模而减小(例如,对于3D球体体积版本,优势差距会更小)。这叫做维度诅咒。我们的MC光线追踪将是非常高的维度(每个反射增加两个维度),所以我不会在这本书分层。但是如果你曾经做过单次反射或阴影,或者一些严格的二维问题,你肯定想分层。

后记:

还记得我在这个系列中前几节关于《MCRT》书中讲到的关于分层方法 蒙特卡洛光线追踪 (准)蒙特卡洛积分,当时我在记录了一大堆数学公式以后,写了一个结论:

分层抽样的效果会比较好。

等我把下一节一维MC相关内容整理完以后,我再重新阐述一下MC分层抽样的原理。

更多推荐

《学一辈子光线追踪》 一 引言和一个简单的蒙特卡洛程序

本文发布于:2024-03-14 02:01:57,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1735379.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:引言   光线   蒙特   卡洛   简单

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!