chunky-dev / chunky

A path tracer to create realistic images of your Minecraft worlds.
https://chunky-dev.github.io/docs
GNU General Public License v3.0
643 stars 76 forks source link

New accurate sun sampling method #1604

Closed JustinTimeCuber closed 6 months ago

JustinTimeCuber commented 1 year ago

The problem

Chunky currently has two sun sampling methods: FAST, which converges quickly but does not provide accurate visuals in all scenarios, and HIGH_QUALITY, which from my testing just seems to be a middleground between FAST and OFF - depending on the ratio between Sun luminosity and Sunlight intensity, HIGH_QUALITY sun sampling can be made "wrong but fast" or "noisy but accurate" or somewhere in-between: image image image

Besides the fact that having two separate controls for sun brightness is confusing (and probably should be looked into in the future), this doesn't really solve the issue of FAST sun sampling being inaccurate, because in order to get accurate results, you're not really getting reduced noise anyway.

Overview of the new algorithm

The idea here is to do the sun sampling as a direct part of calculating diffuse reflections, rather than as an additional ray that has to be combined with the actual diffuse ray to give a result. Without sun sampling, diffuse scattering looks something like this. Depending on the exact settings (sun size, altitude) as well as relative angle of the surface, and ignoring any obstructions, there is a roughly 1 in 1000 chance of a direct sun hit per diffuse reflection: image However, what if we biased the sample, and then corrected for it? That is, we alter the distribution to be something like this: image Then, if the ray is in the 10%, we divide its contribution by 100 (and if it is in the 90%, we multiply it by 1.11). This corrects for the bias introduced by changing the distribution. Another way to think of it is that instead of getting 1 ray of very bright sunlight per 1000 diffuse reflections, we will get 100 relatively dim ones. And notably, although we are technically getting fewer samples from the rest of the scene (and slightly amplifying those samples accordingly), the difference is rather small, in this case about 10%. And this value is configurable, so even a chance of 1% for sun sampling can improve sunlight convergence by a factor of 10 while having a negligible (0.9%) loss in quality for other light sources. This approach is a form of importance sampling.

Noise reduction examples

Generally, noise is reduced in direct and diffusely-reflected sunlight, but not in other less common effects such as specularly-reflected sunlight and caustics. Here is a scene with only diffuse surfaces, rendered with SS off (baseline), SS FAST, and my algorithm at 1%, 10%, and 50% sample chances: image image image image image A few things to note here, besides the general reduction in noise:

Here is a scene that includes both diffuse and specular reflections: image image image image image

Correctness

To ensure that this algorithm works as expected, I have tested it in a few complex scenes at high SPP, in comparison to sun sampling off: image image I was hoping to see caustics in this render, since I had sunlight passing through water. It's possible that they are there but extremely subtle. However, just to ensure that caustics are working as expected, I ran this render: image image

Things to consider before merging

JustinTimeCuber commented 1 year ago

With the latest changes: image Before: image Definitely an improvement in terms of speckles. Not exactly sure why they aren't completely eliminated, but I'll think about it more.

JustinTimeCuber commented 1 year ago

More analysis that should hopefully be pretty convincing that this is unbiased:

10 million samples, with SS=DIFFUSE SS-Diffuse

SS=OFF: SS-Off

Difference (zero difference mapped to 127 RGB value) difference image

leMaik commented 10 months ago

Looks good to me so far and the results are amazing! This PR needs a rebase now.

Some more thoughts:

JustinTimeCuber commented 10 months ago

I have fixed the merge conflict and changed the name to IMPORTANCE as you suggested.

leMaik commented 6 months ago

Great work! :clap: Especially all the renders and the description of the algorithm! :tada: