zoukankan      html  css  js  c++  java
  • PBRT笔记(8)——材质

    BSDF类

    表面着色器会绑定场景中每一个图元(被赋予了这个着色器),而表面着色器则由Material类的实例来表示。它会拥有一个BSDF类对象(可能是BSSDF),用于计算表面上每一点的辐射度(颜色)。

    BSDF代表了BRDFs与BTDFs的集合。BSDF构造函数接受一个SurfaceInteraction对象,该对象包含关于表面上任意一点的微分几何信息,以及一个参数eta,该参数给出了边界上的相对折射率。对于不透明的表面,该参数则无效。构造函数将使用着色法线来构造一个正交坐标系。本节中ns表示着色法线(法线贴图上对应坐标的值)和ng代表了几何法线(面法线)。

    BSDF存储了最多8个BxDF组件,因为在pbrt中不需要更多组件。BSDF实现了BxDFs坐标系与世界坐标系转换的方法。WorldToLocal(const Vector3f &v)与LocalToWorld(const Vector3f &v)。

    着色法线与几何法线的冲突问题

    实际渲染的过程中着色法线可能会发生如图9.2这样的漏光现象情况,也就是说直接计算出得到错误的光线遮挡关系。解决方法是:使用几何法线来决定是计算反射还是计算透射,如果ωi与ωo在同一个几何法线的半球,计算BRDFs,不然则计算BTDFs。与上一步不同,在计算散射方程时,法线和入射方向的点积仍然是用着色法线而不是几何法线来处理的。

    首先将向量从世界坐标系转换为BSDF坐标系,然后决定是使用BRDFs还是BTDFs。然后循环遍历适当的集合并计算它们的辐射度贡献之和。

    Spectrum BSDF::f(const Vector3f &woW, const Vector3f &wiW,
                     BxDFType flags) const {
        ProfilePhase pp(Prof::BSDFEvaluation);
        Vector3f wi = WorldToLocal(wiW), wo = WorldToLocal(woW);
        if (wo.z == 0) return 0.;
        bool reflect = Dot(wiW, ng) * Dot(woW, ng) > 0;
        Spectrum f(0.f);
        for (int i = 0; i < nBxDFs; ++i)
            if (bxdfs[i]->MatchesFlags(flags) &&
                ((reflect && (bxdfs[i]->type & BSDF_REFLECTION)) ||
                 (!reflect && (bxdfs[i]->type & BSDF_TRANSMISSION))))
                f += bxdfs[i]->f(wo, wi);
        return f;
    }
    

    Material类

    Material的派生类必须实现ComputeScatteringFunctions();该函数获取一个SurfaceInteraction对象,该方法用于确定反射属性,并且初始化相应的SurfaceInteraction::BSDF,如果包含了次表面散射,那SurfaceInteraction::BSSRDF也会被初始化。另外几个形参别分是:所使用的内存池引用,透射模式,是否使用多层复合材质的BxDFs(类似车漆这种),之后SurfaceInteraction的实例会调用这个函数进行渲染。

    void SurfaceInteraction::ComputeScatteringFunctions(const RayDifferential &ray,MemoryArena &arena,bool allowMultipleLobes,TransportMode mode) {
        ComputeDifferentials(ray);
        primitive->ComputeScatteringFunctions(this, arena, mode,
                                              allowMultipleLobes);
    }
    

    金属材质

    kd为漫反射值,sigma为粗糙度值。如果sigma为0,即为兰伯特材质,不然就使用OrenNayar模型,另外还有一个凹凸贴图指针变量,在其有效的情况下,用与着色法线的计算。

    void MatteMaterial::ComputeScatteringFunctions(SurfaceInteraction *si,MemoryArena &arena,TransportMode mode,bool allowMultipleLobes) const {
        if (bumpMap) Bump(bumpMap, si);
        
        si->bsdf = ARENA_ALLOC(arena, BSDF)(*si);
        Spectrum r = Kd->Evaluate(*si).Clamp();
        Float sig = Clamp(sigma->Evaluate(*si), 0, 90);
        if (!r.IsBlack()) {
            if (sig == 0)
                si->bsdf->Add(ARENA_ALLOC(arena, LambertianReflection)(r));
            else
                si->bsdf->Add(ARENA_ALLOC(arena, OrenNayar)(r, sig));
        }
    }
    

    塑料材质

    塑料可以被建模为漫反射和光泽散射函数的混合物,参数控制特定的颜色和高光尺寸。塑料材质的参数为Kd和Ks,分别控制漫反射和高光的量。

    reaproughness为控制粗糙度效果的变量,如果remapRoughness参数为true,那么roughness将会映射到0~1范围,其中粗糙度值越高,高光亮点越大。如果为false,那么粗糙度直接初始化microfacet分布的参数α(8.4.2的内容)

    void PlasticMaterial::ComputeScatteringFunctions(
        SurfaceInteraction *si, MemoryArena &arena, TransportMode mode,
        bool allowMultipleLobes) const {
        // Perform bump mapping with _bumpMap_, if present
        if (bumpMap) Bump(bumpMap, si);
        si->bsdf = ARENA_ALLOC(arena, BSDF)(*si);
        // Initialize diffuse component of plastic material
        Spectrum kd = Kd->Evaluate(*si).Clamp();
        if (!kd.IsBlack())
            si->bsdf->Add(ARENA_ALLOC(arena, LambertianReflection)(kd));
    
        // Initialize specular component of plastic material
        Spectrum ks = Ks->Evaluate(*si).Clamp();
        if (!ks.IsBlack()) {
            Fresnel *fresnel = ARENA_ALLOC(arena, FresnelDielectric)(1.5f, 1.f);
            // Create microfacet distribution _distrib_ for plastic material
            Float rough = roughness->Evaluate(*si);
            if (remapRoughness)
                rough = TrowbridgeReitzDistribution::RoughnessToAlpha(rough);
            MicrofacetDistribution *distrib =
                ARENA_ALLOC(arena, TrowbridgeReitzDistribution)(rough, rough);
            BxDF *spec =
                ARENA_ALLOC(arena, MicrofacetReflection)(ks, distrib, fresnel);
            si->bsdf->Add(spec);
        }
    }
    

    混和材质

    存储了2个材质的指针,以及一个缩放参数。

    void MixMaterial::ComputeScatteringFunctions(SurfaceInteraction *si,MemoryArena &arena,TransportMode mode,bool allowMultipleLobes) const {
        // Compute weights and original _BxDF_s for mix material
        Spectrum s1 = scale->Evaluate(*si).Clamp();
        Spectrum s2 = (Spectrum(1.f) - s1).Clamp();
        SurfaceInteraction si2 = *si;
        m1->ComputeScatteringFunctions(si, arena, mode, allowMultipleLobes);
        m2->ComputeScatteringFunctions(&si2, arena, mode, allowMultipleLobes);
    
        // Initialize _si->bsdf_ with weighted mixture of _BxDF_s
        int n1 = si->bsdf->NumComponents(), n2 = si2.bsdf->NumComponents();
        for (int i = 0; i < n1; ++i)
            si->bsdf->bxdfs[i] =
                ARENA_ALLOC(arena, ScaledBxDF)(si->bsdf->bxdfs[i], s1);
        for (int i = 0; i < n2; ++i)
            si->bsdf->Add(ARENA_ALLOC(arena, ScaledBxDF)(si2.bsdf->bxdfs[i], s2));
    }
    

    除此之外的材质

    PBRT还实现了一些别的材质,其实现代码都在materials目录中。

    1. GlassMaterial
    2. MetalMaterial
    3. MirrorMaterial
    4. SubsurfaceMaterial
    5. TranslucentMaterial
    6. UberMaterial
  • 相关阅读:
    脱发
    jquery radio 选择值
    今天看了非诚勿扰记忆哥,觉得人和人还是差的是能力
    如果要在数组中删除东西还是用倒序的数是正确的
    jquery操作 xml
    偶然在一个帖子上看到的
    jquery 队列的应用
    阅读
    Request的getParameter和getAttribute方法的区别
    jsp与jspx文件
  • 原文地址:https://www.cnblogs.com/blueroses/p/10563182.html
Copyright © 2011-2022 走看看