<p>Yes, this is to be expected. The difference between your two images is the difference between using and not using importance sampling.</p>

<p>The first image shows noticeably more noise than the second. This is because instead of biasing the hemisphere samples towards the normal by using cosine weighting, the code instead samples uniformly over the hemisphere and then gives less reflected light to rays nearer to perpendicular to the normal. Note that since this uses the dot product, this is also cosine weighting:</p>

<p>$$A\cdot B=\|A\|\|B\|\cos{\theta}$$</p>

<p>It's just weighting the contribution of each ray, rather than weighting the number of rays in each direction.</p>

<p>The second image is less noisy because it doesn't waste many samples on near-perpendicular rays which contribute very little to the image. The image will still converge to the same result given enough samples - the approach taken in the second image will just get there much sooner.</p>

<p>The effect in both cases is the same:</p>

<ul>
<li><strong>Approach 1</strong>: The weighting is applied to the amount of light reflected per ray, resulting in many of the rays carrying very little contribution.</li>
<li><strong>Approach 2</strong>: Every ray is given the same weight, but fewer of them are used in the directions associated with little contribution.</li>
</ul>

<p>The long term sum is the same either way, but approach 1 involves many rays with negligible contribution, that still require just as much calculation as any other ray, thus wasting most of the calculation time.</p>

<hr>

<p>Note that even with this speed up, the convergence will still be <em>very</em> slow for scenes with small, bright lights, or if there are parts of the scene accessible only by narrow paths. Generally, any scene where there are regions for which only a narrow range of angles contribute most of the light.</p>

CC BY-SA 3.0
2016-09-09T20:39:49.030Z
2016-09-11T16:47:02.643Z
2016-09-11T16:47:02.643Z
trichoplax is on Codidact now
<p>Without explicit light sampling, I'd expect very slow convergence.</p>

<p>Any path that doesn't happen to hit the light source before being terminated will be useless (contributes zero). Since you have a small light source, the vast majority of paths will not hit it. It would be interesting to add some statistics to your tracer to see how many paths return zero vs nonzero. I'd guess you'll find something like 99–99.9% of them are zero, so you're only getting one useful sample out of every 100–1000 or so paths traced.</p>

<p>Naive path tracing is more reasonable with e.g. a sky light, which almost every path can be expected to hit.</p>

CC BY-SA 4.0
2019-02-15T10:08:15.197Z
What is *explicit light sampling* and *sky light*? https://computergraphics.stackexchange.com/questions/8596/how-to-implement-explicit-light-sampling-when-implementing-path-tracing
zwcloud
CC BY-SA 3.0
2016-09-09T17:23:15.240Z
2016-09-09T17:23:15.240Z
Nathan Reed
<p>I have a naive diffuse/emissive material path tracer implementation (pinhole camera) and am seeing it take a very large number of samples per pixel to converge - like probably in the millions - and was wondering if that was normal for "naive" path tracer implementations?</p>

<p>Here is 10,000 samples per pixel:
<a href="https://i.sstatic.net/Il8Lw.png" rel="noreferrer"><img src="https://i.sstatic.net/Il8Lw.png" alt="enter image description here"></a></p>

<p>And here's a 10,000spp image using cosine weighted hemisphere samples as comparison:
<a href="https://i.sstatic.net/bJOV7.png" rel="noreferrer"><img src="https://i.sstatic.net/bJOV7.png" alt="enter image description here"></a></p>

<p>For each pixel I do this:</p>

