I'm trying to learn about raytracing by implementing things in Python 3. I know this is always going to be slower than something like C++, and I know the speed could also be improved by using GPU raytracing, but for this question I'm not looking for general ways of speeding up, but specifically ways of reducing the number of samples required, which will then be useful for any language I may work with in future.
I have a partly formed idea which I'd like to work on, but first I wanted to run this past the experts to see if this is a pre-existing technique so I don't repeat work that has already been done.
I've searched for "sampling solid angle" and "voronoi sphere sampling" but I can't see any sign of prior work. I'll describe my idea in case it goes by a name I can't think of.
Example image
This is an image of three spheres on a plane (which is actually a very large sphere). One is emissive, one is reflective, and one is matt (as is the floor). Sampling is adaptive so that pixels that quickly reach a stable colour do not take up much time. I limit the total number of samples per pixel to avoid the rendering continuing for too long. Even allowed to run overnight, the resulting image is very grainy, and experimenting with smaller images suggests this size image (1366 by 768) would take weeks to converge with my current approach.
My idea: concentrating samples along colour boundaries
I'd like to be able to concentrate samples where they are needed, and to do this adaptively based on previous samples for the same intersection point or pixel. This will give an unknown bias in the distribution of samples, which means taking the average of the samples will give an inaccurate result. Instead I would like to consider the size of the voronoi cell on the surface of the unit hemisphere centred on the point of intersection (for sampling light incident at a point on a matt surface) or on the surface of a small circle (for sampling around a pixel).
Assume that all points within that voronoi cell are receiving rays of the same colour as the centre of the voronoi cell. Now an estimate of the average colour can be obtained by weighting according to the area of each voronoi cell. Choosing new samples on the boundary between the two voronoi cells with the greatest difference in colour leads to an improvement in the estimate without needing to sample the entire hemisphere. Samples should end up more densely concentrated in areas of higher colour gradient. Areas of flat colour should end up being ignored once they have a few points near their boundary.
The extra complication is that in both cases (sampling from a point on a matt surface, or sampling over a circle around a pixel centre) the simplified approach I have described is roughly equivalent to a large number of samples distributed uniformly. To make this work I would need to be able to bias the average by both the voronoi cell areas and the required distribution (cosine around the surface normal for a matt surface or gaussian around a pixel centre).
So I have some more thinking to do before I could test this idea, but I wanted to check first if this has either already been done, or already ruled out as unworkable.