SpatiotemporalBlueNoise¶
from acron.sampling import SpatiotemporalBlueNoise
- class SpatiotemporalBlueNoise¶
Bases:
Spatiotemporal blue noise after Wolfe, Morrical, Akenine-Moller and Ramamoorthi, “Spatiotemporal Blue Noise Masks” (EGSR 2022): a stack of
depthtileable size x size threshold masks, one a frame, such that every slice is blue noise over the screen and every pixel’s sequence through the slices is blue noise over time. A renderer that draws a fresh slice each frame gets noise that a spatial filter and a temporal accumulation (TAA) both remove well, where white noise or one 2D mask animated by a golden- ratio offset leaves low-frequency crawl.The masks are ranked by Ulichney’s void-and-cluster with the paper’s separable energy: a Gaussian over the toroidal distance within a slice (sigma_space) plus a Gaussian over the toroidal distance between slices of the same pixel (sigma_time). Tightest clusters and largest voids are found with tournament trees, so the ranking costs O(N log N) for N = size^2 x depth (64 x 64 x 32 in about half a second).
The result is deterministic: one seed gives the same ranks on any machine with IEEE doubles (integer random numbers, ties broken by the lower index, energies summed in a fixed order with floating-point contraction off, kernels from an in-house exp(), not the C library’s). A stack holds at most 2^26 texels: a larger one logs an error and
generate()does nothing.Inheritance diagram
digraph inheritance2386e02944 { bgcolor=transparent; rankdir=BT; size="8.0, 12.0"; "DTOOL_SUPER_BASE" [fillcolor=white,fontname="Vera Sans, DejaVu Sans, Liberation Sans, Arial, Helvetica, sans",fontsize=11,height=0.25,shape=box,style=""]; "SpatiotemporalBlueNoise" [URL="acron.sampling.SpatiotemporalBlueNoise.html#acron.sampling.SpatiotemporalBlueNoise",fillcolor=white,fontname="Vera Sans, DejaVu Sans, Liberation Sans, Arial, Helvetica, sans",fontsize=11,height=0.25,shape=box,style="",target="_top",tooltip="/**"]; "DTOOL_SUPER_BASE" -> "SpatiotemporalBlueNoise" [arrowsize=0.75,style=""]; }- __init__()¶
A stack of
depthmasks of size x size texels. Nothing is computed untilgenerate(). sigma_space and sigma_time are the energy kernels’ standard deviations (Wolfe et al. use 1.9 for both).
- generate()¶
Ranks every texel. Phase 0 relaxes a random 10% pattern until its tightest cluster is its largest void; phase 1 removes the tightest clusters from it (ranks below its count, descending); phase 2 adds the largest voids (ranks from its count to the end). Past half the texels the largest void of the ones is the tightest cluster of the zeros (the kernels sum to the same total at every texel of the torus), so phase 2 also stands in for Ulichney’s phase 3.
- get_bytes()¶
Every texel as an 8-bit threshold (rank x 256 / count), x fastest, then y, then the slice: the RAM image of a size x size x depth single-channel texture array. Each of the 256 levels appears equally often when the count is a multiple of 256.
- get_depth()¶
The number of slices (frames before the sequence repeats).
- get_rank()¶
The rank (0 .. size^2 depth - 1) of a texel; coordinates wrap.
- get_seed()¶
The seed of the initial random pattern.
- get_sigma_space()¶
The spatial energy kernel’s standard deviation, in texels.
- get_sigma_time()¶
The temporal energy kernel’s standard deviation, in slices.
- get_size()¶
The side of each slice, in texels.
- get_value()¶
A texel’s threshold in (0, 1): (rank + 0.5) / count.
- static halton()¶
The radical inverse of index in the given base: element
indexof the Halton sequence along that axis (index 0 gives 0; TAA jitter starts at 1).
- is_generated()¶
True once
generate()has ranked every texel.