PBRT_V2 总结记录 ShapeSet

class ShapeSet {
public:
    // ShapeSet Public Methods
    ShapeSet(const Reference<Shape> &s);
    float Area() const { return sumArea; }
    ~ShapeSet();
    Point Sample(const Point &p, const LightSample &ls, Normal *Ns) const;
    Point Sample(const LightSample &ls, Normal *Ns) const;
    float Pdf(const Point &p, const Vector &wi) const;
    float Pdf(const Point &p) const;
private:
    // ShapeSet Private Data
    vector<Reference<Shape> > shapes;
    float sumArea;
    vector<float> areas;
    Distribution1D *areaDistribution;
};

类的作用:

(ShapeSet 保存 Shape 列表,主要用于Area Light,作为Area)

A ShapeSet is allocated in the DiffuseAreaLight constructor to store the shape or shapes
that define the light. It conforms(符合) to the Shape interface so that the light source can just
store a single Shape pointer, regardless of how many shapes are in the light source. The
ShapeSet thus must implement the Shape’s sampling routines.

1. 构造函数


// ShapeSet Method Definitions
ShapeSet::ShapeSet(const Reference<Shape> &s) {
    vector<Reference<Shape> > todo;
    todo.push_back(s);
    while (todo.size()) {
        Reference<Shape> sh = todo.back();
        todo.pop_back();
        if (sh->CanIntersect())
            shapes.push_back(sh);
        else
            sh->Refine(todo);
    }
    if (shapes.size() > 64)
        Warning("Area light geometry turned into %d shapes; "
            "may be very inefficient.", (int)shapes.size());

    // Compute total area of shapes in _ShapeSet_ and area CDF
    sumArea = 0.f;
    for (uint32_t i = 0; i < shapes.size(); ++i) {
        float a = shapes[i]->Area();
        areas.push_back(a);
        sumArea += a;
    }
    areaDistribution = new Distribution1D(&areas[0], areas.size());
}

(在构造函数计算所有的shape的sumArea, 通过每一个Shape 的Area计算 一个Distribution1D , 这个Distribution1D  用于之后 随机选择哪个 Shape 用的)

In order to be able to uniformly sample the overall shape by surface area, we would like
to sample individual shapes in the collection with probability based on the ratio of their
area to the total area of all of the shapes.
Therefore, the ShapeSet constructor uses the

Distribution1D to store a discrete CDF for sampling each shape according to individual
probabilities given by this ratio.

2. Sample

Point ShapeSet::Sample(const Point &p, const LightSample &ls,
                       Normal *Ns) const {
    int sn = areaDistribution->SampleDiscrete(ls.uComponent, NULL);
    return shapes[sn]->Sample(p, ls.uPos[0], ls.uPos[1], Ns);
}


Point ShapeSet::Sample(const LightSample &ls, Normal *Ns) const {
    int sn = areaDistribution->SampleDiscrete(ls.uComponent, NULL);
    return shapes[sn]->Sample(ls.uPos[0], ls.uPos[1], Ns);
}

作用:

先利用LightSample.uComponent 来 随机 选择 一个 Shape,然后LightSample.uPos 直接 调用这个 Shape 的对应的 Sample 方法。

3. Pdf

float ShapeSet::Pdf(const Point &p, const Vector &wi) const {
    float pdf = 0.f;
    for (uint32_t i = 0; i < shapes.size(); ++i)
        pdf += areas[i] * shapes[i]->Pdf(p, wi);
    return pdf / sumArea;
}

作用:

(这里计算 pdf,主要还会考虑到 对应shape的Area,用 Area/sumArea 作为权值,其实个人理解就是,点P对应所有Shape的可视区域面积 和 总面积的 比例)

To compute the value of the PDF, we just need to iterate over all of the Shapes and call
their Pdf() methods, taking the area-weighted average of their PDFs since shapes are
selected by area in ShapeSet::Sample().
Executing this method will be inefficient when
large numbers of lights are in the ShapeSet, due to the expense of evaluating the PDF
for each of them (recall that a ray–shape intersection is performed in the Shape::Pdf()

methods). The ShapeSet could therefore maintain a small acceleration structure here so
that it could avoid unnecessarily calling this method for the Shapes that the ray (p, ωi)
doesn’t intersect at all.

猜你喜欢

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