PBRT_V2 总结记录 <62> Light 和 VisibilityTester

Light 类

class Light {
public:
    // Light Interface
    virtual ~Light();
    Light(const Transform &l2w, int ns = 1)
        : nSamples(max(1, ns)), LightToWorld(l2w),
          WorldToLight(Inverse(l2w)) {
        // Warn if light has transformation with scale
        if (WorldToLight.HasScale())
            Warning("Scaling detected in world to light transformation!\n"
                    "The system has numerous assumptions, implicit and explicit,\n"
                    "that this transform will have no scale factors in it.\n"
                    "Proceed at your own risk; your image may have errors or\n"
                    "the system may crash as a result of this.");
    }
    virtual Spectrum Sample_L(const Point &p, float pEpsilon,
        const LightSample &ls, float time, Vector *wi, float *pdf,
        VisibilityTester *vis) const = 0;
    virtual Spectrum Power(const Scene *) const = 0;
    virtual bool IsDeltaLight() const = 0;
    virtual Spectrum Le(const RayDifferential &r) const;
    virtual float Pdf(const Point &p, const Vector &wi) const = 0;
    virtual Spectrum Sample_L(const Scene *scene, const LightSample &ls,
                              float u1, float u2, float time, Ray *ray,
                              Normal *Ns, float *pdf) const = 0;
    virtual void SHProject(const Point &p, float pEpsilon, int lmax,
        const Scene *scene, bool computeLightVisibility, float time,
        RNG &rng, Spectrum *coeffs) const;

    // Light Public Data
    const int nSamples;
protected:
    // Light Protected Data
    const Transform LightToWorld, WorldToLight;
};

类的作用:

(光源的基类,这个设计思路基本和 acceleration structures 一致,都是不需要关心具体的光源细节)

This chapter introduces the abstract Light class, which
defines the interface used for light sources in pbrt, as well as the implementations of a
number of useful light sources. By hiding the implementation of different types of lights
behind a carefully designed interface, the light transport routines can operate without
knowing which particular types of lights are in the scene, similar to how the acceleration
structures can hold collections of primitives without needing to know their actual types.

 

1. 构造函数

 Light(const Transform &l2w, int ns = 1)
        : nSamples(max(1, ns)), LightToWorld(l2w),
          WorldToLight(Inverse(l2w)) {
        // Warn if light has transformation with scale
        if (WorldToLight.HasScale())
            Warning("Scaling detected in world to light transformation!\n"
                    "The system has numerous assumptions, implicit and explicit,\n"
                    "that this transform will have no scale factors in it.\n"
                    "Proceed at your own risk; your image may have errors or\n"
                    "the system may crash as a result of this.");
    }



作用:

(所有的Light都会有两个参数,1个是 transformation l2w, 从光源坐标系变换到世界坐标系,nSamples 光源的采样数目,所以构造函数就直接传入这两个参数,这里需要注意的是,光源也有自己的坐标系)

All lights share two common parameters: a transformation that defines the light’s coordinate
system in world space and a parameter that affects Monte Carlo sampling of lights,
nSamples.
As with shapes, it’s often handy to be able to implement a light assuming a particular
coordinate system
(e.g., that a spotlight is always located at the origin of its light
space, shining down the +z axis). The light-to-world transformation makes it possible
to place such lights at arbitrary positions and orientations in the scene. The nSamples parameter
is used for area light sources where it may be desirable to trace multiple shadow
rays to the light to compute soft shadows; it allows the user to have finer-grained(粒度) control
of the number of samples taken on a per-light basis.

The only other job for the constructor is to warn if the light-to-world
transformation has a scale factor; many of the Light methods will return incorrect results
in this case.1

 

2. 

virtual Spectrum Sample_L(const Point &p, float pEpsilon,
        const LightSample &ls, float time, Vector *wi, float *pdf,
        VisibilityTester *vis) const = 0;

作用:

