shade(p, wo) sampleLight(inter , pdf_light) Get x, ws, NN, emit from inter Shoot a ray from p to x If the ray is not blocked in the middle L_dir = emit * eval(wo, ws, N) * dot(ws, N) * dot(ws, NN) / |x-p| ^2 / pdf_light L_indir = 0.0 Test Russian Roulette with probability RussianRoulette wi = sample(wo, N) Trace a ray r(p, wi) If ray r hit a non -emitting object at q L_indir = shade(q, wi) * eval(wo, wi, N) * dot(wi, N) / pdf(wo, wi, N) / RussianRoulette
Return L_dir + L_indir
Monte Carlo Integration
概率相关知识
设是一个随机变量,是任意实数,则称 为的累计分布函数(Cumulative Distribution Function,CDF)。如果对于随机变量 的累计分布函数 ,存在非负函数,使对任意实数,有 则称 为连续性随机变量,其中函数 称为 的概率密度函数,简称概率密度(Probability Distribution Function,PDF)。概率密度具有以下几个性质:
shade(p, wo) Randomly choose N directions wi~pdf Lo = 0.0 For each wi Trace a ray r(p, wi) If ray r hit the light Lo += (1 / N) * L_i * f_r * cosine / pdf(wi) Else If ray r hit an object at q Lo += (1 / N) * shade(q, -wi) * f_r * cosine / pdf(wi) Return Lo
ray_generation(camPos, pixel) Uniformly choose N sample positions within the pixel pixel_radiance = 0.0 For each sample in the pixel Shoot a ray r(camPos, cam_to_sample) If ray r hit the scene at p pixel_radiance += 1 / N * shade(p, sample_to_cam) Return pixel_radiance
Problem 2: The recursive algorithm will never stop
shade(p, wo) Manually specify a probability P_RR Randomly select ksi in a uniform dist. in [0, 1] If (ksi > P_RR) return0.0
Randomly choose N directions wi~pdf Lo = 0.0 For each wi Trace a ray r(p, wi) If ray r hit the light Lo += (1 / N) * L_i * f_r * cosine / pdf(wi) / P_RR Else If ray r hit an object at q Lo += (1 / N) * shade(q, -wi) * f_r * cosine / pdf(wi) / P_RR Return Lo
# Contribution from the light source. Uniformly sample the light at x’ (pdf_light = 1 / A) Shoot a ray from p to x’ If the ray is not blocked in the middle L_dir = L_i * f_r * cos θ * cos θ’ / |x’ - p|^2 / pdf_light
# Contribution from other reflectors. L_indir = 0.0 Test Russian Roulette with probability P_RR Uniformly sample the hemisphere toward wi (pdf_hemi = 1 / 2pi) Trace a ray r(p, wi) If ray r hit a non-emitting object at q L_indir = shade(q, -wi) * f_r * cos θ / pdf_hemi / P_RR
We can use the fact that the cross product gives a vector orthogonal to the two vectors to write a function that takes one vector and returns two new vectors so that the three of them form an orthonormal coordiante system. Specifically, all three of the vectors will be perpendicular to each other. Note that the other two vectors returned are only unique up to a rotation about the given vector. This function assumes that the vector passed in, , has already been normalized. We first construct a perpendicular vector by zeroing one of the two components of the original vector and permuting the remaining two. Inspection of the two cases should make clear that will be normalized and that the dot product will be equal to zero. Given these two perpendicular vectors, one more cross product wraps things up to give us the third, which by definition of the cross product will be be perpendicular to the first two[1].