<p>I'm working on a monte carlo path traced application. To make life easier I've only been looking at Lambertian surfaces with LR = 1. I've implemented multiple importance sampling, with one sample for NEE and one for cosine weighting. The trouble I've come into is that the sampling from NEE has a tiny weight and even though the sampling correctly hits the light source very frequently, because of the low weight (e.g. 0.05 to 0.999 for cosine weight), the results are essentially discarded and the light has very low effect. I'm using the power heuristic for weighting, and after doing some cancellation and removing redundant terms (e.g. only 1 sample each, and LR = 1) this is the result:</p>
<p><span class="math-container">$$
\sum_{D\,\in\,distributions}
    \sum_{I\,\in\,S(D)}
        \frac{L_i(P, I)\,pdf(D, I)\,dot(N, I)}{\pi\,(pdf(NEE, I)^2 + pdf(cosine, I)^2)}
$$</span></p>
<p>In this case I'm using a single sphere light uniformly cone sampled according to PBRT, so this is <span class="math-container">$cos\,\theta = (1 - \xi) + \xi\,cos\,\theta\,$</span> for sampling and a PDF of <span class="math-container">$\frac{1}{2\pi (1 - cos\, \theta max)}$</span> for NEE samples, and <span class="math-container">$cos \,\theta = \sqrt{\xi}$</span> with PDF <span class="math-container">$\frac{cos \theta}{\pi}$</span> for cosine weighting. When computing the PDF for NEE samples, I check if the sample is actually within the light source's cone, and if not, set the weight as 0 as this sample can't be generated with the NEE distribution.</p>
<p>The basic issue comes when <span class="math-container">$\theta$</span> is quite small, so the NEE PDF works out as quite high for any given sample; I picked a pixel where this was 5.4. This blows out the bottom term so that the final weight is very low. Meanwhile cosine samples have a value of zero so they maintain a high weight. Or in other words, the NEE samples seem very likely just because they can be picked by the NEE distribution at all, whereas cosine samples seem way more unlikely than they really are. This seems to make MIS weight them very highly.</p>
<p>If I had to guess, I'd say the issue is that the PDF for the cone is based on the assumption you are picking a sample from just the cone, which I'm combining with a PDF for the whole hemisphere, so the domains are wrong?</p>
<p>I tried adding a fixed bias for NEE samples, which improves the situation, but only a little; when the bias is big compared to the PDF the result looks good, but as the angle gets smaller, the PDF dominates the bias, so it only works out to some fixed distance.</p>
<p>Any suggestions on fixing my weights so that NEE samples are weighted correctly?</p>

CC BY-SA 4.0
2024-09-30T04:58:25.030Z
The NEE PDF is normally: `1 / emitter_pdf * geometry_term`, where `1 / emitter_pdf` is usually the inverse area of the emitter, and `geometry_term` converts the area product measure to the solid angle measure (at the shading point). So I really don't understand the NEE PDF of yours (and even, the light sampling method), since I can find neither of them. Maybe you can share the link to your code to clarify this?
Enigmatisms
CC BY-SA 4.0
2024-09-30T11:58:30.257Z
I used the method and PDF given by PBRT, https://pbr-book.org/4ed/Sampling_Algorithms/Sampling_Multidimensional_Functions#SamplingWithinaCone. This is the relevant HLSL https://github.com/DeadMG/dx12/blob/master/Renderer.Direct3D12/Shaders/Raytrace/Sampling.hlsl; for efficiency I'm precomputing all terms other than $L_i$. Currently there's only ever one LightSource which is a spherical light.
Puppy
CC BY-SA 4.0
2024-09-30T14:01:13.970Z
Did you forget to normalize the nee pdf by the sum of all lights' power? Line171: `total += light.Power * (1.0f / (2.0f * PI * (1.0f - cos(angle))));`, you return `total` without normalizing it, `light.Power` should have been `light.Power / sum(lights[...].Power)` to make total a valid PDF.
Enigmatisms
CC BY-SA 4.0
2024-09-30T15:51:54.990Z
There's a separate normalization step for the lights and their powers that occurs first, to adjust each light's power for distance and such. Additionally in this test there's only one light with a power of 1. I think the issue probably arises from what you have said above that I should not be using the cone sample PDF as the NEE PDF?
Puppy
CC BY-SA 4.0
2024-10-01T16:41:48.973Z
After some experimentation, angle / PI seems to work well, so I'll just stick with that even though I feel moderately sure it's probably not exactly correct. I'll probably leave the question open for any definitely correct answers.
Puppy
<pathtracing><monte-carlo>
NEE samples underweighted with MIS
Puppy
# NEE samples underweighted with MIS

