Implementation for Bluenoise Dithered Sampling
Re: Implementation for Bluenoise Dithered Sampling
This is unidirectional path tracing with uniform random variables everywhere, 8 bounces, RR, MIS, NEE, Lambert BRDF.
Left side replaces uniform random variables with the tile. For subsequent pixels I shift the tile randomly over x and y, instead of adding an offset to each value.
Left side replaces uniform random variables with the tile. For subsequent pixels I shift the tile randomly over x and y, instead of adding an offset to each value.
Re: Implementation for Bluenoise Dithered Sampling
This is from one of my private projects where i included the masks some months ago, using 3 dimensions to compute SSAO, left with 64x64 tiled blue noise, right with 64x64 tiled white noise (but both using the same QMC set for the samples in each pixel then). For such a case it can make a really nice difference.
Better you leave here with your head still full of kitty cats and puppy dogs.

 Posts: 86
 Joined: Thu Apr 11, 2013 5:15 pm
Re: Implementation for Bluenoise Dithered Sampling
I was thinking of giving this technique a spin, and I had a couple of random thoughts.
1. The idea is basically to add the pixeldependent bluenoise shift to a pixelindependent random number, and subtract 1 if necessary to bring things in the range of [0, 1), right? But during tile generation, the algorithm would think of (for one dimension in both domain and range) a set of values like [0.0, 0.99, 0.0, 0.99, 0.0] to be "good", but [0.0, 0.01, 0.0, 0.01, 0.0] to be "bad", even though they have very similar effects on the result? Maybe some other definition of distance (e.g., sin(2 * pi * (ps  qs)) * 0.5 + 0.5 for one dimension) is more appropriate?
2. Generating highdimensional blue noise tiles is hard, but can you get a goodenough effect by just using multiple independent 1 and/or 2dimensional tiles, or even the same tile at a different sufficientlylarge offset per dimension?
1. The idea is basically to add the pixeldependent bluenoise shift to a pixelindependent random number, and subtract 1 if necessary to bring things in the range of [0, 1), right? But during tile generation, the algorithm would think of (for one dimension in both domain and range) a set of values like [0.0, 0.99, 0.0, 0.99, 0.0] to be "good", but [0.0, 0.01, 0.0, 0.01, 0.0] to be "bad", even though they have very similar effects on the result? Maybe some other definition of distance (e.g., sin(2 * pi * (ps  qs)) * 0.5 + 0.5 for one dimension) is more appropriate?
2. Generating highdimensional blue noise tiles is hard, but can you get a goodenough effect by just using multiple independent 1 and/or 2dimensional tiles, or even the same tile at a different sufficientlylarge offset per dimension?

 Posts: 86
 Joined: Thu Apr 11, 2013 5:15 pm
Re: Implementation for Bluenoise Dithered Sampling
OK, that makes no sense. I tried to jam a couple of ideas together without making sure that one didn't break the other.sin(2 * pi * (ps  qs)) * 0.5 + 0.5
Maybe c * (x  x * x), where x = ps  qs and c is some constant I haven't worked out yet.
Re: Implementation for Bluenoise Dithered Sampling
The idea ideas not adding a deterministic (bluenoise) number to a random number. In fact, the idea is to get rid of the randomness altogether  you use the deterministic number to post your pattern, instead of using a random number.
Regarding the (0, 0.99) vs (0, 0.01) issue, the answer is that it depends. If your 1D sampling domain is "wrapped", i.e. 0.99 and 0.01 are next to each other, then yes, you should ideally take this into account in the distance function when you construct the dither mask. If the domain is not wrapped, then doing so will be suboptimal, that is, you won't get the best blue noise distribution of the error in your image. So you may want to have two dither masks  one with wrapped values and one with nonwrapped.
In 2D you have the same thing, but with some combinations. A torus light source would benefit from a mask with values wrapped along both dimensions. For a disk light or for hemisphere sampling you would use a mask wrapped along one dimension only. For a rectangular light the optimal choice would be a nonwrapped mask.
For higher dimensions using independent (or independently screenspace shifted) masks use possible, but if there's a lot of variance along all dimensions, then you will get some white noise that might destroy/mask the blue noise from the dithering. So it's not optimal, but it's very practical. Generating higherdimensional blue noise masks is hard, because achieving high blue noise quality in high dimensions is hard in general.
Regarding the (0, 0.99) vs (0, 0.01) issue, the answer is that it depends. If your 1D sampling domain is "wrapped", i.e. 0.99 and 0.01 are next to each other, then yes, you should ideally take this into account in the distance function when you construct the dither mask. If the domain is not wrapped, then doing so will be suboptimal, that is, you won't get the best blue noise distribution of the error in your image. So you may want to have two dither masks  one with wrapped values and one with nonwrapped.
In 2D you have the same thing, but with some combinations. A torus light source would benefit from a mask with values wrapped along both dimensions. For a disk light or for hemisphere sampling you would use a mask wrapped along one dimension only. For a rectangular light the optimal choice would be a nonwrapped mask.
For higher dimensions using independent (or independently screenspace shifted) masks use possible, but if there's a lot of variance along all dimensions, then you will get some white noise that might destroy/mask the blue noise from the dithering. So it's not optimal, but it's very practical. Generating higherdimensional blue noise masks is hard, because achieving high blue noise quality in high dimensions is hard in general.
Click here. You'll thank me later.

 Posts: 86
 Joined: Thu Apr 11, 2013 5:15 pm
Re: Implementation for Bluenoise Dithered Sampling
Right, I was using "random" loosely. My understanding of this algorithm is that a Monte Carlo renderer where samples are taken per pixel might have a random number generator implemented likeingenious wrote:The idea ideas not adding a deterministic (bluenoise) number to a random number. In fact, the idea is to get rid of the randomness altogether  you use the deterministic number to post your pattern, instead of using a random number.
fmod(halton(primes[dimension], sampleNumber) + blueNoise(pixelColumn, pixelRow), 1.0f)
And the halton() function might stand in for the "pixelindendent random number".
Isn't the wrapping fundamental to the algorithm? If halton() returned 0.5 in the above code, then blue noise values of 0.0 and 0.99 would produce final results of 0.5 and 0.49, respectively.Regarding the (0, 0.99) vs (0, 0.01) issue, the answer is that it depends. If your 1D sampling domain is "wrapped", i.e. 0.99 and 0.01 are next to each other, then yes, you should ideally take this into account in the distance function when you construct the dither mask.
Re: Implementation for Bluenoise Dithered Sampling
Just to clarify, here the implementation (as described in the paper) computes the bluenoise mask using a distance over wrapped boundaries. If this is not required then it's a rather simple change to alter this behavior. On another note, I've recently added some progress feedback in the terminal as per jbikker's suggestion.