예제 #1
0
파일: uber.cpp 프로젝트: NickYang/pbrt-v3
// UberMaterial Method Definitions
void UberMaterial::ComputeScatteringFunctions(SurfaceInteraction *si,
                                              MemoryArena &arena,
                                              TransportMode mode,
                                              bool allowMultipleLobes) const {
    // Perform bump mapping with _bumpMap_, if present
    if (bumpMap) Bump(bumpMap, si);
    Float e = eta->Evaluate(*si);

    Spectrum op = opacity->Evaluate(*si).Clamp();
    if (op != Spectrum(1.f)) {
        si->bsdf = ARENA_ALLOC(arena, BSDF)(*si, 1.f);
        BxDF *tr = ARENA_ALLOC(arena, SpecularTransmission)(-op + Spectrum(1.f),
                                                            1.f, 1.f, mode);
        si->bsdf->Add(tr);
    } else
        si->bsdf = ARENA_ALLOC(arena, BSDF)(*si, e);

    Spectrum kd = op * Kd->Evaluate(*si).Clamp();
    if (!kd.IsBlack()) {
        BxDF *diff = ARENA_ALLOC(arena, LambertianReflection)(kd);
        si->bsdf->Add(diff);
    }

    Spectrum ks = op * Ks->Evaluate(*si).Clamp();
    if (!ks.IsBlack()) {
        Fresnel *fresnel = ARENA_ALLOC(arena, FresnelDielectric)(1.f, e);
        Float roughu, roughv;
        if (roughnessu)
            roughu = roughnessu->Evaluate(*si);
        else
            roughu = roughness->Evaluate(*si);
        if (roughnessv)
            roughv = roughnessv->Evaluate(*si);
        else
            roughv = roughu;
        if (remapRoughness) {
            roughu = TrowbridgeReitzDistribution::RoughnessToAlpha(roughu);
            roughv = TrowbridgeReitzDistribution::RoughnessToAlpha(roughv);
        }
        MicrofacetDistribution *distrib =
            ARENA_ALLOC(arena, TrowbridgeReitzDistribution)(roughu, roughv);
        BxDF *spec =
            ARENA_ALLOC(arena, MicrofacetReflection)(ks, distrib, fresnel);
        si->bsdf->Add(spec);
    }

    Spectrum kr = op * Kr->Evaluate(*si).Clamp();
    if (!kr.IsBlack()) {
        Fresnel *fresnel = ARENA_ALLOC(arena, FresnelDielectric)(1.f, e);
        si->bsdf->Add(ARENA_ALLOC(arena, SpecularReflection)(kr, fresnel));
    }

    Spectrum kt = op * Kt->Evaluate(*si).Clamp();
    if (!kt.IsBlack())
        si->bsdf->Add(
            ARENA_ALLOC(arena, SpecularTransmission)(kt, 1.f, e, mode));
}
예제 #2
0
파일: fourier.cpp 프로젝트: DINKIN/pbrt-v3
void FourierMaterial::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);
    // Checking for zero channels works as a proxy for checking whether the
    // table was successfully read from the file.
    if (bsdfTable.nChannels > 0)
        si->bsdf->Add(ARENA_ALLOC(arena, FourierBSDF)(bsdfTable, mode));
}
예제 #3
0
Spectrum SeparableBSSRDF::Sample_S(const Scene &scene, Float u1,
                                   const Point2f &u2, MemoryArena &arena,
                                   SurfaceInteraction *si, Float *pdf) const {
    ProfilePhase pp(Prof::BSSRDFEvaluation);
    Spectrum Sp = Sample_Sp(scene, u1, u2, arena, si, pdf);
    if (!Sp.IsBlack()) {
        // Initialize material model at sampled surface interaction
        si->bsdf = ARENA_ALLOC(arena, BSDF)(*si);
        si->bsdf->Add(ARENA_ALLOC(arena, SeparableBSSRDFAdapter)(this));
        si->wo = Vector3f(si->shading.n);
    }
    return Sp;
}
예제 #4
0
// KdSubsurfaceMaterial Method Definitions
void KdSubsurfaceMaterial::ComputeScatteringFunctions(
    SurfaceInteraction *si, MemoryArena &arena, TransportMode mode,
    bool allowMultipleLobes) const {
    // Perform bump mapping with _bumpMap_, if present
    if (bumpMap) Bump(bumpMap, si);
    Spectrum R = Kr->Evaluate(*si).Clamp();
    Spectrum T = Kt->Evaluate(*si).Clamp();
    Float urough = uRoughness->Evaluate(*si);
    Float vrough = vRoughness->Evaluate(*si);

    // Initialize _bsdf_ for smooth or rough dielectric
    si->bsdf = ARENA_ALLOC(arena, BSDF)(*si, eta);

    if (R.IsBlack() && T.IsBlack()) return;

    bool isSpecular = urough == 0 && vrough == 0;
    if (isSpecular && allowMultipleLobes) {
        si->bsdf->Add(
            ARENA_ALLOC(arena, FresnelSpecular)(R, T, 1.f, eta, mode));
    } else {
        if (remapRoughness) {
            urough = TrowbridgeReitzDistribution::RoughnessToAlpha(urough);
            vrough = TrowbridgeReitzDistribution::RoughnessToAlpha(vrough);
        }
        MicrofacetDistribution *distrib =
            isSpecular ? nullptr
            : ARENA_ALLOC(arena, TrowbridgeReitzDistribution)(
                urough, vrough);
        if (!R.IsBlack()) {
            Fresnel *fresnel = ARENA_ALLOC(arena, FresnelDielectric)(1.f, eta);
            if (isSpecular)
                si->bsdf->Add(
                    ARENA_ALLOC(arena, SpecularReflection)(R, fresnel));
            else
                si->bsdf->Add(ARENA_ALLOC(arena, MicrofacetReflection)(
                                  R, distrib, fresnel));
        }
        if (!T.IsBlack()) {
            if (isSpecular)
                si->bsdf->Add(ARENA_ALLOC(arena, SpecularTransmission)(
                                  T, 1.f, eta, mode));
            else
                si->bsdf->Add(ARENA_ALLOC(arena, MicrofacetTransmission)(
                                  T, distrib, 1.f, eta, mode));
        }
    }

    Spectrum mfree = scale * mfp->Evaluate(*si).Clamp();
    Spectrum kd = Kd->Evaluate(*si).Clamp();
    Spectrum sig_a, sig_s;
    SubsurfaceFromDiffuse(table, kd, Spectrum(1.f) / mfree, &sig_a, &sig_s);
    si->bssrdf = ARENA_ALLOC(arena, TabulatedBSSRDF)(*si, this, mode, eta,
                 sig_a, sig_s, table);
}
예제 #5
0
Spectrum GridDensityMedium::Sample(const Ray &rWorld, Sampler &sampler,
                                   MemoryArena &arena,
                                   MediumInteraction *mi) const {
    Ray ray = WorldToMedium(
        Ray(rWorld.o, Normalize(rWorld.d), rWorld.tMax * rWorld.d.Length()));
    // Compute $[\tmin, \tmax]$ interval of _ray_'s overlap with medium bounds
    const Bounds3f b(Point3f(0, 0, 0), Point3f(1, 1, 1));
    Float tMin, tMax;
    if (!b.IntersectP(ray, &tMin, &tMax)) return Spectrum(1.f);

    // Run delta-tracking iterations to sample a medium interaction
    Float t = tMin;
    while (true) {
        t -= std::log(1 - sampler.Get1D()) * invMaxDensity;
        if (t >= tMax) break;
        if (Density(ray(t)) * invMaxDensity * sigma_t > sampler.Get1D()) {
            // Populate _mi_ with medium interaction information and return
            PhaseFunction *phase = ARENA_ALLOC(arena, HenyeyGreenstein)(g);
            *mi = MediumInteraction(rWorld(t), -rWorld.d, rWorld.time, this,
                                    phase);
            return sigma_s / sigma_t;
        }
    }
    return Spectrum(1.f);
}
예제 #6
0
Spectrum GridDensityMedium::Sample(const Ray &_ray, Sampler &sampler,
                                   MemoryArena &arena,
                                   MediumInteraction *mi) const {
    // Transform the ray into local coordinates and determine overlap interval
    // [_tMin, tMax_]
    const Bounds3f dataBounds(Point3f(0.f, 0.f, 0.f), Point3f(1.f, 1.f, 1.f));
    Ray ray = WorldToMedium(
        Ray(_ray.o, Normalize(_ray.d), _ray.tMax * _ray.d.Length()));
    Float tMin, tMax;
    if (!dataBounds.IntersectP(ray, &tMin, &tMax)) return Spectrum(1.f);
    tMin = std::max(tMin, (Float)0.f);
    tMax = std::min(tMax, ray.tMax);
    if (tMin >= tMax) return Spectrum(1.f);

    // Run Delta-Tracking iterations to sample a medium interaction
    Float t = tMin;
    while (true) {
        t -= std::log(1 - sampler.Get1D()) * invMaxDensity;
        if (t >= tMax) break;
        Float density = Density(ray(t));
        if (density * invMaxDensity * sigma_t > sampler.Get1D()) {
            // Populate _mi_ with medium interaction information and return
            PhaseFunction *phase = ARENA_ALLOC(arena, HenyeyGreenstein)(g);
            *mi = MediumInteraction(_ray(t), -_ray.d, _ray.time, this, phase);
            return sigma_s / sigma_t;
        }
    }
    return Spectrum(1.0f);
}
예제 #7
0
파일: clx.c 프로젝트: mycoboco/beluga
/*
 *  initializes a keyword-code table
 */
