Package squidpony.squidmath
Class BlueNoise
java.lang.Object
squidpony.squidmath.BlueNoise
public class BlueNoise extends Object
Provides access to a precalculated, tiling plane of 2D blue noise, that is, noise without high-frequency components,
as well as seeded modifications to that tiling blue noise plane that make it have even fewer patterns.
Not actually a noise class like
This uses 64x64 grayscale textures 0 through 63 from Christoph Peters' invaluable blue noise resource. It may use more of the textures from that site in the future.
Created by Tommy Ettinger on 10/15/2019.
FastNoise
. The blue-noise distribution has the practical effect that a value
only appears next to a similar value very rarely. For a quick introduction, see
Alan Wolfe's blog, which has many more
useful posts and links that often relate to blue noise and its relatives, like low-discrepancy sequences (which
SquidLib calls quasi-random sequences, like VanDerCorputQRNG
).
This uses 64x64 grayscale textures 0 through 63 from Christoph Peters' invaluable blue noise resource. It may use more of the textures from that site in the future.
Created by Tommy Ettinger on 10/15/2019.
-
Field Summary
Fields Modifier and Type Field Description static byte[][]
ALT_NOISE
Raw data this class uses, as 64 1D byte arrays.static GreasedRegion[]
LEVELS
A 256-element array ofGreasedRegion
s, each 64x64, where the first GreasedRegion has an impossibly strict threshold on what points to include (it is empty), but the second has some points far apart, the third has more, and so on until the last element includes almost all points.static byte[][]
RAW_2D
Stores the same values asRAW_NOISE
if considered [x][y] indexed; available for convenient usage by GreasedRegion and other classes that can use 2D byte arrays.static byte[]
RAW_NOISE
The raw data this class uses, as a 1D byte array. -
Method Summary
Modifier and Type Method Description static int[][]
blueSpill(int[][] toFill, int spillerLimit, IRNG rng)
ModifiestoFill
in-place by filling it with the (seeded variant) blue noise of this class, finding any points with values less thanspillerLimit
when brought into a 0-255 range, and then expanding those points pseudo-randomly while keeping the same value for any expanded range as its original point.static int[][]
blueSpill(int width, int height, int spillerLimit, IRNG rng)
Generates a 2D int array (as withnew int[width][height]
) and fills it with the (seeded variant) blue noise of this class, finding any points with values less thanspillerLimit
when brought into a 0-255 range, and then expanding those points pseudo-randomly while keeping the same value for any expanded range as its original point.static byte
get(int x, int y)
Gets a byte from the raw data this stores, treating it as an infinite 2D plane of tiling 64x64 regions.static byte
get(int x, int y, byte[] noiseData)
Gets a byte from some raw data at least 4096 bytes in length, treating it as an infinite 2D plane of tiling 64x64 regions.static byte
get(int x, int y, int z)
Gets a byte from the raw data this stores, treating it as an infinite 3D space of tiling 64x64x64 regions.static byte
getChosen(int x, int y, int seed)
A mix of white noise and blue noise that has very few patterns detectable in frequency space, though it has some artifacts detectable to the human eye.static byte
getSeeded(int x, int y, int seed)
Gets a modified byte from the raw data this stores, using seed to adjust repeated sections of blue noise so patterns are much less noticeable.static byte
getSeeded(int x, int y, int seed, byte[] noiseData)
Gets a modified byte from some raw noise data in an array of at least 4096 bytes, using seed to adjust repeated sections of noise so patterns are much less noticeable.static void
indexedBlueNoisePoint(double[] dest, int index, double strength)
Implements http://extremelearning.com.au/a-simple-method-to-construct-isotropic-quasirandom-blue-noise-point-sequences/ .
-
Field Details
-
ALT_NOISE
Raw data this class uses, as 64 1D byte arrays. Any of the 1D arrays this holds can be passed toget(int, int, byte[])
orgetSeeded(int, int, int, byte[])
as their noiseData parameter. This group of byte arrays is static, which is probably OK even on Android as long as no one writes to it, and usesStandardCharsets
to decode itself from a String, which only works on GWT 2.8.2 and newer. Each byte array can be considered [x][y] indexed or [y][x] indexed; the original images were [y][x] indexed. -
RAW_NOISE
The raw data this class uses, as a 1D byte array. You probably don't want to use this field, but you might, so it is public... but don't write to it. It's static, which is probably OK even on Android as long as no one changes it, and usesStandardCharsets
to decode itself from a String, which only works on GWT 2.8.2 and newer. This can be considered [x][y] indexed or [y][x] indexed; the original image was [y][x] indexed. -
RAW_2D
Stores the same values asRAW_NOISE
if considered [x][y] indexed; available for convenient usage by GreasedRegion and other classes that can use 2D byte arrays. -
LEVELS
A 256-element array ofGreasedRegion
s, each 64x64, where the first GreasedRegion has an impossibly strict threshold on what points to include (it is empty), but the second has some points far apart, the third has more, and so on until the last element includes almost all points.
-
-
Method Details
-
get
Gets a byte from the raw data this stores, treating it as an infinite 2D plane of tiling 64x64 regions. You can interpret the blue noise in many ways, but it is meant to be used with a threshold to select mostly widely-spaced points when the threshold requires values greater than 100 or less than -100, or irregularly-shaped patterns of points when the threshold is in the middle, like for values less than 0. This tiles extremely well, or at least it appears so for a human; computers can detect the repetitive nature of this blue noise quite easily. Blue noise at left, magnitude histogram at right.- Parameters:
x
- x position, can be any int; results will repeat every 64 cellsy
- y position, can be any int; results will repeat every 64 cells- Returns:
- a byte that obeys a blue-noise distribution, so a value is only next to a similar value very rarely
-
get
Gets a byte from the raw data this stores, treating it as an infinite 3D space of tiling 64x64x64 regions. You can interpret the blue noise in many ways, but it is meant to be used with a threshold to select mostly widely-spaced points when the threshold requires values greater than 100 or less than -100, or irregularly-shaped patterns of points when the threshold is in the middle, like for values less than 0. This tiles extremely well, or at least it appears so for a human; computers can detect the repetitive nature of this blue noise quite easily. The blue noise property is only really preserved for slices of noise with the same z; changing z can be used to select a 2D noise plane as well. Blue noise at left, magnitude histogram at right.- Parameters:
x
- x position, can be any int; results will repeat every 64 cellsy
- y position, can be any int; results will repeat every 64 cellsz
- z position, can be any int; results will repeat every 64 cells, but this is different from x and y- Returns:
- a byte that obeys a blue-noise distribution, so a value is only next to a similar value very rarely
-
get
Gets a byte from some raw data at least 4096 bytes in length, treating it as an infinite 2D plane of tiling 64x64 regions. You probably want to get the noiseData from an element ofALT_NOISE
.- Parameters:
x
- x position, can be any int; results will repeat every 64 cellsy
- y position, can be any int; results will repeat every 64 cellsnoiseData
- a byte array with minimum length 4096; probably fromALT_NOISE
- Returns:
- a byte that obeys a blue-noise distribution, so a value is only next to a similar value very rarely
-
getChosen
A mix of white noise and blue noise that has very few patterns detectable in frequency space, though it has some artifacts detectable to the human eye. Blue noise at left, magnitude histogram at right. This works by choosing from one of four nearby blue noise tiles and using it as-is, with the choice determined by an initial blue noise sample from a non-tiling blue noise tile, weighted heavily based on how close a pixel is to a border between the four noise tiles. Compared togetSeeded(int, int, int)
, the "progressive" quality of the blue noise this uses is preserved better, meaning if you get the set of points with values under or over a certain value, that set is still usually blue noise. (Keeping this quality is quite hard for blue noise textures generated from combining existing tiles!)
This was changed somewhat on April 28, 2020 to a version with softer line artifacts that don't persist as long. It tends to look like it has less artifacts to human observers now, and about the same to signal processing. Upon closer inspection, it actually has many more line artifacts, but they are small, irregularly-spaced, and blend easily into their surroundings. This seems to be a tradeoff with this kind of blue noise. You can make an obvious grid of badly-stitched-together blue noise textures, and the frequencies will be good, but it will look terrible to humans; you could instead improve the appearance to humans by using just one blue noise texture, but that gets detected immediately by a computer as a pattern.- Parameters:
x
- x position, can be any int; results will not repeat for a very long timey
- y position, can be any int; results will not repeat for a very long timeseed
- seed value, can be any int; should be the same for all calls that should be from the same 2D plane- Returns:
- a byte that obeys an almost-blue-noise distribution, so a value is only next to a similar value rarely
-
getSeeded
Gets a modified byte from the raw data this stores, using seed to adjust repeated sections of blue noise so patterns are much less noticeable. Unlikeget(int, int)
, this won't repeat every 64 cells on x or y, but it isn't as correct at matching blue-noise frequencies, and tends to look "scratchy" in places, like TV static. This chooses a sub-array fromALT_NOISE
based on the seed, and the same seed will use the same sub-array in all locations. This tends to look less scratchy thangetChosen(int, int, int)
, but has worse measured repetitive qualities. The "progressive" quality of the blue noise this uses is not well-preserved, meaning if you get the set of points with values under or over a certain value, that set doesn't usually resemble blue noise. Blue noise at left, magnitude histogram at right.- Parameters:
x
- x position, can be any int; results will not repeat for a very long timey
- y position, can be any int; results will not repeat for a very long timeseed
- seed value, can be any int; should be the same for all calls that should be from the same 2D plane- Returns:
- a byte that obeys an almost-blue-noise distribution, so a value is only next to a similar value rarely
-
getSeeded
Gets a modified byte from some raw noise data in an array of at least 4096 bytes, using seed to adjust repeated sections of noise so patterns are much less noticeable. Unlikeget(int, int)
, this won't repeat every 64 cells on x or y, but it isn't as correct at matching blue-noise frequencies, and tends to look "scratchy" in places, like TV static. You probably want to get the noiseData from an element ofALT_NOISE
; unlikegetSeeded(int, int, int)
, this won't choose a different byte array, and will always use the givennoiseData
. The "progressive" quality of the blue noise this uses is not well-preserved, meaning if you get the set of points with values under or over a certain value, that set doesn't usually resemble blue noise.- Parameters:
x
- x position, can be any int; results will not repeat for a very long timey
- y position, can be any int; results will not repeat for a very long timeseed
- seed value, can be any int; should be the same for all calls that should be from the same 2D planenoiseData
- a byte array with minimum length 4096; probably fromALT_NOISE
- Returns:
- a byte that obeys an almost-blue-noise distribution, so a value is only next to a similar value rarely
-
blueSpill
Generates a 2D int array (as withnew int[width][height]
) and fills it with the (seeded variant) blue noise of this class, finding any points with values less thanspillerLimit
when brought into a 0-255 range, and then expanding those points pseudo-randomly while keeping the same value for any expanded range as its original point.- Parameters:
width
- the width of the 2D array to returnheight
- the height of the 2D array to returnspillerLimit
- the upper exclusive bound for the values that will be present in toFill when this finishesrng
- any IRNG to generate random values during expansion, such asRNG
orGWTRNG
- Returns:
- a 2D int array containing ints from 0 (inclusive) to
spillerLimit
(exclusive)
-
blueSpill
ModifiestoFill
in-place by filling it with the (seeded variant) blue noise of this class, finding any points with values less thanspillerLimit
when brought into a 0-255 range, and then expanding those points pseudo-randomly while keeping the same value for any expanded range as its original point.- Parameters:
toFill
- a 2D int array that will be modified in-place and entirely replaced; its contents don't matterspillerLimit
- the upper exclusive bound for the values that will be present in toFill when this finishesrng
- any IRNG to generate random values during expansion, such asRNG
orGWTRNG
- Returns:
toFill
, after modifications
-
indexedBlueNoisePoint
Implements http://extremelearning.com.au/a-simple-method-to-construct-isotropic-quasirandom-blue-noise-point-sequences/ .- Parameters:
dest
- will be modified and must have at least 2 length; the first element will store x, the second yindex
- which point to generate; must be non-negativestrength
- typically 1.0; can be smaller to produce less jitter and weaker blue-noise properties
-