PBRT_V2 总结记录 <95> InfiniteAreaLight 补充

InfiniteAreaLight


// InfiniteAreaLight Declarations
class InfiniteAreaLight : public Light {
public:
    // InfiniteAreaLight Public Methods
    InfiniteAreaLight(const Transform &light2world, const Spectrum &power, int ns,
        const string &texmap);
    ~InfiniteAreaLight();
    Spectrum Power(const Scene *) const;
    bool IsDeltaLight() const { return false; }
    Spectrum Le(const RayDifferential &r) const;
    Spectrum Sample_L(const Point &p, float pEpsilon, const LightSample &ls,
        float time, Vector *wi, float *pdf, VisibilityTester *visibility) const;
    Spectrum Sample_L(const Scene *scene, const LightSample &ls, float u1, float u2,
        float time, Ray *ray, Normal *Ns, float *pdf) const;
    float Pdf(const Point &, const Vector &) const;
    void SHProject(const Point &p, float pEpsilon, int lmax, const Scene *scene,
        bool computeLightVis, float time, RNG &rng, Spectrum *coeffs) const;
private:
    // InfiniteAreaLight Private Data
    MIPMap<RGBSpectrum> *radianceMap;
    Distribution2D *distribution;
};

 

1. 构造函数:


InfiniteAreaLight::InfiniteAreaLight(const Transform &light2world,
        const Spectrum &L, int ns, const string &texmap)
    : Light(light2world, ns) {
    int width = 0, height = 0;
    RGBSpectrum *texels = NULL;
    // Read texel data from _texmap_ into _texels_
    if (texmap != "") {
        texels = ReadImage(texmap, &width, &height);
        if (texels)
            for (int i = 0; i < width * height; ++i)
                texels[i] *= L.ToRGBSpectrum();
    }
    if (!texels) {
        width = height = 1;
        texels = new RGBSpectrum[1];
        texels[0] = L.ToRGBSpectrum();
    }
    radianceMap = new MIPMap<RGBSpectrum>(width, height, texels);
    delete[] texels;
    // Initialize sampling PDFs for infinite area light

    // Compute scalar-valued image _img_ from environment map
    float filter = 1.f / max(width, height);
    float *img = new float[width*height];
    for (int v = 0; v < height; ++v) {
        float vp = (float)v / (float)height;
        float sinTheta = sinf(M_PI * float(v+.5f)/float(height));
        for (int u = 0; u < width; ++u) {
            float up = (float)u / (float)width;
            img[u+v*width] = radianceMap->Lookup(up, vp, filter).y();
            img[u+v*width] *= sinTheta;
        }
    }

    // Compute sampling distributions for rows and columns of image
    distribution = new Distribution2D(img, width, height);
    delete[] img;
}

补充《PBRT_V2 总结记录 <69> InfiniteAreaLight》,在构造函数里面,

    // Compute scalar-valued image _img_ from environment map
    float filter = 1.f / max(width, height);
    float *img = new float[width*height];
    for (int v = 0; v < height; ++v) {
        float vp = (float)v / (float)height;
        float sinTheta = sinf(M_PI * float(v+.5f)/float(height));
        for (int u = 0; u < width; ++u) {
            float up = (float)u / (float)width;
            img[u+v*width] = radianceMap->Lookup(up, vp, filter).y();
            img[u+v*width] *= sinTheta;
        }
    }

    distribution = new Distribution2D(img, width, height);

作用:

(个人理解,这里主要的目的就是根据 环境图的亮度(radianceMap->Lookup().y()) 来计算 1个Distribution2D ,也就是 2D PDF,那么为什么要乘上 sin θ,主要的目的就是为了可以更加均匀地采样图片,( eliminate(消除) the
effect of the distortion(变形) from mapping the 2D image to the unit sphere in the sampling
method here
))

The first step is to transformthe continuously defined spectral radiance function defined
by the environment map’s texels to a piecewise-constant scalar function by computing
its luminance at a set of sample points using the Spectrum::y() method.

