PBRT_V2 总结记录 UseRadianceProbes

UseRadianceProbes

class UseRadianceProbes : public SurfaceIntegrator {
public:
    // UseRadianceProbes Public Methods
    UseRadianceProbes(const string &filename);
    ~UseRadianceProbes();
    void RequestSamples(Sampler *sampler, Sample *sample, const Scene *scene);
    Spectrum Li(const Scene *scene, const Renderer *,
                const RayDifferential &ray, const Intersection &isect,
                const Sample *sample, RNG &rng, MemoryArena &arena) const;
private:
    // UseRadianceProbes Private Methods
    const Spectrum *c_inXYZ(int lmax, int vx, int vy, int vz) const {
        vx = Clamp(vx, 0, nProbes[0]-1);
        vy = Clamp(vy, 0, nProbes[1]-1);
        vz = Clamp(vz, 0, nProbes[2]-1);
        int offset = vx + vy * nProbes[0] + vz * nProbes[0] * nProbes[1];
        return &c_in[SHTerms(lmax) * offset];
    }

    // UseRadianceProbes Private Data
    BBox bbox;
    int lmax, includeDirectInProbes, includeIndirectInProbes;
    int nProbes[3];
    Spectrum *c_in;

    // Declare sample parameters for light source sampling
    LightSampleOffsets *lightSampleOffsets;
    BSDFSampleOffsets *bsdfSampleOffsets;
};

作用:

(UseRadianceProbes  使用 CreateRadianceProbes  生成出来的 radiance probes 来渲染场景)

The UseRadianceProbes SurfaceIntegrator reads in a text file of radiance probes generated
by the CreateRadianceProbes Renderer and uses the probes to illuminate the scene.
Because the lighting computations with radiance probes can be performed extremely efficiently
and because looking up radiance probes stored in a regular grid is straightforward,
the corresponding lighting calculations can reasonably be performed in interactive rendering
systems.

1. 


Spectrum UseRadianceProbes::Li(const Scene *scene, const Renderer *renderer,
            const RayDifferential &ray, const Intersection &isect,
            const Sample *sample, RNG &rng, MemoryArena &arena) const {
    Spectrum L(0.);
    Vector wo = -ray.d;
    // Compute emitted light if ray hit an area light source
    L += isect.Le(wo);

    // Evaluate BSDF at hit point
    BSDF *bsdf = isect.GetBSDF(ray, arena);
    const Point &p = bsdf->dgShading.p;
    const Normal &n = bsdf->dgShading.nn;
    // Compute reflection for radiance probes integrator
    if (!includeDirectInProbes)
        L += UniformSampleAllLights(scene, renderer, arena, p, n,
                wo, isect.rayEpsilon, ray.time, bsdf, sample, rng,
                lightSampleOffsets, bsdfSampleOffsets);

    // Compute reflected lighting using radiance probes

    // Compute probe coordinates and offsets for lookup point
    Vector offset = bbox.Offset(p);
    float voxx = (offset.x * nProbes[0]) - 0.5f;
    float voxy = (offset.y * nProbes[1]) - 0.5f;
    float voxz = (offset.z * nProbes[2]) - 0.5f;
    int vx = Floor2Int(voxx), vy = Floor2Int(voxy), vz = Floor2Int(voxz);
    float dx = voxx - vx, dy = voxy - vy, dz = voxz - vz;

    // Get radiance probe coefficients around lookup point
    const Spectrum *b000 = c_inXYZ(lmax, vx,   vy,   vz);
    const Spectrum *b100 = c_inXYZ(lmax, vx+1, vy,   vz);
    const Spectrum *b010 = c_inXYZ(lmax, vx,   vy+1, vz);
    const Spectrum *b110 = c_inXYZ(lmax, vx+1, vy+1, vz);
    const Spectrum *b001 = c_inXYZ(lmax, vx,   vy,   vz+1);
    const Spectrum *b101 = c_inXYZ(lmax, vx+1, vy,   vz+1);
    const Spectrum *b011 = c_inXYZ(lmax, vx,   vy+1, vz+1);
    const Spectrum *b111 = c_inXYZ(lmax, vx+1, vy+1, vz+1);

    // Compute incident radiance from radiance probe coefficients
    Spectrum *c_inp = arena.Alloc<Spectrum>(SHTerms(lmax));
    for (int i = 0; i < SHTerms(lmax); ++i) {
        // Do trilinear interpolation to compute SH coefficients at point
        Spectrum c00 = Lerp(dx, b000[i], b100[i]);
        Spectrum c10 = Lerp(dx, b010[i], b110[i]);
        Spectrum c01 = Lerp(dx, b001[i], b101[i]);
        Spectrum c11 = Lerp(dx, b011[i], b111[i]);
        Spectrum c0 = Lerp(dy, c00, c10);
        Spectrum c1 = Lerp(dy, c01, c11);
        c_inp[i] = Lerp(dz, c0, c1);
    }

    // Convolve incident radiance to compute irradiance function
    Spectrum *c_E = arena.Alloc<Spectrum>(SHTerms(lmax));
    SHConvolveCosTheta(lmax, c_inp, c_E);

    // Evaluate irradiance function and accumulate reflection
    Spectrum rho = bsdf->rho(wo, rng, BSDF_ALL_REFLECTION);
    float *Ylm = ALLOCA(float, SHTerms(lmax));
    SHEvaluate(Vector(Faceforward(n, wo)), lmax, Ylm);
    Spectrum E = 0.f;
    for (int i = 0; i < SHTerms(lmax); ++i)
        E += c_E[i] * Ylm[i];
    L += rho * INV_PI * E.Clamp();
    return L;
}