void (clx_init)(void)
{
    static struct {
        const char *name;
        int code;
    } map[] = {
#define xx(a, b, c, d, e, f, g, h)
#define kk(a, b, c, d, e, f, g, h) g, LEX_##a,
#define yy(a, b, c, d, e, f, g, h)
#include "xtoken.h"
    };

    int i;
    unsigned h;
    struct tab *p;

    for (i = 0; i < NELEM(map); i++) {
        map[i].name = hash_string(map[i].name);
        h = hashkey(map[i].name, NELEM(tab));
        p = ARENA_ALLOC(strg_perm, sizeof(*p));
        p->key = map[i].name;
        p->code = map[i].code;
        p->link = tab[h];
        tab[h] = p;
    }

    proc_prep();
}
예제 #8
0
void createMicrofacet30and0(BSDF* bsdf, bool beckmann) {
    Spectrum Ks(0.5);
    MicrofacetDistribution *distrib1, *distrib2;
    if (beckmann) {
      Float alphax = BeckmannDistribution::RoughnessToAlpha(0.8);
      Float alphay = BeckmannDistribution::RoughnessToAlpha(0.8);
      distrib1 = ARENA_ALLOC(arena, BeckmannDistribution)(alphax, alphay);

      alphax = BeckmannDistribution::RoughnessToAlpha(0.01);
      alphay = BeckmannDistribution::RoughnessToAlpha(0.01);
      distrib2 = ARENA_ALLOC(arena, BeckmannDistribution)(alphax, alphay);
    }
    else {
      Float alphax = TrowbridgeReitzDistribution::RoughnessToAlpha(0.8);
      Float alphay = TrowbridgeReitzDistribution::RoughnessToAlpha(0.8);
      distrib1 = ARENA_ALLOC(arena, TrowbridgeReitzDistribution)(alphax, alphay);

      alphax = TrowbridgeReitzDistribution::RoughnessToAlpha(0.01);
      alphay = TrowbridgeReitzDistribution::RoughnessToAlpha(0.01);
      distrib2 = ARENA_ALLOC(arena, TrowbridgeReitzDistribution)(alphax, alphay);
    }

    Fresnel* fresnel = ARENA_ALLOC(arena, FresnelNoOp)();
    BxDF* bxdf1 =
        ARENA_ALLOC(arena, MicrofacetReflection)(Ks, distrib1, fresnel);
    bsdf->Add(bxdf1);
    BxDF* bxdf2 =
        ARENA_ALLOC(arena, MicrofacetReflection)(Ks, distrib2, fresnel);
    bsdf->Add(bxdf2);
}
예제 #9
0
파일: bsdfs.cpp 프로젝트: Drooids/pbrt-v3
void createMicrofacet(BSDF* bsdf, MemoryArena& arena, bool beckmann,
                      bool samplevisible, float roughx, float roughy) {
    Spectrum Ks(1);
    MicrofacetDistribution* distrib;
    if (beckmann) {
        Float alphax = BeckmannDistribution::RoughnessToAlpha(roughx);
        Float alphay = BeckmannDistribution::RoughnessToAlpha(roughy);
        distrib = ARENA_ALLOC(arena, BeckmannDistribution)(alphax, alphay,
                                                           samplevisible);
    } else {
        Float alphax = TrowbridgeReitzDistribution::RoughnessToAlpha(roughx);
        Float alphay = TrowbridgeReitzDistribution::RoughnessToAlpha(roughy);
        distrib = ARENA_ALLOC(arena, TrowbridgeReitzDistribution)(
            alphax, alphay, samplevisible);
    }
    Fresnel* fresnel = ARENA_ALLOC(arena, FresnelNoOp)();
    BxDF* bxdf = ARENA_ALLOC(arena, MicrofacetReflection)(Ks, distrib, fresnel);
    bsdf->Add(bxdf);
}
예제 #10
0
파일: bsdfs.cpp 프로젝트: Drooids/pbrt-v3
void createFresnelBlend(BSDF* bsdf, MemoryArena& arena, bool beckmann,
                        bool samplevisible, float roughx, float roughy) {
    Spectrum d(0.5);
    Spectrum s(0.5);
    MicrofacetDistribution* distrib;
    if (beckmann) {
        Float alphax = BeckmannDistribution::RoughnessToAlpha(roughx);
        Float alphay = BeckmannDistribution::RoughnessToAlpha(roughy);
        distrib = ARENA_ALLOC(arena, BeckmannDistribution)(alphax, alphay,
                                                           samplevisible);
    } else {
        Float alphax = TrowbridgeReitzDistribution::RoughnessToAlpha(roughx);
        Float alphay = TrowbridgeReitzDistribution::RoughnessToAlpha(roughy);
        distrib = ARENA_ALLOC(arena, TrowbridgeReitzDistribution)(
            alphax, alphay, samplevisible);
    }
    BxDF* bxdf = ARENA_ALLOC(arena, FresnelBlend)(d, s, distrib);
    bsdf->Add(bxdf);
}
예제 #11
0
// KdSubsurfaceMaterial Method Definitions
void KdSubsurfaceMaterial::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, eta);
    Spectrum R = Kr->Evaluate(*si).Clamp();
    Spectrum T = Kt->Evaluate(*si).Clamp();

    if (allowMultipleLobes && (!R.IsBlack() || !T.IsBlack()))
        si->bsdf->Add(
            ARENA_ALLOC(arena, FresnelSpecular)(1., 1., 1.f, eta, mode));
    else {
        if (!R.IsBlack())
            si->bsdf->Add(ARENA_ALLOC(arena, SpecularReflection)(
                R, ARENA_ALLOC(arena, FresnelDielectric)(1.f, eta)));
        if (!T.IsBlack())
            si->bsdf->Add(
                ARENA_ALLOC(arena, SpecularTransmission)(T, 1.f, eta, mode));
    }

    Spectrum sig_t = scale * sigma_t->Evaluate(*si).Clamp();
    Spectrum kd = Kd->Evaluate(*si).Clamp();
    Spectrum sig_a, sig_s;
    SubsurfaceFromDiffuse(table, kd, sig_t, &sig_a, &sig_s);
    si->bssrdf = ARENA_ALLOC(arena, TabulatedBSSRDF)(*si, this, mode, eta,
                                                     sig_a, sig_s, table);
}
예제 #12
0
void MetalMaterial::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);

    Float uRough =
        uRoughness ? uRoughness->Evaluate(*si) : roughness->Evaluate(*si);
    Float vRough =
        vRoughness ? vRoughness->Evaluate(*si) : roughness->Evaluate(*si);
    if (remapRoughness) {
        uRough = TrowbridgeReitzDistribution::RoughnessToAlpha(uRough);
        vRough = TrowbridgeReitzDistribution::RoughnessToAlpha(vRough);
    }
    Fresnel *frMf = ARENA_ALLOC(arena, FresnelConductor)(1., eta->Evaluate(*si),
                    k->Evaluate(*si));
    MicrofacetDistribution *distrib =
        ARENA_ALLOC(arena, TrowbridgeReitzDistribution)(uRough, vRough);
    si->bsdf->Add(ARENA_ALLOC(arena, MicrofacetReflection)(1., distrib, frMf));
}
예제 #13
0
// GlassMaterial Method Definitions
void GlassMaterial::ComputeScatteringFunctions(SurfaceInteraction *si,
                                               MemoryArena &arena,
                                               TransportMode mode,
                                               bool allowMultipleLobes) const {
    // Perform bump mapping with _bumpMap_, if present
    if (bumpMap) Bump(bumpMap, si);
    Float eta = index->Evaluate(*si);
    si->bsdf = ARENA_ALLOC(arena, BSDF)(*si, eta);

    Spectrum R = Kr->Evaluate(*si).Clamp();
    Spectrum T = Kt->Evaluate(*si).Clamp();
    if (R.IsBlack() && T.IsBlack()) return;

    Float urough = uRoughness->Evaluate(*si);
    Float vrough = vRoughness->Evaluate(*si);
    bool isSpecular = urough == 0 && vrough == 0;
    if (isSpecular && allowMultipleLobes) {
        si->bsdf->Add(
            ARENA_ALLOC(arena, FresnelSpecular)(R, T, 1.f, eta, mode));
    } else {
        if (remapRoughness) {
            urough = TrowbridgeReitzDistribution::RoughnessToAlpha(urough);
            vrough = TrowbridgeReitzDistribution::RoughnessToAlpha(vrough);
        }
        MicrofacetDistribution *distrib =
            isSpecular ? nullptr
                       : ARENA_ALLOC(arena, TrowbridgeReitzDistribution)(
                             urough, vrough);
        if (!R.IsBlack()) {
            Fresnel *fresnel = ARENA_ALLOC(arena, FresnelDielectric)(1.f, eta);
            if (isSpecular)
                si->bsdf->Add(
                    ARENA_ALLOC(arena, SpecularReflection)(R, fresnel));
            else
                si->bsdf->Add(ARENA_ALLOC(arena, MicrofacetReflection)(
                    R, distrib, fresnel));
        }
        if (!T.IsBlack()) {
            if (isSpecular)
                si->bsdf->Add(ARENA_ALLOC(arena, SpecularTransmission)(
                    T, 1.f, eta, mode));
            else
                si->bsdf->Add(ARENA_ALLOC(arena, MicrofacetTransmission)(
                    T, distrib, 1.f, eta, mode));
        }
    }
}
예제 #14
0
파일: proc.c 프로젝트: mycoboco/beluga
/*
 *  recognizes a string literal including escape sequence
 */