Finally, each image value in the img buffer is multiplied by the value of sin θ corresponding
to the θ value each row has when the latitude–longitude image is mapped to the
sphere. Note that this multiplication has no effect on the sampling method’s correctness:

because the value of sin θ is always greater than zero over the [0, π] range, we are just
reshaping the sampling PDF. The motivation for adjusting the PDF is to eliminate(消除) the
effect of the distortion(变形) from mapping the 2D image to the unit sphere in the sampling
method here; 

 

2. 


Spectrum InfiniteAreaLight::Sample_L(const Point &p, float pEpsilon,
        const LightSample &ls, float time, Vector *wi, float *pdf,
        VisibilityTester *visibility) const {
    PBRT_INFINITE_LIGHT_STARTED_SAMPLE();
    // Find $(u,v)$ sample coordinates in infinite light texture
    float uv[2], mapPdf;
    distribution->SampleContinuous(ls.uPos[0], ls.uPos[1], uv, &mapPdf);
    if (mapPdf == 0.f) return 0.f;

    // Convert infinite light sample point to direction
    float theta = uv[1] * M_PI, phi = uv[0] * 2.f * M_PI;
    float costheta = cosf(theta), sintheta = sinf(theta);
    float sinphi = sinf(phi), cosphi = cosf(phi);
    *wi = LightToWorld(Vector(sintheta * cosphi, sintheta * sinphi,
                              costheta));

    // Compute PDF for sampled infinite light direction
    *pdf = mapPdf / (2.f * M_PI * M_PI * sintheta);
    if (sintheta == 0.f) *pdf = 0.f;

    // Return radiance value for infinite light direction
    visibility->SetRay(p, pEpsilon, *wi, time);
    Spectrum Ls = Spectrum(radianceMap->Lookup(uv[0], uv[1]),
                           SPECTRUM_ILLUMINANT);
    PBRT_INFINITE_LIGHT_FINISHED_SAMPLE();
    return Ls;
}

作用:

这个函数就会返回 一个 radiance,表示光源到达这个点的 radiance(在没有被其他物体遮挡的情况下),同时也会返回 wi, 表示 光源的radiance 是从哪一个方向到达的,  同时也会 初始化一个 VisibilityTester  来记录 point 和 光源的 遮挡关系。

 

细节

a.

    // Compute PDF for sampled infinite light direction
    *pdf = mapPdf / (2.f * M_PI * M_PI * sintheta);
    if (sintheta == 0.f) *pdf = 0.f;

作用:(计算pdf, 这里就是 先 计算 p(θ , φ) 和 p(u,v)的关系,再利用 p(w) 与 p(θ , φ) 的关系,计算出 p(w) 和 p(u,v)的关系,(怎么计算的话,可以参考 《PBRT_V2 总结记录 <93> Transforming Between Distributions In Multiple Dimensions》)但是这里需要注意的是,mapPdf 是 直接采样  distribution,distribution的值在构造函数里面已经乘上了 sinθ, 那么这里其实抵消了  sinθ,就形成均匀采样的结果)

First, consider the function g that maps from (u, v) to (θ , φ),

The absolute value of the determinant of the Jacobian |Jg| is 2π^2. Applying the multidimensional
change of variables equation from Section 13.5.1, we can find the density in
terms of spherical coordinates (θ , φ).

From the definition of spherical coordinates, it is easy to determine that the absolute
value of the Jacobian for the mapping from (r , θ , φ) to (x, y, z) is r^2 sin θ. Since we are
interested in the unit sphere, r = 1, and again applying the multidimensional change of
variables equation to find the final relationship between probability densities,

This is the key relationship for applying this technique: it lets us sample from the
piecewise-constant distribution defined by the image map and transform the sample
and its probability density to be in terms of directions on the unit sphere.

