蒙特卡洛光線追蹤技術系列 見 蒙特卡洛光線追蹤技術
竟然有兩個第二章,我也是很無奈啊。
在我們的光線跟蹤器中,我們選擇隨機方向,方向可以表示爲單位球體上的點。採用與之前相同的方法。但現在我們需要在二維上定義一個pdf。假設我們在所有方向上都有這個積分:
INTEGRAL( cos^2(theta) )
即我們需要計算 ∫ cos2θdθ
通過MC積分,我們應該能夠得到 cos^2(theta)/p(direction) 的樣本。但在這種情況下,方向是什麼?我們可以根據極座標來計算,所以p是(theta,phi)。但是,請記住,pdf必須積分爲1,並表示該方向被採樣的相對概率。我們有上一本書中的一種方法,可以在一個單位的球體中取均勻的隨機樣本:
vec3 random_in_unit_sphere() {
vec3 p;
do {
p = 2.0*vec3(myRandom(), myRandom(), myRandom()) - vec3(1, 1, 1);
} while (dot(p, p) >= 1.0);
return p;
}
爲了得到單位球面上的點,我們可以將向量規格化爲這些點:
vec3 random_in_unit_sphere() {
vec3 p;
do {
p = 2.0*vec3(myRandom(), myRandom(), myRandom()) - vec3(1, 1, 1);
} while (dot(p, p) >= 1.0);
return unitVector(p);
}
現在這些統一的點的pdf是什麼?作爲單位球體上的密度,它是球體的1/面積或1/(4*Pi)。如果被積函數是cos^2(θ),θ是與z軸的夾角:
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include "time.h"
#include "Vec3.h"
#define M_PI 3.14159265
double myRandom() {
return rand() / (RAND_MAX + 1.0);
}
vec3 random_in_unit_sphere() {
vec3 p;
do {
p = 2.0*vec3(myRandom(), myRandom(), myRandom()) - vec3(1, 1, 1);
} while (dot(p, p) >= 1.0);
return unitVector(p);
}
inline float pdf(const vec3&p) {
return 1 / (4 * M_PI);
}
int main() {
srand(time(NULL));
int N = 1000000;
float sum = 0.0;
for (int i = 0;i < N;i++) {
vec3 d = random_in_unit_sphere();
float cosine_squared = d.z()*d.z();
sum += cosine_squared / pdf(d);
}
printf("I = %f \n", sum/N);
system("pause");
}
得到結果:
分析答案(如果你還記得足夠的高級計算,請檢查我!)是(4/3)*Pi,上面的代碼生成這個值。接下來,我們準備將其應用於光線跟蹤!
這裏的關鍵點是所有的積分和概率,以及所有在單位球面上的積分和概率。單位球面上的面積是如何測量方向的。稱之爲方向,立體角,或面積-都是一樣的。立體角是常用的術語。如果你對它的理解感到很舒服,那就太好了!但如果不是,做我所做的,想象單位球面上一組方向通過的區域。立體角ω和單位球面上的投影面積A是一樣的。
現在讓我們繼續討論我們正在求解的光傳輸方程。