《學一輩子光線追蹤》 二點五五 在球面方向的MC積分

蒙特卡洛光線追蹤技術系列 見 蒙特卡洛光線追蹤技術

竟然有兩個第二章,我也是很無奈啊。

在我們的光線跟蹤器中,我們選擇隨機方向,方向可以表示爲單位球體上的點。採用與之前相同的方法。但現在我們需要在二維上定義一個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是一樣的。

現在讓我們繼續討論我們正在求解的光傳輸方程。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章