细节

a.

// Compute probe coordinates and offsets for lookup point
    Vector offset = bbox.Offset(p);
    float voxx = (offset.x * nProbes[0]) - 0.5f;
    float voxy = (offset.y * nProbes[1]) - 0.5f;
    float voxz = (offset.z * nProbes[2]) - 0.5f;
    int vx = Floor2Int(voxx), vy = Floor2Int(voxy), vz = Floor2Int(voxz);
    float dx = voxx - vx, dy = voxy - vy, dz = voxz - vz;

作用:

(获得 交点 p 在 bbox 场景包围盒中,属于哪一个子包围盒节点,获得 vx,vy,vz 的索引,dx,dy,dz 是表示,周围的子包围盒的 probe 对这个交点的影响)

The integer coordinates of the lookup point p are found using the same calculation as
is used to convert from continuous to discrete pixel coordinates (recall the discussion in
Section 7.1.7). Given the discrete coordinates, floating-point offsets dx, dy, and dz are
found for trilinear interpolation.

扫描二维码关注公众号,回复: 5100435 查看本文章

b.

// Get radiance probe coefficients around lookup point
    const Spectrum *b000 = c_inXYZ(lmax, vx,   vy,   vz);
    const Spectrum *b100 = c_inXYZ(lmax, vx+1, vy,   vz);
    const Spectrum *b010 = c_inXYZ(lmax, vx,   vy+1, vz);
    const Spectrum *b110 = c_inXYZ(lmax, vx+1, vy+1, vz);
    const Spectrum *b001 = c_inXYZ(lmax, vx,   vy,   vz+1);
    const Spectrum *b101 = c_inXYZ(lmax, vx+1, vy,   vz+1);
    const Spectrum *b011 = c_inXYZ(lmax, vx,   vy+1, vz+1);
    const Spectrum *b111 = c_inXYZ(lmax, vx+1, vy+1, vz+1);


    const Spectrum *c_inXYZ(int lmax, int vx, int vy, int vz) const {
        vx = Clamp(vx, 0, nProbes[0]-1);
        vy = Clamp(vy, 0, nProbes[1]-1);
        vz = Clamp(vz, 0, nProbes[2]-1);
        int offset = vx + vy * nProbes[0] + vz * nProbes[0] * nProbes[1];
        return &c_in[SHTerms(lmax) * offset];
    }

作用:

(得到 交点 p 在哪一个 子包围盒,那么就可以 获得 子包围盒 对应的SH 系数,同时也获得周围附近的子包围盒的 的SH)

The c_inXYZ() utility function, not included here in the book text, clamps the given
discrete coordinates to the valid range and returns a pointer to the first Spectrum in the
array that holds the SH coefficients at the given grid cell.

c.