(Asked by: username_0 on 2024-09-28)

I'm working on a monte carlo path traced application. To make life easier I've only been looking at Lambertian surfaces with LR = 1. I've implemented multiple importance sampling, with one sample for NEE and one for cosine weighting. The trouble I've come into is that the sampling from NEE has a tiny weight and even though the sampling correctly hits the light source very frequently, because of the low weight (e.g. 0.05 to 0.999 for cosine weight), the results are essentially discarded and the light has very low effect. I'm using the power heuristic for weighting, and after doing some cancellation and removing redundant terms (e.g. only 1 sample each, and LR = 1) this is the result:

$$
\sum\_{D\,\in\,distributions}
\sum\_{I\,\in\,S(D)}
\frac{L\_i(P, I)\,pdf(D, I)\,dot(N, I)}{\pi\,(pdf(NEE, I)^2 + pdf(cosine, I)^2)}
$$

In this case I'm using a single sphere light uniformly cone sampled according to PBRT, so this is $cos\,\theta = (1 - \xi) + \xi\,cos\,\theta\,$ for sampling and a PDF of $\frac{1}{2\pi (1 - cos\, \theta max)}$ for NEE samples, and $cos \,\theta = \sqrt{\xi}$ with PDF $\frac{cos \theta}{\pi}$ for cosine weighting. When computing the PDF for NEE samples, I check if the sample is actually within the light source's cone, and if not, set the weight as 0 as this sample can't be generated with the NEE distribution.

The basic issue comes when $\theta$ is quite small, so the NEE PDF works out as quite high for any given sample; I picked a pixel where this was 5.4. This blows out the bottom term so that the final weight is very low. Meanwhile cosine samples have a value of zero so they maintain a high weight. Or in other words, the NEE samples seem very likely just because they can be picked by the NEE distribution at all, whereas cosine samples seem way more unlikely than they really are. This seems to make MIS weight them very highly.

If I had to guess, I'd say the issue is that the PDF for the cone is based on the assumption you are picking a sample from just the cone, which I'm combining with a PDF for the whole hemisphere, so the domains are wrong?

I tried adding a fixed bias for NEE samples, which improves the situation, but only a little; when the bias is big compared to the PDF the result looks good, but as the angle gets smaller, the PDF dominates the bias, so it only works out to some fixed distance.

Any suggestions on fixing my weights so that NEE samples are weighted correctly?

**Tags:** pathtracing, monte-carlo

> **Comments:**
> **username_1**: The NEE PDF is normally: `1 / emitter_pdf * geometry_term`, where `1 / emitter_pdf` is usually the inverse area of the emitter, and `geometry_term` converts the area product measure to the solid angle measure (at the shading point). So I really don't understand the NEE PDF of yours (and even, the light sampling method), since I can find neither of them. Maybe you can share the link to your code to clarify this?  
> **username_0**: I used the method and PDF given by PBRT, https://pbr-book.org/4ed/Sampling_Algorithms/Sampling_Multidimensional_Functions#SamplingWithinaCone. This is the relevant HLSL https://github.com/DeadMG/dx12/blob/master/Renderer.Direct3D12/Shaders/Raytrace/Sampling.hlsl; for efficiency I'm precomputing all terms other than $L_i$. Currently there's only ever one LightSource which is a spherical light.  
> **username_1**: Did you forget to normalize the nee pdf by the sum of all lights' power? Line171: `total += light.Power * (1.0f / (2.0f * PI * (1.0f - cos(angle))));`, you return `total` without normalizing it, `light.Power` should have been `light.Power / sum(lights[...].Power)` to make total a valid PDF.  
> **username_0**: There's a separate normalization step for the lights and their powers that occurs first, to adjust each light's power for distance and such. Additionally in this test there's only one light with a power of 1. I think the issue probably arises from what you have said above that I should not be using the cone sample PDF as the NEE PDF?  
> **username_0**: After some experimentation, angle / PI seems to work well, so I'll just stick with that even though I feel moderately sure it's probably not exactly correct. I'll probably leave the question open for any definitely correct answers.  

---

## 0 answers