<ol>
<li>Cast a ray out into the scene for the pixel (starting at near plane, of the direction of the camera to the pixel's location on the near plane).</li>
<li>When an object is hit, I calculate a uniform random direction in the hemisphere defined by the normal and continue.</li>
<li>At each level, i return emissive + (2 * Dot(normal, bounceRayDir) * ColorFromBounceRay * DiffuseColor/pi)</li>
<li>If nothing is hit by a bounced ray, i return black.</li>
<li>I'm working with 3 floating point color channels, where the intent is that 0-1 corresponds to 0-255 in the final output uint8 per color channel.</li>
<li>I allow 5 bounces max.</li>
</ol>

<p>After averaging all the samples for the pixel, I do this to convert it from HDR to LDR:</p>

<ol>
<li>For each color channel i do gamma correction: channel = powf(channel, 1.0f /2.2f)</li>
<li>I then multiply the channel value by 255, clamp it from 0-255 and cast it to uint8 for the final pixel color.</li>
</ol>

<p>The source code can be seen here in the gist below.  It includes windows.h for bitmap headers, but otherwise has no non standard headers, and no library dependencies:
<a href="https://gist.github.com/anonymous/0dc9f7f5abf15f8fdb9aa84ecfcf67d5" rel="noreferrer">https://gist.github.com/anonymous/0dc9f7f5abf15f8fdb9aa84ecfcf67d5</a></p>

CC BY-SA 3.0
2016-09-09T14:41:11.993Z
[WebGL Path Tracing demo](http://madebyevan.com/webgl-path-tracing/) is also not very fast converging for diffuse reflectors. So yours is at least not the only one with such a property.
Ruslan
<pathtracing>
Is it expected that a naive path tracer takes many, many samples to converge?
Alan Wolfe
# Is it expected that a naive path tracer takes many, many samples to converge?

(Asked by: username_0 on 2016-09-09)

I have a naive diffuse/emissive material path tracer implementation (pinhole camera) and am seeing it take a very large number of samples per pixel to converge - like probably in the millions - and was wondering if that was normal for "naive" path tracer implementations?

Here is 10,000 samples per pixel:
[![enter image description here](https://i.sstatic.net/Il8Lw.png)](https://i.sstatic.net/Il8Lw.png)

And here's a 10,000spp image using cosine weighted hemisphere samples as comparison:
[![enter image description here](https://i.sstatic.net/bJOV7.png)](https://i.sstatic.net/bJOV7.png)

For each pixel I do this:

1. Cast a ray out into the scene for the pixel (starting at near plane, of the direction of the camera to the pixel's location on the near plane).
2. When an object is hit, I calculate a uniform random direction in the hemisphere defined by the normal and continue.
3. At each level, i return emissive + (2 \* Dot(normal, bounceRayDir) \* ColorFromBounceRay \* DiffuseColor/pi)
4. If nothing is hit by a bounced ray, i return black.
5. I'm working with 3 floating point color channels, where the intent is that 0-1 corresponds to 0-255 in the final output uint8 per color channel.
6. I allow 5 bounces max.

After averaging all the samples for the pixel, I do this to convert it from HDR to LDR:

1. For each color channel i do gamma correction: channel = powf(channel, 1.0f /2.2f)
2. I then multiply the channel value by 255, clamp it from 0-255 and cast it to uint8 for the final pixel color.

The source code can be seen here in the gist below. It includes windows.h for bitmap headers, but otherwise has no non standard headers, and no library dependencies:
<https://gist.github.com/anonymous/0dc9f7f5abf15f8fdb9aa84ecfcf67d5>

**Tags:** pathtracing

> **Comments:**
> **username_1**: [WebGL Path Tracing demo](http://madebyevan.com/webgl-path-tracing/) is also not very fast converging for diffuse reflectors. So yours is at least not the only one with such a property.  

---

## 2 answers

### Answer by username_3 on 2016-09-09. Score: 11 | Accepted answer

Without explicit light sampling, I'd expect very slow convergence.

Any path that doesn't happen to hit the light source before being terminated will be useless (contributes zero). Since you have a small light source, the vast majority of paths will not hit it. It would be interesting to add some statistics to your tracer to see how many paths return zero vs nonzero. I'd guess you'll find something like 99–99.9% of them are zero, so you're only getting one useful sample out of every 100–1000 or so paths traced.

Naive path tracing is more reasonable with e.g. a sky light, which almost every path can be expected to hit.

> **Comments:**
> **username_4**: What is *explicit light sampling* and *sky light*? https://computergraphics.stackexchange.com/questions/8596/how-to-implement-explicit-light-sampling-when-implementing-path-tracing  

---

### Answer by username_2 on 2016-09-09. Score: 6

Yes, this is to be expected. The difference between your two images is the difference between using and not using importance sampling.

The first image shows noticeably more noise than the second. This is because instead of biasing the hemisphere samples towards the normal by using cosine weighting, the code instead samples uniformly over the hemisphere and then gives less reflected light to rays nearer to perpendicular to the normal. Note that since this uses the dot product, this is also cosine weighting:

$$A\cdot B=\|A\|\|B\|\cos{\theta}$$

It's just weighting the contribution of each ray, rather than weighting the number of rays in each direction.

The second image is less noisy because it doesn't waste many samples on near-perpendicular rays which contribute very little to the image. The image will still converge to the same result given enough samples - the approach taken in the second image will just get there much sooner.

The effect in both cases is the same:

* **Approach 1**: The weighting is applied to the amount of light reflected per ray, resulting in many of the rays carrying very little contribution.
* **Approach 2**: Every ray is given the same weight, but fewer of them are used in the directions associated with little contribution.

The long term sum is the same either way, but approach 1 involves many rays with negligible contribution, that still require just as much calculation as any other ray, thus wasting most of the calculation time.

---

Note that even with this speed up, the convergence will still be *very* slow for scenes with small, bright lights, or if there are parts of the scene accessible only by narrow paths. Generally, any scene where there are regions for which only a narrow range of angles contribute most of the light.


---