(传入一个world space的 Point,和light sample需要的time参数,那么这个函数就会返回 一个 radiance,表示光源到达这个点的 radiance(在没有被其他物体遮挡的情况下),同时也会返回 wi, 表示 光源的radiance 是从哪一个方向到达的,  同时也会 初始化一个 VisibilityTester  来记录 point 和 光源的 遮挡关系)

(这里需要注意的是,对于某一些光源,这个光源发射出来的光线可能从很多个方向来到达这个Point,而不只是一个方向,这种情况的话,需要对光源进行采样,看看这个光源 发出的所有的光线中, 有哪一些是到达Point的。(其实就是对光源进行积分,而不是对Point进行积分))

The key method for lights to implement is Sample_L(). The caller passes the world space
position of a point in the scene and the time at which the light sample is to be taken, and
the light returns the radiance arriving at that point due to that light, assuming there are
no occluding objects between them (Figure 12.1).Although this method also takes a time
value, the Light implementations do not currently support being animated themselves—
the lights themselves are at fixed positions in the scene.
(Addressing this limitation is
left as an exercise.) However, the time value is needed to set the corresponding value
appropriately in the traced visibility ray.

Figure 12.1: The Light::Sample_L() method returns incident radiance from the light at a point p
and also returns the direction vector ω that gives the direction from which radiance is arriving.

 

The light is also responsible for initializing the incident direction to the light source
ωi and for initializing the VisibilityTester object, which holds information about the
shadow ray that must be traced to verify that there are no occluding objects between the
light and p.
The VisibilityTester, which will be described in Section 12.1.1, need not
be initialized if the returned radiance value is black—for example, due to the point p
being outside of the cone of illumination of a spotlight. In addition to the point p being
illuminated, this method takes an epsilon value for shadow rays leaving p, pEpsilon.

 

For some types of lights, light may arrive at p from many directions, not just from
a single direction as with a point light source, for example. For these types of light
sources, the Sample_L() method must randomly sample a point on the light source’s
surface, so thatMonte Carlo integration can be used to find the reflected light at p due to
illumination from the light.
Implementations of the Sample_L() interface for such lights
will be introduced later, in Section 14.6. The LightSample is used by these methods, and
the pdf output parameter stores the probability density for the light sample taken. For
all of the implementations in this chapter, the LightSample is ignored and the pdf is
set to one. The pdf value’s role in the context of Monte Carlo sampling is discussed in
Section 14.6.1.

 

3. virtual Spectrum Power(const Scene *) const = 0;

作用:

All lights must also be able to return their total emitted power; this quantity is useful for
light transport algorithms that may want to devote(贡献) additional computational resources
to lights in the scene that make the largest contribution.
Because a precise value for
emitted power isn’t needed elsewhere in the system, a number of the implementations of
this method later in this chapter will compute approximations to this value rather than
expending computational effort to find a precise value.

 

4. virtual bool IsDeltaLight() const = 0;

作用:

(这个方法就是用来表明这个光源 是否被描述为 delta distribution,像 point light 和 directional light 都是 delta light,  因为没有办法对 这些光源进行采样,这个方法主要是用来之后的  Monte Carlo algorithms 计算 radiance 的时候,Monte Carlo 要知道这个光源是否是 delta light,如果是 delta light 的话,采用不一样的计算方式)

Finally, the IsDeltaLight() method indicates(表明) whether the light is described by a delta
distribution. Examples of such lights include point lights, which emit illumination from
a single point, and directional lights, where all light arrives from the same direction.
The
only way to detect illumination from light sources like these is to call their Sample_L()
methods. It’s impossible to randomly choose a direction from a point p that happens to
find such a light source.
(This is analogous to delta components in BSDFs from specular
reflection or transmission.) The Monte Carlo algorithms that sample illumination from
light sources need to be aware of which lights are described by delta distributions, since
this affects some of their computations.

 

 

VisibilityTester 类


