PBRT_V2 总结记录 <32> OrenNayar

概述:

(Oren and Nayar 主要是模拟 粗糙表面的,主要是利用反射模型去模拟)

Oren and Nayar (1994) observed(观察) that real-world objects tend not to exhibit perfect Lambertian
reflection. Specifically, rough surfaces generally appear brighter as the illumination
direction approaches the viewing direction.
They developed a reflection model that
describes rough surfaces
as a collection of symmetric V-shaped grooves in an effort to
better model effects like these.
They further assumed that each individual microfacet
(groove face) exhibited perfect Lambertian reflection and derived a BRDF that models
the aggregate reflection of the collection of grooves. The distribution of microfacets was
modeled with a Gaussian distribution with a single parameter σ, the standard deviation
of the orientation angle.

 

The resulting model, which accounts for shadowing, masking, and interreflection among
the microfacets, does not have a closed-form solution, so they found the following approximation
that fit it well:

where if σ is in radians,

 

OrenNayar 类

class OrenNayar : public BxDF {
public:
    // OrenNayar Public Methods
    Spectrum f(const Vector &wo, const Vector &wi) const;
    OrenNayar(const Spectrum &reflectance, float sig)
        : BxDF(BxDFType(BSDF_REFLECTION | BSDF_DIFFUSE)),
          R(reflectance) {
        float sigma = Radians(sig);
        float sigma2 = sigma*sigma;
        A = 1.f - (sigma2 / (2.f * (sigma2 + 0.33f)));
        B = 0.45f * sigma2 / (sigma2 + 0.09f);
    }
private:
    // OrenNayar Private Data
    Spectrum R;
    float A, B;
};

1. 构造函数:

OrenNayar(const Spectrum &reflectance, float sig)
        : BxDF(BxDFType(BSDF_REFLECTION | BSDF_DIFFUSE)),
          R(reflectance) {
        float sigma = Radians(sig);
        float sigma2 = sigma*sigma;
        A = 1.f - (sigma2 / (2.f * (sigma2 + 0.33f)));
        B = 0.45f * sigma2 / (sigma2 + 0.09f);
    }

(预计算 A,B,为了之后计算 BRDF的时候,节省计算量)

The implementation precomputes and stores the values of the A and B parameters
in the constructor to save work in evaluating the BRDF later.

 

2. Spectrum f(const Vector &wo, const Vector &wi) const;

(下面的代码其实就是 翻译上面公式)


Spectrum OrenNayar::f(const Vector &wo, const Vector &wi) const {
    float sinthetai = SinTheta(wi);
    float sinthetao = SinTheta(wo);
    // Compute cosine term of Oren-Nayar model
    float maxcos = 0.f;
    if (sinthetai > 1e-4 && sinthetao > 1e-4) {
        float sinphii = SinPhi(wi), cosphii = CosPhi(wi);
        float sinphio = SinPhi(wo), cosphio = CosPhi(wo);
        float dcos = cosphii * cosphio + sinphii * sinphio;
        maxcos = max(0.f, dcos);
    }

    // Compute sine and tangent terms of Oren-Nayar model
    float sinalpha, tanbeta;
    if (AbsCosTheta(wi) > AbsCosTheta(wo)) {
        sinalpha = sinthetao;
        tanbeta = sinthetai / AbsCosTheta(wi);
    }
    else {
        sinalpha = sinthetai;
        tanbeta = sinthetao / AbsCosTheta(wo);
    }
    return R * INV_PI * (A + B * maxcos * sinalpha * tanbeta);
}

细节:

a. 

float sinthetai = SinTheta(wi);
float sinthetao = SinTheta(wo);

作用:

(先计算 sin θi 和 sin θo)

Application of trigonometry(三角函数) can substantially improve the efficiency of the evaluation
routine compared to a naive implementation. The implementation starts by computing
the values of sin θi and sin θo.

 

b. 

    float maxcos = 0.f;
    if (sinthetai > 1e-4 && sinthetao > 1e-4) {
        float sinphii = SinPhi(wi), cosphii = CosPhi(wi);
        float sinphio = SinPhi(wo), cosphio = CosPhi(wo);
        float dcos = cosphii * cosphio + sinphii * sinphio;
        maxcos = max(0.f, dcos);
    }

作用:

(利用三角函数公式,可以计算 cos(φi − φo))

It is now necessary to compute the max(0, cos(φi − φo)) term.We can apply the trigonometric
identity

such that we just need to compute the sines and cosines of φi and φo

 

c.

    float sinalpha, tanbeta;
    if (AbsCosTheta(wi) > AbsCosTheta(wo)) {
        sinalpha = sinthetao;
        tanbeta = sinthetai / AbsCosTheta(wi);
    }
    else {
        sinalpha = sinthetai;
        tanbeta = sinthetao / AbsCosTheta(wo);
    }

作用:

(计算 sin α 和 tan β,在计算这两个的时候,主要是要考虑比较大小)

Finally, the sin α and tan β terms are found. Note that whichever of ωi or ωo has a larger
value for cos θ (i.e., a larger z component) has a smaller value for θ. We can set sin α
using the appropriate sine value computed at the beginning of the method. The tangent
can then be computed using the identity tan a = sin a/ cos a.

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值