We can now see why the initialization routines multiplied the values of the piecewiseconstant
sampling function by a sin θ term. Consider, for example, a constant-valued
environment map: with the p(u, v) sampling technique, all (θ , φ) values are equally
likely to be chosen. Due to the mapping to directions on the sphere, however, this would
lead to more directions being sampled near the poles of the sphere, not a uniform sampling
of directions on the sphere, which would be a more desirable result. The 1/ sin θ
term in the p(ω) PDF corrects for this non-uniform sampling of directions so that correct
results are computed in Monte Carlo estimates. Given this state of affairs, however,
it’s better to have modified the p(u, v) sampling distribution so that it’s less likely to
select directions near the poles in the first place.

 

3. 

float InfiniteAreaLight::Pdf(const Point &, const Vector &w) const {
    PBRT_INFINITE_LIGHT_STARTED_PDF();
    Vector wi = WorldToLight(w);
    float theta = SphericalTheta(wi), phi = SphericalPhi(wi);
    float sintheta = sinf(theta);
    if (sintheta == 0.f) return 0.f;
    float p = distribution->Pdf(phi * INV_TWOPI, theta * INV_PI) /
           (2.f * M_PI * M_PI * sintheta);
    PBRT_INFINITE_LIGHT_FINISHED_PDF();
    return p;
}

作用:

The InfiniteAreaLight::Pdf() method needs to convert the direction ω to the corresponding
(u, v) coordinates in the sampling distribution. Given these, the PDF p(u, v)
is computed as the product of the two 1D PDFs by the Distribution2D::Pdf() method,
which is adjusted here for mapping to the sphere as was done in the Sample_L() method.

 

4. 


Spectrum InfiniteAreaLight::Sample_L(const Scene *scene,
        const LightSample &ls, float u1, float u2, float time,
        Ray *ray, Normal *Ns, float *pdf) const {
    PBRT_INFINITE_LIGHT_STARTED_SAMPLE();
    // Compute direction for infinite light sample ray

    // Find $(u,v)$ sample coordinates in infinite light texture
    float uv[2], mapPdf;
    distribution->SampleContinuous(ls.uPos[0], ls.uPos[1], uv, &mapPdf);
    if (mapPdf == 0.f) return Spectrum(0.f);

    float theta = uv[1] * M_PI, phi = uv[0] * 2.f * M_PI;
    float costheta = cosf(theta), sintheta = sinf(theta);
    float sinphi = sinf(phi), cosphi = cosf(phi);
    Vector d = -LightToWorld(Vector(sintheta * cosphi, sintheta * sinphi,
                                    costheta));
    *Ns = (Normal)d;

    // Compute origin for infinite light sample ray
    Point worldCenter;
    float worldRadius;
    scene->WorldBound().BoundingSphere(&worldCenter, &worldRadius);
    Vector v1, v2;
    CoordinateSystem(-d, &v1, &v2);
    float d1, d2;
    ConcentricSampleDisk(u1, u2, &d1, &d2);
    Point Pdisk = worldCenter + worldRadius * (d1 * v1 + d2 * v2);
    *ray = Ray(Pdisk + worldRadius * -d, d, 0., INFINITY, time);

    // Compute _InfiniteAreaLight_ ray PDF
    float directionPdf = mapPdf / (2.f * M_PI * M_PI * sintheta);
    float areaPdf = 1.f / (M_PI * worldRadius * worldRadius);
    *pdf = directionPdf * areaPdf;
    if (sintheta == 0.f) *pdf = 0.f;
    Spectrum Ls = (radianceMap->Lookup(uv[0], uv[1]), SPECTRUM_ILLUMINANT);
    PBRT_INFINITE_LIGHT_FINISHED_SAMPLE();
    return Ls;
}

作用:

(这个Sample_L 利用采样点生成一条 ray,这条Ray 是从 Light 发出的,保存到 参数 ray中,而且,返回光源面上一点的法线到 参数 Ns中,并且会返回这个采样点 所产生的 光源 Spectrum 值,其实就是这个光源的随机发出 Ray,这个Ray 带有多少 radiance)

Generating a random ray leaving an infinite light source can be done by sampling a
direction with the same approach as is used for direct lighting in the Sample_L() method
above. The sampled ray’s origin is then set using the same approach as was used for
DistantLights in Section 14.6.2, where a disk that covers the scene’s bounding sphere
is oriented along the ray’s direction.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值