Skip to content

3. How FGS Works

Michele Cosentino edited this page Apr 27, 2026 · 3 revisions

Now that you know the syntax of the filmgrn1 format, we can explore the core engine behind it: the Auto-Regressive (AR) spatial filter. The AR coefficients (cY, cCb, cCr) defined in the table dictate the exact physical texture, size, and "clumping" of the synthesized grain.

Auto-Regressive 2D Spatial Grid

The AR coefficients are provided as a 1D linear continuous array in the filmgrn1 format, but they map to a 2D spatial grid around the current pixel being synthesized.

To maintain causality, the filter only uses pixels that have already been generated in raster-scan order (top-to-bottom, left-to-right). This means the filter's shape is asymmetrical.

If ar_coeff_lag = 3 (Maximum lag), it means the AR filter looks up to 3 pixels away in every direction, forming a theoretical $7 \times 7$ grid. The filter generates 24 coefficients (c0 to c23) which populate only the past (causal) portion of this grid.

Here is exactly how those coefficients are spatially arranged relative to the Target pixel (which stands perfectly at the center of the convolution grid):

x-3 x-2 x-1 x=0 x+1 x+2 x+3
y-3 c0 c1 c2 c3 c4 c5 c6
y-2 c7 c8 c9 c10 c11 c12 c13
y-1 c14 c15 c16 c17 c18 c19 c20
y=0 c21 c22 c23 Target - - -
y+1 - - - - - - -
y+2 - - - - - - -
y+3 - - - - - - -

The Mathematics of Causal Generation

Unlike a traditional blurring convolution filter (which requires preexisting pixels from all 360-degree directions to compute an average), the AV1 AR grain generator builds the texture sequentially.

When deciding the final value of the Target pixel, the system:

  1. Generates a purely pseudo-random Gaussian noise sample (acting as a base seed).
  2. "Looks back" at the history of the 24 pixels immediately preceding it (the valid $c_n$ slots in the top-left area). Because the system always processes left-to-right and top-to-bottom, these pixels were already successfully calculated in previous steps and are available in RAM.
  3. Multiplies those historical pixel values by their corresponding AR coefficients and sums them together. This resultant geometry is added to the Gaussian base.

Note

Hardware Parallelization & Templates: It is critical to understand that this causal, sequential AR processing does not run continuously across the entire width and height of a 4K/8K video frame, as that would create a massive bottleneck. Instead, AV1 first generates a single master grain template per frame (an array of $82 \times 73$ pixels for Luma, and proportionally smaller arrays like $44 \times 38$ for Chroma 4:2:0). The heavy AR filter math is calculated strictly within this isolated template. Once this master template is fully synthesized, the decoder fills the entire video frame by extracting randomly offset $32 \times 32$ blocks (for Luma) from within that same template. Because it is just "stamping" random chunks of an already-calculated template across the screen, the hardware can process the whole frame perfectly in parallel, vastly speeding up the synthesis process.


Shaping the Grain: Positive, Negative, and Zero Coefficients

The numeric values of the coefficients dictate how the noise clusters together.

  • Zero (0): Applies no correlation. If all 24 coefficients are zero, the synthesis produces pure White Noise (similar to uncompressed digital sensor static), with no clumping or recognizable spatial patterns.
  • Positive Values (> 0): Induce positive correlation, encouraging adjacent pixels to share the same brightness. This causes the noise to merge into larger, softer clumps (similar to organic silver halide crystals on celluloid). Proximity Effect: Putting positive values directly adjacent to the Target (like c23 directly to the left, or c17 directly above) will stretch the grain horizontally or vertically, producing pill-shaped or elongated clumps.
  • Negative Values (< 0): Induce anti-correlation, forcing adjacent pixels to take opposite brightness values. This produces a high-frequency, "peppery", or razor-sharp sandy texture. Edge Enhancement: A common artistic technique is to place strong positive coefficients directly near the Target to build a clump, and surround them with negative coefficients further away. The negative values act as an "unsharp mask", carving out the edges of the grain clumps and making them look extraordinarily sharp and well-defined against the video.

Correlated Chroma: The 25th Coefficient

When synthesizing grain for the Chroma planes (Cb and Cr), the AFGS1 specification provides an optional, highly advanced parameter known as Cross-Plane Correlation.

If cross-component correlation is established, the cCb and cCr coefficient arrays will contain 25 values instead of 24 (at maximum lag). The first 24 values (c0 to c23) behave exactly like the Luma plane, mapping natively to the 2D spatial grid illustrated above. The 25th value (c24) acts as a dedicated Luma-injector multiplier. It assesses the fully completed Luma grain value residing at the exact same $[y=0,\ x=0]$ coordinate, multiplies it by this 25th coefficient, and injects it straight into the Chroma synthesis.

This forcefully anchors and aligns the spatial clustering of the color grain layers to the physical texture of the Luma layer, preventing the "floating chroma noise" effect typical of older digital codecs.


Mathematical Stability and Limits

The noise synthesis in AFGS1 utilizes a 2D IIR (Infinite Impulse Response) filter based on the autoregressive model. The stability of this entire IIR filter system strictly depends on the energy of the AR coefficients.

Mathematically, the sum of your coefficients divided by $2^{shift}$ (using the ar_coeff_shift parameter) must be less than 1.0. If the sum exceeds this limit, the IIR filter diverges, and the grain generator becomes mathematically unstable.

Instead of natural noise, an unstable generator will produce repeating patterns, geometric artifacts, or purely "static" vertical/horizontal blocks that look like severe digital corruption.

The Instability Neighborhood (Pushing the Limits)

Think of the AR filter like water ripples in a pond.

  • Very Stable (Small Coefficients): The ripples die out quickly. This generates very fine, dusty noise (like standard digital static) because the pixels don't influence each other over long distances.
  • Near-Unstable (Large Coefficients): If you push the sum of the coefficients very close to the 1.0 stability limit, the ripples travel much further before fading. This forces the pixels to stick together over larger areas.

In this "boundary" zone right before the math breaks down, the grain naturally aggregates into large, thick waves and blobs. Exploiting this near-unstable state is a powerful trick used to simulate extremely coarse, rough, or damaged vintage film stocks that would otherwise be impossible to create.

Example of an unstable grain pattern:

image

Example of a grain pattern near the instability limit (safe but coarse):

image

Grain Seeds

The random_seed in the filmgrn1 event is the starting point for the random pattern generator.

By design, AFGS reproduces the exact same noise pattern across any spec-compliant video player. To achieve an organic and realistic film grain effect everywhere, the random seed must be updated per event or per frame, unless the goal is intentionally to create a static, frozen grain pattern. FGSEditor manages a pool of carefully selected seeds to ensure maximum randomness and avoid repeating artifacts.