Page **3** of **3**

### Re: Implementation for Blue-noise Dithered Sampling

Posted: **Thu Feb 09, 2017 11:32 am**

by **jbikker**

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.

### Re: Implementation for Blue-noise Dithered Sampling

Posted: **Thu Feb 09, 2017 4:22 pm**

by **toxie**

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.

- Untitled.png (581.97 KiB) Viewed 704 times

### Re: Implementation for Blue-noise Dithered Sampling

Posted: **Sun Apr 16, 2017 2:19 pm**

by **friedlinguini**

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 pixel-dependent blue-noise shift to a pixel-independent 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 high-dimensional blue noise tiles is hard, but can you get a good-enough effect by just using multiple independent 1- and/or 2-dimensional tiles, or even the same tile at a different sufficiently-large offset per dimension?

### Re: Implementation for Blue-noise Dithered Sampling

Posted: **Sun Apr 16, 2017 8:34 pm**

by **friedlinguini**

sin(2 * pi * (ps - qs)) * 0.5 + 0.5

OK, that makes no sense. I tried to jam a couple of ideas together without making sure that one didn't break the other.

Maybe c * (x - x * x), where x = ps - qs and c is some constant I haven't worked out yet.

### Re: Implementation for Blue-noise Dithered Sampling

Posted: **Mon Apr 17, 2017 4:58 pm**

by **ingenious**

The idea ideas not adding a deterministic (blue-noise) 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 non-wrapped.

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 non-wrapped mask.

For higher dimensions using independent (or independently screen-space 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 higher-dimensional blue noise masks is hard, because achieving high blue noise quality in high dimensions is hard in general.

### Re: Implementation for Blue-noise Dithered Sampling

Posted: **Mon Apr 17, 2017 10:30 pm**

by **friedlinguini**

ingenious wrote:The idea ideas not adding a deterministic (blue-noise) 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.

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 like

fmod(halton(primes[dimension], sampleNumber) + blueNoise(pixelColumn, pixelRow), 1.0f)

And the halton() function might stand in for the "pixel-indendent 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.

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.