Skip to content

Book 3, 12.5; unnecessary per-term multiplication instead of single division in pdf_value of hittable_list #1746

Description

@Lethargy2718

This is the current implementation of hittable_list::pdf_value in listing 56, where each object's pdf_value is multiplied by weight:

double pdf_value(const point3& origin, const vec3& direction) const override {
    auto weight = 1.0 / objects.size();
    auto sum = 0.0;

    for (const auto& object : objects)
        sum += weight * object->pdf_value(origin, direction);

    return sum;
}

However, since weight is constant across all terms, the multiplication can be factored out of the loop and applied once to the final sum instead, replacing N multiplications with a single division per call:

double pdf_value(const point3& origin, const vec3& direction) const override {
    auto sum = 0.0;

    for (const auto& object : objects)
        sum += object->pdf_value(origin, direction);

    return sum / objects.size();
}

This is a purely arithmetic change, and produces the same result, aside from possible negligible floating-point differences.

Currently, pdf_value is called on every sample and bounce of a diffuse ray when there is a hittable_list of sampled objects. For scenes with many lights/hittables, this adds a lot of unnecessary CPU cycles.

This change removes N-1 redundant multiplications per call, which leads to a shorter execution time.

It may become less readable, but that could easily be fixed by splitting it into two lines:

auto weight = 1.0 / objects.size();
return sum * weight;

I'm prepared to submit the PR for this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions