<p>Actually,shape-&gt;Sample(ref, u, pdf) returns the pdf in solid angle measure.The sample function in sample is actually this.</p>
<pre><code>Interaction Shape::Sample(const Interaction &amp;ref, const Point2f &amp;u,
                          Float *pdf) const {
    Interaction intr = Sample(u, pdf);
    Vector3f wi = intr.p - ref.p;
    if (wi.LengthSquared() == 0)
        *pdf = 0;
    else {
        wi = Normalize(wi);
        // Convert from area measure, as returned by the Sample() call
        // above, to solid angle measure.
        *pdf *= DistanceSquared(ref.p, intr.p) / AbsDot(intr.n, -wi);
        if (std::isinf(*pdf)) *pdf = 0.f;
    }
    return intr;
}
</code></pre>
<p>This function will call virtual function sample(    <code>virtual Interaction Sample(const Point2f &amp;u, Float *pdf) const = 0;</code>) ,which is also the function in your triangle example.So the virtual function computes pdf in area measure,and the non-virtual function comverts pdf to the solid angle measute</p>

CC BY-SA 4.0
2023-03-15T13:05:46.023Z
Thanks, I think you are right.
Enigmatisms
CC BY-SA 4.0
2023-03-11T12:39:09.187Z
2023-03-11T12:39:09.187Z
袁军平
<p>When using MIS, we always want to express the PDF value in a unified measure in order not to render the ratio between them meaningless. Yet when I read through chapter 16 of PBR-book, I got confused by how to choose the correct measure.</p>
<p>First, I see that in <a href="https://www.pbr-book.org/3ed-2018/Light_Transport_III_Bidirectional_Methods/Bidirectional_Path_Tracing#SubpathConnections" rel="nofollow noreferrer">subpath connection</a> <code>s == 1</code> (only one vertex on the light path is used) case, we first need to sample (sort of like) direct component if the light vertex is connectible:</p>
<pre class="lang-cpp prettyprint-override"><code>Spectrum lightWeight = light-&gt;Sample_Li(pt.GetInteraction(), sampler.Get2D(),
                                                   &amp;wi, &amp;pdf, &amp;vis);
</code></pre>
<p>Here, <code>pdf</code> is computed in <code>Sample_Li</code> method, and it is later used for</p>
<pre class="lang-cpp prettyprint-override"><code>sampled = Vertex::CreateLight(ei, lightWeight / (pdf * lightPdf), 0);
</code></pre>
<p>Typical MC estimation step, right? In unidirectional path tracing, <code>pdf * lightPdf</code> is defined in solid angle measure, so after sampling a vertex on an area source (with <code>pdf = 1. / area</code>), we should convert the pdf to solid angle measure using <code>length^2 / cos</code>. However, in <code>pbrt-v3</code>, <code>Sample_Li</code> seems to return pdf defined in area measure. Here I quote the code from <code>lights/diffusive.cpp</code> in <code>pbrt-v3</code>:</p>
<pre class="lang-cpp prettyprint-override"><code>Interaction pShape = shape-&gt;Sample(ref, u, pdf);
</code></pre>
<p>And the sample method (for example, if the shape is triangle):</p>
<pre class="lang-cpp prettyprint-override"><code>Interaction Triangle::Sample(const Point2f &amp;u, Float *pdf) const {
    /** ... */
    *pdf = 1 / Area();
    /** ... */
}
</code></pre>
<p>To me, it doesn't seem like the conversion is done. To make it even more confusing, pbr-book says:</p>
<blockquote>
<p>Like Sample_Li(), the PDF value this method returns is defined with respect to <strong>solid angle</strong> at the reference point. <a href="https://www.pbr-book.org/3ed-2018/Light_Transport_III_Bidirectional_Methods/The_Path-Space_Measurement_Equation#Camera::Sample_Wi" rel="nofollow noreferrer">[reference]</a></p>
</blockquote>
<p>And yes, <code>Sample_Wi()</code> does return pdf defined in solid angle measure:</p>
<pre class="lang-cpp prettyprint-override"><code>// pdf calculation defined in Sample_Wi
*pdf = (dist * dist) / (AbsDot(lensIntr.n, *wi) * lensArea);
</code></pre>
<p>Yet, <code>lightWeight</code> seems to be divided by pdf returned by <code>Sample_Li()</code>, which seems to be  defined in area measure. This is baffling me a lot? Did misunderstand anything here? Is this some kind of weird mechanism in BDPT?</p>

<pathtracing><pbrt><pdf>
Confusion about PDF defined in solid angle / area measure
Enigmatisms
# Confusion about PDF defined in solid angle / area measure

(Asked by: username_0 on 2023-02-25)

When using MIS, we always want to express the PDF value in a unified measure in order not to render the ratio between them meaningless. Yet when I read through chapter 16 of PBR-book, I got confused by how to choose the correct measure.

First, I see that in [subpath connection](https://www.pbr-book.org/3ed-2018/Light_Transport_III_Bidirectional_Methods/Bidirectional_Path_Tracing#SubpathConnections) `s == 1` (only one vertex on the light path is used) case, we first need to sample (sort of like) direct component if the light vertex is connectible:

```cpp
Spectrum lightWeight = light->Sample_Li(pt.GetInteraction(), sampler.Get2D(),
                                                   &wi, &pdf, &vis);

```

Here, `pdf` is computed in `Sample_Li` method, and it is later used for

```cpp
sampled = Vertex::CreateLight(ei, lightWeight / (pdf * lightPdf), 0);

```

Typical MC estimation step, right? In unidirectional path tracing, `pdf * lightPdf` is defined in solid angle measure, so after sampling a vertex on an area source (with `pdf = 1. / area`), we should convert the pdf to solid angle measure using `length^2 / cos`. However, in `pbrt-v3`, `Sample_Li` seems to return pdf defined in area measure. Here I quote the code from `lights/diffusive.cpp` in `pbrt-v3`:

```cpp
Interaction pShape = shape->Sample(ref, u, pdf);

```

And the sample method (for example, if the shape is triangle):

```cpp
Interaction Triangle::Sample(const Point2f &u, Float *pdf) const {
    /** ... */
    *pdf = 1 / Area();
    /** ... */
}

```

To me, it doesn't seem like the conversion is done. To make it even more confusing, pbr-book says:

> Like Sample\_Li(), the PDF value this method returns is defined with respect to **solid angle** at the reference point. [[reference]](https://www.pbr-book.org/3ed-2018/Light_Transport_III_Bidirectional_Methods/The_Path-Space_Measurement_Equation#Camera::Sample_Wi)

And yes, `Sample_Wi()` does return pdf defined in solid angle measure:

```cpp
// pdf calculation defined in Sample_Wi
*pdf = (dist * dist) / (AbsDot(lensIntr.n, *wi) * lensArea);

```

Yet, `lightWeight` seems to be divided by pdf returned by `Sample_Li()`, which seems to be defined in area measure. This is baffling me a lot? Did misunderstand anything here? Is this some kind of weird mechanism in BDPT?

**Tags:** pathtracing, pbrt, pdf


---

## 1 answers

### Answer by username_1 on 2023-03-11. Score: 2 | Accepted answer

Actually,shape->Sample(ref, u, pdf) returns the pdf in solid angle measure.The sample function in sample is actually this.

```
Interaction Shape::Sample(const Interaction &ref, const Point2f &u,
                          Float *pdf) const {
    Interaction intr = Sample(u, pdf);
    Vector3f wi = intr.p - ref.p;
    if (wi.LengthSquared() == 0)
        *pdf = 0;
    else {
        wi = Normalize(wi);
        // Convert from area measure, as returned by the Sample() call
        // above, to solid angle measure.
        *pdf *= DistanceSquared(ref.p, intr.p) / AbsDot(intr.n, -wi);
        if (std::isinf(*pdf)) *pdf = 0.f;
    }
    return intr;
}

```

This function will call virtual function sample( `virtual Interaction Sample(const Point2f &u, Float *pdf) const = 0;`) ,which is also the function in your triangle example.So the virtual function computes pdf in area measure,and the non-virtual function comverts pdf to the solid angle measute

> **Comments:**
> **username_0**: Thanks, I think you are right.  

---