static const char *recstr(lex_t *t)
{
    char *p, *r;
    const char *ss, *s;

    assert(t);

    ss = s = LEX_SPELL(t);
    if (!strchr(s, '\\'))
        return s;

    p = r = ARENA_ALLOC(strg_perm, strlen(s)+1);    /* file names go into strg_perm */
    while (*s) {
        *p = (*s == '\\')? xnu(lex_bs(t, ss, &s, xiu(UCHAR_MAX), "file name")): *s++;
        p++;
    }

    return r;
}
예제 #15
0
파일: mg.c 프로젝트: mycoboco/beluga
/*
 *  remembers a macro guard
 */
void (mg_once)(void)
{
    unsigned h;
    struct mgt *p;
    const lmap_t *pos = lmap_pfrom(lmap_from);

    assert(pos->type <= LMAP_INC);
    h = hashkey(pos->u.i.rf, NELEM(mgt));
    for (p = mgt[h]; p; p = p->link)
        if (p->path == pos->u.i.rf) {
            if (p->name)    /* #pragma once always wins */
                p->name = mg_name;
            return;
        }

    p = ARENA_ALLOC(strg_perm, sizeof(*p));
    p->path = pos->u.i.rf;
    p->name = mg_name;
    p->link = mgt[h];
    mgt[h] = p;
}
예제 #16
0
// TranslucentMaterial Method Definitions
void TranslucentMaterial::ComputeScatteringFunctions(
    SurfaceInteraction *si, MemoryArena &arena, TransportMode mode,
    bool allowMultipleLobes) const {
    // Perform bump mapping with _bumpMap_, if present
    if (bumpMap) Bump(bumpMap, si);
    Float eta = 1.5f;
    si->bsdf = ARENA_ALLOC(arena, BSDF)(*si, eta);

    Spectrum r = reflect->Evaluate(*si).Clamp();
    Spectrum t = transmit->Evaluate(*si).Clamp();
    if (r.IsBlack() && t.IsBlack()) return;

    Spectrum kd = Kd->Evaluate(*si).Clamp();
    if (!kd.IsBlack()) {
        if (!r.IsBlack())
            si->bsdf->Add(ARENA_ALLOC(arena, LambertianReflection)(r * kd));
        if (!t.IsBlack())
            si->bsdf->Add(ARENA_ALLOC(arena, LambertianTransmission)(t * kd));
    }
    Spectrum ks = Ks->Evaluate(*si).Clamp();
    if (!ks.IsBlack() && (!r.IsBlack() || !t.IsBlack())) {
        Float rough = roughness->Evaluate(*si);
        if (remapRoughness)
            rough = TrowbridgeReitzDistribution::RoughnessToAlpha(rough);
        MicrofacetDistribution *distrib =
            ARENA_ALLOC(arena, TrowbridgeReitzDistribution)(rough, rough);
        if (!r.IsBlack()) {
            Fresnel *fresnel = ARENA_ALLOC(arena, FresnelDielectric)(1.f, eta);
            si->bsdf->Add(ARENA_ALLOC(arena, MicrofacetReflection)(
                r * ks, distrib, fresnel));
        }
        if (!t.IsBlack())
            si->bsdf->Add(ARENA_ALLOC(arena, MicrofacetTransmission)(
                t * ks, distrib, 1.f, eta, mode));
    }
}
예제 #17
0
Spectrum SeparableBSSRDF::Sample_Sp(const Scene &scene, Float u1,
                                    const Point2f &u2, MemoryArena &arena,
                                    SurfaceInteraction *pi, Float *pdf) const {
    ProfilePhase pp(Prof::BSSRDFEvaluation);
    // Choose projection axis for BSSRDF sampling
    Vector3f vx, vy, vz;
    if (u1 < .5f) {
        vx = ss;
        vy = ts;
        vz = Vector3f(ns);
        u1 *= 2;
    } else if (u1 < .75f) {
        // Prepare for sampling rays with respect to _ss_
        vx = ts;
        vy = Vector3f(ns);
        vz = ss;
        u1 = (u1 - .5f) * 4;
    } else {
        // Prepare for sampling rays with respect to _ts_
        vx = Vector3f(ns);
        vy = ss;
        vz = ts;
        u1 = (u1 - .75f) * 4;
    }

    // Choose spectral channel for BSSRDF sampling
    int ch = Clamp((int)(u1 * Spectrum::nSamples), 0, Spectrum::nSamples - 1);
    u1 = u1 * Spectrum::nSamples - ch;

    // Sample BSSRDF profile in polar coordinates
    Float r = Sample_Sr(ch, u2[0]);
    if (r < 0) return Spectrum(0.f);
    Float phi = 2 * Pi * u2[1];

    // Compute BSSRDF profile bounds and intersection height
    Float rMax = Sample_Sr(ch, 0.999f);
    if (r > rMax) return Spectrum(0.f);
    Float l = 2 * std::sqrt(rMax * rMax - r * r);

    // Compute BSSRDF sampling ray segment
    Interaction base;
    base.p =
        po.p + r * (vx * std::cos(phi) + vy * std::sin(phi)) - l * vz * 0.5f;
    base.time = po.time;
    Point3f pTarget = base.p + l * vz;

    // Intersect BSSRDF sampling ray against the scene geometry

    // Declare _IntersectionChain_ and linked list
    struct IntersectionChain {
        SurfaceInteraction si;
        IntersectionChain *next = nullptr;
    };
    IntersectionChain *chain = ARENA_ALLOC(arena, IntersectionChain)();

    // Accumulate chain of intersections along ray
    IntersectionChain *ptr = chain;
    int nFound = 0;
    while (scene.Intersect(base.SpawnRayTo(pTarget), &ptr->si)) {
        base = ptr->si;
        // Append admissible intersection to _IntersectionChain_
        if (ptr->si.primitive->GetMaterial() == this->material) {
            IntersectionChain *next = ARENA_ALLOC(arena, IntersectionChain)();
            ptr->next = next;
            ptr = next;
            nFound++;
        }
    }

    // Randomly choose one of several intersections during BSSRDF sampling
    if (nFound == 0) return Spectrum(0.0f);
    int selected = Clamp((int)(u1 * nFound), 0, nFound - 1);
    while (selected-- > 0) chain = chain->next;
    *pi = chain->si;

    // Compute sample PDF and return the spatial BSSRDF term $\Sp$
    *pdf = this->Pdf_Sp(*pi) / nFound;
    return this->Sp(*pi);
}
예제 #18
0
void createOrenNayar20(BSDF* bsdf) {
    Spectrum Kd(1);
    float sigma = 20.0;
    BxDF* bxdf = ARENA_ALLOC(arena, OrenNayar)(Kd, sigma);
    bsdf->Add(bxdf);
}
예제 #19
0
파일: bsdfs.cpp 프로젝트: Drooids/pbrt-v3
void TestBSDF(void (*createBSDF)(BSDF*, MemoryArena&),
              const char* description) {
    MemoryArena arena;

    Options opt;
    pbrtInit(opt);

    const int thetaRes = CHI2_THETA_RES;
    const int phiRes = CHI2_PHI_RES;
    const int sampleCount = CHI2_SAMPLECOUNT;
    Float* frequencies = new Float[thetaRes * phiRes];
    Float* expFrequencies = new Float[thetaRes * phiRes];
    RNG rng;

    int index = 0;
    std::cout.precision(3);

    // Create BSDF, which requires creating a Shape, casting a Ray that
    // hits the shape to get a SurfaceInteraction object.
    BSDF* bsdf = nullptr;
    Transform t = RotateX(-90);
    Transform tInv = Inverse(t);
    {
        bool reverseOrientation = false;
        ParamSet p;

        std::shared_ptr<Shape> disk(
            new Disk(&t, &tInv, reverseOrientation, 0., 1., 0, 360.));
        Point3f origin(0.1, 1,
                       0);  // offset slightly so we don't hit center of disk
        Vector3f direction(0, -1, 0);
        Float tHit;
        Ray r(origin, direction);
        SurfaceInteraction isect;
        disk->Intersect(r, &tHit, &isect);
        bsdf = ARENA_ALLOC(arena, BSDF)(isect);
        createBSDF(bsdf, arena);
    }

    for (int k = 0; k < CHI2_RUNS; ++k) {
        /* Randomly pick an outgoing direction on the hemisphere */
        Point2f sample {rng.UniformFloat(), rng.UniformFloat()};
        Vector3f woL = CosineSampleHemisphere(sample);
        Vector3f wo = bsdf->LocalToWorld(woL);

        FrequencyTable(bsdf, wo, rng, sampleCount, thetaRes, phiRes,
                       frequencies);

        IntegrateFrequencyTable(bsdf, wo, sampleCount, thetaRes, phiRes,
                                expFrequencies);

        std::string filename = StringPrintf("/tmp/chi2test_%s_%03i.m",
                                            description, ++index);
        DumpTables(frequencies, expFrequencies, thetaRes, phiRes,
                   filename.c_str());

        auto result =
            Chi2Test(frequencies, expFrequencies, thetaRes, phiRes, sampleCount,
                     CHI2_MINFREQ, CHI2_SLEVEL, CHI2_RUNS);
        EXPECT_TRUE(result.first) << result.second << ", iteration " << k;
    }

    delete[] frequencies;
    delete[] expFrequencies;

    pbrtCleanup();
}
예제 #20
0
파일: bsdfs.cpp 프로젝트: Drooids/pbrt-v3
void createLambertian(BSDF* bsdf, MemoryArena& arena) {
    Spectrum Kd(1);
    bsdf->Add(ARENA_ALLOC(arena, LambertianReflection)(Kd));
}
예제 #21
0
int main(int argc, char* argv[]) {
    Options opt;
    pbrtInit(opt);

    // number of monte carlo estimates
    // const int estimates = 1;
    const int estimates = 10000000;

    // radiance of uniform environment map
    const double environmentRadiance = 1.0;

    fprintf(stderr,
            "outgoing radiance from a surface viewed\n"
            "straight on with uniform lighting\n\n"
            "    uniform incoming radiance = %.3f\n"
            "    monte carlo samples = %d\n\n\n",
            environmentRadiance, estimates);

    CreateBSDFFunc BSDFFuncArray[] = {
        createLambertian,
        createOrenNayar0,
        createOrenNayar20,
        [](BSDF* bsdf) -> void
        { createMicrofacet(bsdf, true, true, 0.5, 0.5); },
        [](BSDF* bsdf) -> void
        { createMicrofacet(bsdf, false, true, 0.5, 0.5); },
        [](BSDF* bsdf) -> void
        { createMicrofacet(bsdf, true, true, 0.2, 0.1); },
        [](BSDF* bsdf) -> void
        { createMicrofacet(bsdf, false, true, 0.2, 0.1); },
        [](BSDF* bsdf) -> void
        { createMicrofacet(bsdf, true, true, 0.15, 0.25); },
        [](BSDF* bsdf) -> void
        { createMicrofacet(bsdf, false, true, 0.15, 0.25); },
        [](BSDF* bsdf) -> void
        { createMicrofacet(bsdf, true, true, 0.33, 0.033); },
        [](BSDF* bsdf) -> void
        { createMicrofacet(bsdf, false, true, 0.33, 0.033); },
        [](BSDF* bsdf) -> void
        { createMicrofacet(bsdf, true, false, 0.5, 0.5); },
        [](BSDF* bsdf) -> void
        { createMicrofacet(bsdf, false, false, 0.5, 0.5); },
        [](BSDF* bsdf) -> void
        { createMicrofacet(bsdf, true, false, 0.2, 0.1); },
        [](BSDF* bsdf) -> void
        { createMicrofacet(bsdf, false, false, 0.2, 0.1); },
        [](BSDF* bsdf) -> void
        { createMicrofacet(bsdf, true, false, 0.15, 0.25); },
        [](BSDF* bsdf) -> void
        { createMicrofacet(bsdf, false, false, 0.15, 0.25); },
        [](BSDF* bsdf) -> void
        { createMicrofacet(bsdf, true, false, 0.33, 0.033); },
        [](BSDF* bsdf) -> void
        { createMicrofacet(bsdf, false, false, 0.33, 0.033); },
        [](BSDF* bsdf) -> void
        { createFresnelBlend(bsdf, true, true, 0.15, 0.25); },
        [](BSDF* bsdf) -> void
        { createFresnelBlend(bsdf, false, true, 0.15, 0.25); },
        [](BSDF* bsdf) -> void
        { createFresnelBlend(bsdf, true, false, 0.15, 0.25); },
        [](BSDF* bsdf) -> void
        { createFresnelBlend(bsdf, false, false, 0.15, 0.25); },
    };

    const char* BSDFFuncDescripArray[] = {
        "Lambertian",
        "Oren Nayar (sigma 0)",
        "Oren Nayar (sigma 20)",
        "Beckmann (roughness 0.5, sample visible mf area)",
        "Trowbridge-Reitz (roughness 0.5, sample visible mf area)",
        "Beckmann (roughness 0.2/0.1, sample visible mf area)",
        "Trowbridge-Reitz (roughness 0.2/0.1, sample visible mf area)",
        "Beckmann (roughness 0.15/0.25, sample visible mf area)",
        "Trowbridge-Reitz (roughness 0.15/0.25, sample visible mf area)",
        "Beckmann (roughness 0.33/0.033, sample visible mf area)",
        "Trowbridge-Reitz (roughness 0.33/0.033, sample visible mf area)",
        "Beckmann (roughness 0.5, traditional sample wh)",
        "Trowbridge-Reitz (roughness 0.5, traditional sample wh)",
        "Beckmann (roughness 0.2/0.1, traditional sample wh)",
        "Trowbridge-Reitz (roughness 0.2/0.1, traditional sample wh)",
        "Beckmann (roughness 0.15/0.25, traditional sample wh)",
        "Trowbridge-Reitz (roughness 0.15/0.25, traditional sample wh)",
        "Beckmann (roughness 0.33/0.033, traditional sample wh)",
        "Trowbridge-Reitz (roughness 0.33/0.033, traditional sample wh)",
        "Fresnel Blend Beckmann (roughness 0.15/0.25, sample visible mf area)",
        "Fresnel Blend Trowbridge-Reitz (roughness 0.15/0.25, sample visible mf area)",
        "Fresnel Blend Beckmann (roughness 0.15/0.25, traditional sample wh)",
        "Fresnel Blend Trowbridge-Reitz (roughness 0.15/0.25, traditional sample wh)",
    };

    GenSampleFunc SampleFuncArray[] = {
        Gen_Sample_f,
        // CO        Gen_CosHemisphere,
        // CO        Gen_UniformHemisphere,
    };

    const char* SampleFuncDescripArray[] = {
        "BSDF Importance Sampling",
        // CO        "Cos Hemisphere",
        // CO        "Uniform Hemisphere",
    };

    int numModels = sizeof(BSDFFuncArray) / sizeof(BSDFFuncArray[0]);
    int numModelsDescrip =
        sizeof(BSDFFuncDescripArray) / sizeof(BSDFFuncDescripArray[0]);
    int numGenerators = sizeof(SampleFuncArray) / sizeof(SampleFuncArray[0]);
    int numGeneratorsDescrip =
        sizeof(SampleFuncDescripArray) / sizeof(SampleFuncDescripArray[0]);

    if (numModels != numModelsDescrip) {
        fprintf(stderr,
                "BSDFFuncArray and BSDFFuncDescripArray out of sync!\n");
        exit(1);
    }

    if (numGenerators != numGeneratorsDescrip) {
        fprintf(stderr,
                "SampleFuncArray and SampleFuncDescripArray out of sync!\n");
        exit(1);
    }

    // for each bsdf model
    for (int model = 0; model < numModels; model++) {
        BSDF* bsdf;

        // create BSDF which requires creating a Shape, casting a Ray
        // that hits the shape to get a SurfaceInteraction object.
        {
            Transform t = RotateX(-90);
            bool reverseOrientation = false;
            ParamSet p;

            std::shared_ptr<Shape> disk(
                new Disk(new Transform(t), new Transform(Inverse(t)),
                         reverseOrientation, 0., 1., 0, 360.));
            Point3f origin(
                0.1, 1, 0);  // offset slightly so we don't hit center of disk
            Vector3f direction(0, -1, 0);
            Float tHit;
            Ray r(origin, direction);
            SurfaceInteraction isect;
            disk->Intersect(r, &tHit, &isect);
            bsdf = ARENA_ALLOC(arena, BSDF)(isect);
            (BSDFFuncArray[model])(bsdf);
        }

        // facing directly at normal
        Vector3f woL = Normalize(Vector3f(0, 0, 1));
        Vector3f wo = bsdf->LocalToWorld(woL);
        // was bsdf->dgShading.nn
        const Normal3f n = Normal3f(bsdf->LocalToWorld(Vector3f(0, 0, 1)));

        // for each method of generating samples over the hemisphere
        for (int gen = 0; gen < numGenerators; gen++) {
            double redSum = 0.0;

            const int numHistoBins = 10;
            double histogram[numHistoBins][numHistoBins];
            for (int i = 0; i < numHistoBins; i++) {
                for (int j = 0; j < numHistoBins; j++) {
                    histogram[i][j] = 0;
                }
            }
            int badSamples = 0;
            int outsideSamples = 0;

            int warningTarget = 1;
            for (int sample = 0; sample < estimates; sample++) {
                Vector3f wi;
                Float pdf;
                Spectrum f;

                // sample hemisphere around bsdf, wo is fixed
                (SampleFuncArray[gen])(bsdf, wo, &wi, &pdf, &f);

                double redF = spectrumRedValue(f);

                // add hemisphere sample to histogram
                Vector3f wiL = bsdf->WorldToLocal(wi);
                float x = Clamp(wiL.x, -1.f, 1.f);
                float y = Clamp(wiL.y, -1.f, 1.f);
                float wiPhi = (atan2(y, x) + Pi) / (2.0 * Pi);
                float wiCosTheta = wiL.z;
                bool validSample = (wiCosTheta > 1e-7);
                if (wiPhi < -0.0001 || wiPhi > 1.0001 || wiCosTheta > 1.0001) {
                    // wiCosTheta can be less than 0
                    fprintf(stderr, "bad wi! %.3f %.3f %.3f, (%.3f %.3f)\n",
                            wiL[0], wiL[1], wiL[2], wiPhi, wiCosTheta);
                } else if (validSample) {
                    int histoPhi = (int)(wiPhi * numHistoBins);
                    if (histoPhi == numHistoBins)
                      --histoPhi;
                    int histoCosTheta = (int)(wiCosTheta * numHistoBins);
                    if (histoCosTheta == numHistoBins)
                      --histoCosTheta;
                    assert(histoPhi >= 0 && histoPhi < numHistoBins);
                    assert(histoCosTheta >= 0 && histoCosTheta < numHistoBins);
                    histogram[histoCosTheta][histoPhi] += 1.0 / pdf;
                }

                if (!validSample) {
                    outsideSamples++;
                } else if (pdf == 0.f || std::isnan(pdf) || redF < 0 ||
                           std::isnan(redF)) {
                    if (badSamples == warningTarget) {
                        fprintf(stderr,
                                "warning %d, bad sample %d! "
                                "pdf: %.3f, redF: %.3f\n",
                                warningTarget, sample, pdf, redF);
                        warningTarget *= 10;
                    }
                    badSamples++;
                } else {
                    // outgoing radiance estimate =
                    //   bsdf * incomingRadiance * cos(wi) / pdf
                    redSum += redF * environmentRadiance * AbsDot(wi, n) / pdf;
                }
            }
            int goodSamples = estimates - badSamples;

            // print results
            fprintf(stderr,
                    "*** BRDF: '%s', Samples: '%s'\n\n"
                    "wi histogram showing the relative weight in each bin\n"
                    "  all entries should be close to 2pi = %.5f:\n"
                    "  (%d bad samples, %d outside samples)\n\n"
                    "                          phi bins\n",
                    BSDFFuncDescripArray[model], SampleFuncDescripArray[gen],
                    Pi * 2.0, badSamples, outsideSamples);
            double totalSum = 0.0;
            for (int i = 0; i < numHistoBins; i++) {
                fprintf(stderr, "  cos(theta) bin %02d:", i);
                for (int j = 0; j < numHistoBins; j++) {
                    fprintf(stderr, " %5.2f", histogram[i][j] * numHistoBins *
                                                  numHistoBins / goodSamples);
                    totalSum += histogram[i][j];
                }
                fprintf(stderr, "\n");
            }
            fprintf(stderr,
                    "\n  final average :  %.5f (error %.5f)\n\n"
                    "  radiance = %.5f\n\n",
                    totalSum / goodSamples, totalSum / goodSamples - Pi * 2.0,
                    redSum / goodSamples);
        }
    }

    pbrtCleanup();
    return 0;
}
예제 #22
0
Spectrum SeparableBSSRDF::Sample_Sp(const Scene &scene, Float sample1,
                                    const Point2f &sample2, MemoryArena &arena,
                                    SurfaceInteraction *pi, Float *pdf) const {
    ProfilePhase pp(Prof::BSSRDFEvaluation);
    // Choose projection axis for BSSRDF sampling
    Vector3f axis;
    if (sample1 < .25f) {
        axis = ss;
        sample1 *= 4;
    } else if (sample1 < .5f) {
        axis = ts;
        sample1 = (sample1 - .25f) * 4;
    } else {
        axis = Vector3f(ns);
        sample1 = (sample1 - .5f) * 2;
    }

    // Choose spectral channel for BSSRDF sampling
    int ch =
        Clamp((int)(sample1 * Spectrum::nSamples), 0, Spectrum::nSamples - 1);
    sample1 = sample1 * Spectrum::nSamples - ch;

    // Sample BSSRDF profile in polar coordinates
    Float r = Sample_Sr(ch, sample2.x);
    if (r < 0) return Spectrum(0.f);
    Float phi = 2 * Pi * sample2.y;

    // Compute BSSRDF profile bounds and intersection height
    Float rMax = Sample_Sr(ch, 0.999f);
    if (r > rMax) return Spectrum(0.f);
    Float l = 2 * std::sqrt(rMax * rMax - r * r);

    // Compute BSSRDF sampling ray segment
    Vector3f v0, v1;
    CoordinateSystem(axis, &v0, &v1);
    Interaction base;
    base.p =
        po.p + r * (v0 * std::cos(phi) + v1 * std::sin(phi)) - l * axis * 0.5f;
    base.time = po.time;
    Point3f target = base.p + l * axis;

    // Intersect BSSRDF sampling ray against the scene geometry
    struct IntersectionChain {
        SurfaceInteraction si;
        IntersectionChain *next;
    };
    IntersectionChain *chain = ARENA_ALLOC(arena, IntersectionChain)(),
                      *ptr = chain;
    int nFound = 0;
    while (true) {
        if (!scene.Intersect(base.SpawnRayTo(target), &ptr->si)) break;
        base = ptr->si;
        // Append admissible intersection to _IntersectionChain_
        if (ptr->si.primitive->GetMaterial() == material) {
            IntersectionChain *next = ARENA_ALLOC(arena, IntersectionChain)();
            ptr->next = next;
            ptr = next;
            nFound++;
        }
    }

    // Randomly choose one of several intersections during BSSRDF sampling
    if (nFound == 0) return Spectrum(0.0f);
    int selected = Clamp((int)(sample1 * nFound), 0, nFound - 1);
    while (selected-- > 0) chain = chain->next;
    *pi = chain->si;

    // Compute sample PDF and return the spatial BSSRDF term $\Sp$
    *pdf = Pdf_Sp(*pi) / nFound;
    return Sp(*pi);
}