struct VisibilityTester {
    // VisibilityTester Public Methods
    void SetSegment(const Point &p1, float eps1,
                    const Point &p2, float eps2, float time) {
        float dist = Distance(p1, p2);
        r = Ray(p1, (p2-p1) / dist, eps1, dist * (1.f - eps2), time);
        Assert(!r.HasNaNs());
    }
    void SetRay(const Point &p, float eps, const Vector &w, float time) {
        r = Ray(p, w, eps, INFINITY, time);
        Assert(!r.HasNaNs());
    }
    bool Unoccluded(const Scene *scene) const;
    Spectrum Transmittance(const Scene *scene, const Renderer *renderer,
        const Sample *sample, RNG &rng, MemoryArena &arena) const;
    Ray r;
};

类的作用:

(这个类主要就是 用来判断 两点之间 是否 互相可视,判断是否有其他物体在他们中间)

The VisibilityTester is a closure(闭包)—an object that encapsulates a small amount of data
and some computation that is yet to be done. It allows lights to return a radiance value
under the assumption that the receiving point p and the light source are mutually(互相) visible.

The integrator can then decide if illumination from the direction ω is relevant before
incurring the cost of tracing the shadow ray—for example, light incident on the back
side of a surface that isn’t translucent(不是透明表面) contributes nothing to reflection from the other
side. If the actual amount of arriving illumination is in fact needed, a call to one of the
visibility tester’s methods causes the necessary shadow ray to be traced.

 

1. 

    void SetSegment(const Point &p1, float eps1,
                    const Point &p2, float eps2, float time) {
        float dist = Distance(p1, p2);
        r = Ray(p1, (p2-p1) / dist, eps1, dist * (1.f - eps2), time);
        Assert(!r.HasNaNs());
    }

    void SetRay(const Point &p, float eps, const Vector &w, float time) {
        r = Ray(p, w, eps, INFINITY, time);
        Assert(!r.HasNaNs());
    }

作用:

(初始化 VisibilityTesters 的函数,

SetSegment, 表明 一个两点之间的可视化测试,

SetRay 表明 是否有其他物体 与 Ray 进行相交)

There are two methods that initialize VisibilityTesters. The first of them, Visibility
Tester::SetSegment(), indicates that the visibility test is to be done between two points
in the scene.
In addition to the two points, it takes “epsilon” values to offset the ray’s
starting point and ending point, respectively.

The other initialization method, VisibilityTester::SetRay(), indicates that the test
should indicate whether there is any object along a given direction.
This variant is useful
for computing shadows from directional lights.

 

2. 

bool VisibilityTester::Unoccluded(const Scene *scene) const {
    return !scene->IntersectP(r);
}

作用:

(其实这个就是判断 两点之间是否可视,或者ray方向是否与一个物体方法碰撞)

The next pair of methods trace the appropriate ray. The first one, VisibilityTester::
Unoccluded() traces the shadow ray and returns a Boolean result. Some ray tracers
include a facility for casting colored shadows from partially transparent objects and
would return a spectrum from a method like this. pbrt does not include this facility
explicitly, since those systems typically implement it with a nonphysical hack. Thus, the
VisibilityTester::Unoccluded() method here returns a Boolean.
Scenes where illumination
passes through a transparent object should be rendered with an integrator that
supports this kind of effect, like the PhotonIntegrator described in Section 15.6.

 

 

3. 

Spectrum VisibilityTester::Transmittance(const Scene *scene,
        const Renderer *renderer, const Sample *sample,
        RNG &rng, MemoryArena &arena) const {
    return renderer->Transmittance(scene, RayDifferential(r), sample,
                                   rng, arena);
}

作用:

(返回经过  participating media ,还剩下百分之多少的 illumination)

VisibilityTester::Transmittance() determines the fraction of illumination from the
light to the point that is not extinguished(灭绝) by participating media in the scene. If the scene
has no participating media, this method returns a constant spectral value of one.

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值