1. 程式人生 > >PBRT_V2 總結記錄 <28> Fresnel 和 FresnelConductor 和 FresnelDielectric 和 FresnelNoOp

PBRT_V2 總結記錄 <28> Fresnel 和 FresnelConductor 和 FresnelDielectric 和 FresnelNoOp

Fresnel 類:

class Fresnel {
public:
    // Fresnel Interface
    virtual ~Fresnel();
    virtual Spectrum Evaluate(float cosi) const = 0;
};

類的作用:

(Fresnel  是 FresnelConductor 和  FresnelDielectric 的子類)

For convenience, we will define an abstract Fresnel class that provides an interface for computing Fresnel reflection coefficients.

The FresnelConductor and FresnelDielectric implementations of this interface help simplify the implementation of subsequent BRDFs that may need to support both forms.

1. virtual Spectrum Evaluate(float cosi) const = 0;

The only method provided by the Fresnel interface is Fresnel::Evaluate(). Given the cosine of the angle made by the incoming direction and the surface normal, it returns the amount of light reflected by the surface.

FresnelConductor 類

class FresnelConductor : public Fresnel {
public:
    // FresnelConductor Public Methods
    Spectrum Evaluate(float cosi) const;
    FresnelConductor(const Spectrum &e, const Spectrum &kk)
        : eta(e), k(kk) {
    }

private:
    Spectrum eta, k;
};

類的作用:

(模擬導體的反射,導體只有reflectance,沒有 transmitted)

1.  

Spectrum FresnelConductor::Evaluate(float cosi) const {     return FrCond(fabsf(cosi), eta, k); }  

作用:

(直接呼叫 上一節的 FrCond 方法)

The evaluation routine for FresnelConductor is also simple; it just calls the FrCond() function defined earlier. Note that it takes the absolute value of cosi before calling FrCond(), since FrCond() expects that the cosine will be measured with respect to the normal on the same side of the surface as ωi, or equivalently that the absolute value of cos θi should be used.

FresnelDielectric 類

class FresnelDielectric : public Fresnel {
public:
    // FresnelDielectric Public Methods
    Spectrum Evaluate(float cosi) const;
    FresnelDielectric(float ei, float et) : eta_i(ei), eta_t(et) { }
private:
    float eta_i, eta_t;
};

類的作用:

(模擬絕緣體材質,有reflectanc 和 transmitted, transmitted = 1 - reflectanc)

FresnelDielectric similarly implements the Fresnel interface for dielectric materials

1. 


Spectrum FresnelDielectric::Evaluate(float cosi) const {
    // Compute Fresnel reflectance for dielectric
    cosi = Clamp(cosi, -1.f, 1.f);

    // Compute indices of refraction for dielectric
    bool entering = cosi > 0.;
    float ei = eta_i, et = eta_t;
    if (!entering)
        swap(ei, et);

    // Compute _sint_ using Snell's law
    float sint = ei/et * sqrtf(max(0.f, 1.f - cosi*cosi));
    if (sint >= 1.) {
        // Handle total internal reflection
        return 1.;
    }
    else {
        float cost = sqrtf(max(0.f, 1.f - sint*sint));
        return FrDiel(fabsf(cosi), cost, ei, et);
    }
}

細節:

a.

(先判斷入射向量是 是否與 法線在同一個半球,如果不是的話,就要 交換 折射的兩個 indices,利用 Snell's Law 來計算出

sin θt, 再計算出 cos θt,得到 FrDiel 方法需要的所有引數)

Evaluating the Fresnel formula for dielectric media is a bit more complicated than for conductors. First, it is necessary to determine if the incident direction is on the outside of the medium or inside it, so that the two indices of refraction can be interpreted(解析) appropriately. Next, Snell’s law is applied to compute the sine of the angle between the transmitted direction and the surface normal. Finally, the cosine of this angle is found using the identity sinθ^2 + cos θ^2 = 1.

b.

bool entering = cosi > 0.; float ei = eta_i, et = eta_t; if (!entering)     swap(ei, et);

作用:

(判斷入射向量是 是否與 法線在同一個半球,如果不是的話,就要 交換 折射的兩個 indices)

The sign of the cosine of the incident angle indicates on which side of the medium the incident ray lies (Figure 8.6). If the cosine is between 0 and 1, the ray is on the outside, and if the cosine is between −1 and 0, the ray is on the inside. The variables ei and et are set such that ei has the index of refraction of the incident medium.

c.

float sint = ei/et * sqrtf(max(0.f, 1.f - cosi*cosi));

作用:

(利用 Snell's Law 來計算出 sin θt)

Once the indices of refraction are set, we can compute sin θt using Snell’s law:

d.

if (sint >= 1.)     // Handle total internal reflection     return 1.; }

作用:

(如果 sint 大於1 表示,全部反射 )

When light is traveling from one medium to another medium with a lower index of refraction, none of the light at incident angles near grazing(擦邊) passes into the other medium.

The largest angle at which this happens is called the critical angle; when θi is greater than the critical angle, total internal reflection occurs, and all of the light is reflected. That case is detected here by a value of sin θt greater than one; in that case, the Fresnel equations are unnecessary.

FresnelNoOp 類:

class FresnelNoOp : public Fresnel {
public:
    Spectrum Evaluate(float) const { return Spectrum(1.); }
};

類的作用:

(100% 反射)

The FresnelNoOp implementation of the Fresnel interface returns 100% reflection for all incoming directions. Although this is physically implausible, it is a convenient capability to have available