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

 

开学人倍忙,趁着第二周周末,咱们继续图形相关的博客html

 

 Prefacedom

今天咱们来介绍一些理论方面的东西,为Monte Carlo 应用到咱们的光线追踪器作铺垫函数

咱们今天会介绍两章的东西,由于有一章内容太过简单学习

本篇目的原版内容 见相册spa

这个东西你点上去会有页数的,不要看混了设计

 

 readycode

看这一篇您须要具有如下知识htm

1. 了解重要性采样blog

2. 二重积分,基础微分ci

3. (半)球坐标系

4. 光线追踪基本原理

5. 立体角(solid angle),如今普及一下

首先类比二维空间的圆,假设咱们在二维空间内定义了一个单位圆,咱们截取圆上的一段弧AB,它对应的圆心角为∠α

并且咱们知道弧长 = α*R,那么整个周长就是C = 2*π*R

那么咱们三维空间,仍然有相似的定义

    

 

记粉色区域为A 

立体角的单位是球面度(sr),1sr定义为球面上一块面积(A)为R2的区域,从球心看过去的三维角度。

类比于二维圆上的圆弧和圆心角,那块面积区域为三维弧度,面积区域相对于球心在三维坐标系下的张角即为立体角

立体角计算

Ω = ∫∫A (sinθ)dθdφ

A为三维弧度

其中,θ表明经度,φ表明维度

整个球面的立体角为

Ω = 0->2π dφ ∫0->π (sinθ)

Ω = 2π*2 = 4π

 

 content

咱们以前的光线追踪器中有一个过程是获取一个三维空间的随机方向,咱们利用单位球体内的随机点来表明该方向,那么咱们今天用Monte Carlo 来实现相同的效果

 

Chapter2 MC Integration on the Sphere of Directions

首先咱们须要定义一个2D的pdf函数

咱们假定下面这个积分适用于任意方向

   ∫cos2θdθ

在MC积分下,咱们应该作 cos2θ/p(direction) 的采样

可是这里的direction在咱们的环境中如何定义的呢?

咱们须要在极坐标系下进行定义,p是关于θ和φ的一个函数

可是,无论你怎么整,必定要记住,

设计一个pdf函数,它的积分必须是1,而且pdf表明着该方向被采样的相对几率

咱们看一下以前咱们的随机函数(模板和异常可忽略)

template<typename T = lvgm::precision>
    const lvgm::vec3<T> random_unit_sphere()    
        {
        if (typeid(T) == typeid(int))
            {
            std::cerr << "integer doesn't have a random number from 0 to 1\n";
            throw "integer doesn't have a random number from 0 to 1\n";
            }

        lvgm::vec3<T> p;
        do
            {
            p = 2.0*lvgm::vec3<T>(rand01(), rand01(), rand01()) - lvgm::vec3<T>(1, 1, 1);
            } while (dot(p, p) >= 1.0);
        return p;
        }

这获得的是单位球体内部的随机三维点

若是咱们要获得球体表面的三维空间点,那么咱们只须要单位化一下便可

也就是return p的单位化向量

那么,可以表明这些球体表面点的pdf函数应该是什么呢?

做为单位球体表面点的均匀密度,用立体角的方式定义均匀密度

即单位立体角的球面度/整个球体对应的球面度,也就是1/球体面积 或者 1/4π

 

若是被积函数咱们选取上面的cos2θ,θ为随机方向与z轴的夹角,那么程序以下

void sphereMC()
{
    auto pdf = []() {return 1 / (4 * π); };
    size_t n{ 10000000 };
    double sum{ 0 };
    for (int i = 0; i < n; ++i)
    {
        dvec3 d = random_unit_sphere().ret_unitization();
        double cosine = d.z()*d.z();
        sum += cosine / pdf();
    }
    stds cout << "I = " << sum / n << stds endl;
}

答案是 4π/3,绝对没毛病

 

 Chapter3 Light Scaterring

在上本书中,咱们基于表面或者次表面实现散射光线,这是一个普适模型。

可是,更天然的方式是几率,该光线多大几率被吸取了?

设   光线反射几率为A

那么 光线被吸取的几率就为 1-A

这里的A其实表明以前材质中的albedo(latin for whiteness)。

Albedo表明着某些反射形式的反射比例

当咱们实现玻璃材质的时候,albedo伴随着入射光线方向的变化而变化,进而计算相应变化的像素值

在大多数的基于物理的渲染器,咱们将用一组波长表示浅色而不是RGB,咱们用长中短波长来表明RGB

若是实现光散射,那么咱们能够基于立体角设计一个pdf来描述光线散射方向分布。

我将其称为散射pdf:sdirection),这个散射pdf也会随着入射方向的变化而变化

 

因此这个表面色彩就数量(wavelength)而言有以下积分形式

color =  A * s(direction) * color(direction) dθ    [公式1]

须要注意的是:A 和 s()都是依赖于观察方向的,固然,color也随着观察方向的变化而变化,A 和 s()也可能随着表面或体内部的位置而变化

 

若是咱们将Monte Carlo应用到上面的积分的话,那么咱们获得以下的统计估计公式

Color = (A * s(direction) * color(direction)) / p(direction)  [公式2]

 

这里的p(direction)是方向参数随机模拟生成的一个pdf函数

 

对于Lambertian材质表面,咱们假定其密度是呈余弦规律的。

so, 一个Lambertian表面的p()是正比于cosθ,而θ是光线方向和表面法线的夹角,还须要注意一点:全部设计的pdf函数在定义域内的积分必须是1

咱们还知道,对于磨砂表面来讲,入射光线和表面法线的夹角不会超过90°,因此,咱们定义

对于 cosθ < 0 的状况,咱们设定s(direction) = 0

因此有效区间为半球面,而基于半球的cos积分为π,这个怎么理解呢?

还记得already中的球面度吗?咱们那时候说过那个区域A的微分形式(基于球坐标)为

dA = sinθ dθdφ

因此,半球面积 = 

 

因此,Lambertian表面散射pdf为:

  s(direction) = cosθ / π        [公式3]

若是咱们采样也使用一样的pdf函数,

即: p(direction) = cosθ/π          [公式4]

那么分子分母能够消去,就获得了

  Color = A * color(direction) 

这是咱们原始的color函数中的设定,但咱们如今须要归纳一下完整的形式,以便咱们能够向重要方向发送额外的光线,例如朝向灯光。

 

若是你看过其余相关书籍,你可能会看到双向反射分布函数(BRDF)描述的反射。 它的表示形式很是简单:

BRDF =  A * s(direction) / cosθ      [公式5]

例如,对于朗伯表面,BRDF = A / Pi。(联立公式三、5可得)

咱们的表达方式和BRDF之间的转换很容易。而对于参与媒体(卷),咱们的反照率一般被称为散射反照率,而咱们的反照片一般被称为相位函数。

 

这一篇主要讲一些理论相关的东西,可能没什么直观感觉,可是下一篇学习的时候就须要用到这些东西了,没感受的也不要紧,结合下一篇可能会体会更深入一点

 

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

相关文章
相关标签/搜索