首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何计算多瓣BSDF的PDF

如何计算多瓣BSDF的PDF
EN

Computer Graphics用户
提问于 2019-11-13 16:08:05
回答 1查看 243关注 0票数 0

在PBRT中,BSDF表示为一个BxDF瓣数组。每个瓣都设置一个位标志,表示它是哪种类型的瓣。(镜面、漫射、反射、透射等)我正在研究PBRT是如何为输入方向采样BSDF的,wi。

按照标准的Monte抽样,我期望代码能够随机地采样一个适当的瓣,然后设置pdf = pdf_{picked}/n,其中n是适当类型的叶数。然而,这不是PBRT所做的。我的问题是为什么?为了进一步发展,这是PBRT函数:

代码语言:javascript
复制
Spectrum BSDF::Sample_f(const Vector3f &woWorld, Vector3f *wiWorld,
                        const Point2f &u, Float *pdf, BxDFType type,
                        BxDFType *sampledType) const {
    // Choose which _BxDF_ to sample
    int matchingComps = NumComponents(type);
    if (matchingComps == 0) {
        *pdf = 0;
        if (sampledType)
            *sampledType = BxDFType(0);
        return Spectrum(0);
    }
    int comp = std::min((int)std::floor(u[0] * matchingComps), matchingComps - 1);

    // Get _BxDF_ pointer for chosen component
    BxDF *bxdf = nullptr;
    int count = comp;
    for (int i = 0; i < nBxDFs; ++i)
        if (bxdfs[i]->MatchesFlags(type) && count-- == 0) {
            bxdf = bxdfs[i];
            break;
        }

    // Remap _BxDF_ sample _u_ to [0,1)^2#qcStackCode#
    Point2f uRemapped(std::min(u[0] * matchingComps - comp, OneMinusEpsilon),
                      u[1]);

    // Sample chosen _BxDF_
    Vector3f wi, wo = WorldToLocal(woWorld);
    if (wo.z == 0)
        return 0.;
    *pdf = 0;
    if (sampledType) *sampledType = bxdf->type;
    Spectrum f = bxdf->Sample_f(wo, &wi, uRemapped, pdf, sampledType);

    if (*pdf == 0) {
        if (sampledType) *sampledType = BxDFType(0);
        return 0;
    }
    *wiWorld = LocalToWorld(wi);

    // Compute overall PDF with all matching _BxDF_s
    if (!(bxdf->type & BSDF_SPECULAR) && matchingComps > 1)
        for (int i = 0; i < nBxDFs; ++i)
            if (bxdfs[i] != bxdf && bxdfs[i]->MatchesFlags(type))
                *pdf += bxdfs[i]->Pdf(wo, wi);
    if (matchingComps > 1)
        *pdf /= matchingComps;

    // Compute value of BSDF for sampled direction
    if (!(bxdf->type & BSDF_SPECULAR)) {
        bool reflect = Dot(*wiWorld, ng) * Dot(woWorld, ng) > 0;
        f = 0.;
        for (int i = 0; i < nBxDFs; ++i)
            if (bxdfs[i]->MatchesFlags(type) &&
                ((reflect && (bxdfs[i]->type & BSDF_REFLECTION)) ||
                 (!reflect && (bxdfs[i]->type & BSDF_TRANSMISSION))))
                f += bxdfs[i]->f(wo, wi);
    }

    return f;
}

在伪代码中,它看起来正在执行以下操作:

代码语言:javascript
复制
// Get the number of lobes that match the ones we asked for
numMatchingLobes = NumComponents(type);

// Early out check
if (numMatchingLobes == 0):
    return

// Randomly pick one of the matching lobes
pickedBxDF = Rand()

// Transform wo from world space to local space
// Then sample the chosen BxDF to get f, pdf, and wi
f, pdf, wi = pickedBxDF.sample_f(woWorld.ToLocal())

// Early out check
if (pdf == 0):
    return

// Transform wi to world space
wiWorld = wi.ToWorld()

// Add all of the pdfs of the matching lobes if the picked BxDF wasn't specular
if pickedBxDF.type not Specular && numMatchingLobes > 1:
    for BxDF in matchingLobes:
        pdf += BxDF.pdf(wi, wo)

// Divide the resulting pdf by the number of matching lobes
pdf /= numMatchingLobes;


// Calculate the combined f if the picked BxDF isn't specular
if pickedBxDF.type not Specular:
    // Reset f to zero
    f = 0

    // Add each BxDF's f, iff it matches reflection / transmission
    reflect = wo and wi on same hemisphere as geoNormal
    for BxDF in matchingLobes:
        // Add the 
        if reflect and BxDF.type == Reflection:
            f += BxDF.f(wo, wi)
        elif !reflect and BxDF.type == Transmission:
            f += BxDF.f(wo, wi)

我不理解的部分是,为什么它会在已经计算出来的pdf的基础上添加所有匹配的叶的pdf。这似乎会使摘取的叶的pdf数加倍。

例如,如果有两个匹配的叶,称为A和B。

我们用A计算f,pdf和wi,然后用一个for循环,我们把A和B的pdf相加,除以2。

\frac{A + A + B}{2}

这似乎不对。PBRT代码错误吗?它是否应该重置pdf,类似于下面的f计算代码?

EN

回答 1

Computer Graphics用户

回答已采纳

发布于 2019-11-13 21:20:43

求和不包括被挑选来取样的BxDF。再看看这一行:

代码语言:javascript
复制
if (bxdfs[i] != bxdf && bxdfs[i]->MatchesFlags(type))

在这里,bxdf是前面取样的那个,所以当它迭代到那个样本时,它会跳过它。

票数 1
EN
页面原文内容由Computer Graphics提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://computergraphics.stackexchange.com/questions/9343

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档