Is it expected that a naive path tracer takes many, many samples to converge? 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:


And here's a 10,000spp image using cosine weighted hemisphere samples as comparison:


For each pixel I do this:


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).
When an object is hit, I calculate a uniform random direction in the hemisphere defined by the normal and continue.
At each level, i return emissive + (2 * Dot(normal, bounceRayDir) * ColorFromBounceRay * DiffuseColor/pi)
If nothing is hit by a bounced ray, i return black.
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.
I allow 5 bounces max.


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


For each color channel i do gamma correction: channel = powf(channel, 1.0f /2.2f)
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
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.