// Compute incident radiance from radiance probe coefficients
    Spectrum *c_inp = arena.Alloc<Spectrum>(SHTerms(lmax));
    for (int i = 0; i < SHTerms(lmax); ++i) {
        // Do trilinear interpolation to compute SH coefficients at point
        Spectrum c00 = Lerp(dx, b000[i], b100[i]);
        Spectrum c10 = Lerp(dx, b010[i], b110[i]);
        Spectrum c01 = Lerp(dx, b001[i], b101[i]);
        Spectrum c11 = Lerp(dx, b011[i], b111[i]);
        Spectrum c0 = Lerp(dy, c00, c10);
        Spectrum c1 = Lerp(dy, c01, c11);
        c_inp[i] = Lerp(dz, c0, c1);
    }

作用:

(计算最后的SH系数,考虑周围的 子包围盒的SH系数)

Given the pointers to the eight sets of coefficients around the point, we’ll now compute
the trilinearly interpolated SH coefficients that represent the incident radiance at p and
store them in the temporary c_inp array.

d.

    // Convolve incident radiance to compute irradiance function
    Spectrum *c_E = arena.Alloc<Spectrum>(SHTerms(lmax));
    SHConvolveCosTheta(lmax, c_inp, c_E);

    // Evaluate irradiance function and accumulate reflection
    Spectrum rho = bsdf->rho(wo, rng, BSDF_ALL_REFLECTION);
    float *Ylm = ALLOCA(float, SHTerms(lmax));
    SHEvaluate(Vector(Faceforward(n, wo)), lmax, Ylm);
    Spectrum E = 0.f;
    for (int i = 0; i < SHTerms(lmax); ++i)
        E += c_E[i] * Ylm[i];
    L += rho * INV_PI * E.Clamp();
    return L;

作用:

Ramamoorthi (2002) showed that the reflection equation, Equation (5.8), can equivalently
be written as a convolution of a signal (the incident radiance function) with a
filter (the cosine weighted BSDF).

(这里我理解的就是,the incident radiance function (卷积) the incident radiance function = 一个积分)

Here, we would like to compute the incident irradiance function on one side of a surface,
which is given as a function of position and normal by the integral

(那么 这里的 E 就可以 Li (卷积) max(0, cos θi) 得到)

Given a function of direction f (ω) and a
circularly symmetric 1D function g(θ), with respective SH coefficients , then
it’s possible to directly compute the SH coefficients of the function that is the result of
their convolution (f ∗ g),

(上面说的就是,f 与 g 的 卷积 的 SH 系数 可以 用

 

来计算)

下面是计算 E 值,

怎么计算呢,上面的 clm 其实就是 E 的SH系数,那么 E的 SH系数怎么计算呢,就是上面说的,这里的 E 就可以

通过 Li (卷积) max(0, cos θi) 得到,那么  E的 SH系数 =  Li (卷积) max(0, cos θi)  的SH系数 = 17.16的公式,

那么  SHConvolveCosTheta 函数 的 c_E 参数,就是返回了   E的 SH系数,


void SHConvolveCosTheta(int lmax, const Spectrum *c_in,
                        Spectrum *c_out) {
    static const float c_costheta[18] = { 0.8862268925, 1.0233267546,
        0.4954159260, 0.0000000000, -0.1107783690, 0.0000000000,
        0.0499271341, 0.0000000000, -0.0285469331, 0.0000000000,
        0.0185080823, 0.0000000000, -0.0129818395, 0.0000000000,
        0.0096125342, 0.0000000000, -0.0074057109, 0.0000000000 };
    for (int l = 0; l <= lmax; ++l)
        for (int m = -l; m <= l; ++m) {
            int o = SHIndex(l, m);
            if (l < 18) c_out[o] = lambda(l) * c_in[o] * c_costheta[l];
            else        c_out[o] = 0.f;
        }
}

 c_costheta 就是 max(0, cos θ) 的SH系数, c_in 就是 Li 的SH系数,lambda 就是  

得到了 c_E 的之后,就可以用

来计算 交点的E 值。

得到E之后,直接使用 diffyse reflectance 来重构 outgoing radiance。 

The diffuse reflectance ρ times the reconstructed irradiance gives the final contribution to outgoing
radiance.

猜你喜欢

转载自blog.csdn.net/aa20274270/article/details/86528491