Your Brain's Rendering Pipeline,
in 2000+ Lines of GLSL

GLSL (OpenGL Shading Language) is a C-like language that runs directly on the GPU. A fragment shader is a program that executes once per pixel, in parallel, every frame, which suits real-time image processing. The main simulation runs as a single fragment shader at 60fps; saliency and structure maps are computed separately in JavaScript and passed in as textures, and some research modes add WebGPU compute passes.

You see the world through a pipeline. Light enters the eye, gets filtered, decomposed, and reassembled, and at each stage the periphery gets a different deal than the fovea.

Retina
Photons → electrical signals
LGN
Gates what reaches cortex
V1
Decomposes into features
V4
Color & form processing
What does the signal look like at each stage? What's preserved, what's lost, and what representation arrives downstream?

Scrutinizer makes those transformations visible. Each biological stage maps to a real-time shader operation, running on every pixel, every frame.

Retina → LGN → V1 → V4 · implemented in a single GLSL fragment shader

Signal transformation pipeline: raw photoreceptor input → LGN filtering gate → V1 feature extraction → reassembled perceptual output
The signal at each stage. Dense photoreceptor input is filtered by the LGN gate, decomposed into oriented features by V1, and reassembled into a sparse perceptual representation. Information is transformed at each stage.
Scrutinizer browser demo — foveated vision simulation in real time

The simulation running live on a browser page. The cursor marks your fovea.

Wrapped in a browser built with the popular Electron framework, the simulation runs on any web page in real time.

The Pipeline: Biology → GLSL

The visual system is vastly more complex than any current simulation captures: dozens of cortical areas, parallel processing streams, recurrent feedback loops. The shader models four stages chosen for their outsized impact on peripheral appearance: retinal spatial filtering, LGN attentional gating, V1 feature integration, and V4 color processing. Every parameter depends on eccentricity from the gaze point.

Retina
Photoreceptors → Ganglion cells. 1:1 foveal, 100:1 peripheral.
sampleSource(uv)
MIP pyramid generation
LGN
Attentional gating. Structure mask. Saliency gate.
V1
Feature extraction. Crowding. Positional uncertainty.
V4
Color processing. Rod vision. Aesthetic rendering.
The Central Equation: Eccentricity

Every stage depends on one value, the normalized distance from the gaze point:

$$\text{eccentricity} = \frac{|\vec{P}_{\text{fragment}} - \vec{P}_{\text{gaze}}|}{r_{\text{fovea}}}$$

$\vec{P}_{\text{fragment}}$ is the screen position of the current pixel (in GPU terminology, a fragment, and the shader runs this equation independently for every pixel on screen, every frame). $\vec{P}_{\text{gaze}}$ is the current gaze point (mouse position or eye-tracker input). At eccentricity = 0, you're at the fovea (full detail). At 1.0, you're at the foveal boundary. At 2.5, parafovea. Beyond that is peripheral vision, which covers most of the visual field and accounts for most of the shader's work.

Biological Primer

The retina is a layered neural circuit.

The sections below summarize the minimum context for following the simulation. The structures involved (retina, LGN, V1, V4) have been well characterized since Kuffler (1953) and Hubel & Wiesel (1962).

Receptive Field Mosaic

Each circle represents one ganglion cell's receptive field. Dense, small fields at the fovea; sparse, large fields in the periphery. This is why peripheral vision loses spatial detail: fewer cells, each pooling a wider region.

The Retina: Where Vision Begins

Light hits photoreceptors (rods and cones), which convert photons to electrical signals. These signals pass through bipolar cells to retinal ganglion cells, whose axons form the optic nerve.

In the fovea, a 1.5mm pit at the retina's center densely packed with cones, each cone connects to its own ganglion cell (1:1 wiring). In the periphery, each ganglion cell pools many cones (and 100+ rods, whose signals dominate only in dim light), trading spatial resolution for sensitivity. This convergence ratio is the fundamental reason peripheral vision loses detail. Because signals are pooled, you can detect that something is there but can't tell what it is.

Photoreceptor Convergence

Photoreceptors (top) funnel onto ganglion cells (bottom). At the fovea, each cone has its own dedicated ganglion cell (1:1). In the periphery, dozens of photoreceptors converge onto a single cell with a large receptive field. Sensitivity rises and spatial resolution falls.

Receptive Fields and Center-Surround

Kuffler (1953) recorded from individual ganglion cells in the cat retina while shining small spots of light at different positions. He found that each cell responded to a specific patch of the visual field (its receptive field), and that a spot in the center excited the cell while a spot in the surround inhibited it (or vice versa). This center-surround antagonism is the retina's first act of computation. It extracts local contrast and responds only weakly to absolute brightness.

A neuron's receptive field is the region of visual space that drives its response. Retinal ganglion cells have center-surround receptive fields (Kuffler, 1953): an excitatory center ringed by an inhibitory surround, or vice versa. The Difference-of-Gaussians (DoG) is a mathematical model of this response profile.

Center-surround organization makes these neurons bandpass filters. They respond to spatial frequencies matching their field size and respond only weakly to uniform illumination. Receptive field size scales with eccentricity: larger fields in the periphery means coarser frequency tuning further from fixation.

The Visual Pathway

Signals leave the retina via the optic nerve and pass through a series of processing stages before reaching cortex.

Lateral Geniculate Nucleus (LGN)
A six-layered thalamic relay. Magnocellular layers (fed by parasol ganglion cells) carry fast, achromatic, motion-sensitive signals. Parvocellular layers (fed by midget ganglion cells) carry slower, color-sensitive, high spatial frequency signals.
V1 (primary visual cortex)
Orientation-selective neurons (Hubel & Wiesel, 1962) decompose the image into local features: edges, bars, gratings at specific angles.
V4
Processes increasingly complex properties: contours, color constancy, object recognition.

Eccentricity and the Three Zones

0–2°
Fovea: highest acuity, cone-dominated
2–5°
Parafovea: crowding begins
5°+
Periphery: coarse spatial pooling

Eccentricity is the angular distance from fixation, measured in degrees of visual angle. The cortex devotes disproportionate surface area to the fovea, a property called cortical magnification (M-scaling). This is why a letter at 10° eccentricity must be ~5x larger than a foveal letter to be equally legible.

👁
Try it: How letter size scales with eccentricity
Interactive stimulus: watch letter recognition degrade as eccentricity increases.
→

Stage 1: The LGN Gate

The LGN is a relay with a gate: only 5–10% of the input to its relay cells comes from the retina, and the rest is modulatory.
Paraphrased from Sherman & Guillery, The role of the thalamus in the flow of information to the cortex (2002)
RETINA LGN gated relay V1 V4 top-down modulation cortex tells the gate what to pass schematic. Physically: retina → optic nerve → chiasm → optic tract → LGN (in thalamus) → optic radiation → V1 → ventral stream → V4
The LGN as Sherman & Guillery describe it: a gate on the signal path, with a control input wired from cortex. Feed-forward signal flows retina → LGN → V1 → V4. The dashed gold arrow is the cortico-thalamic feedback: V1 telling the LGN what to let through. The post-gate beam is narrower than the pre-gate beam because not everything the retina captures reaches cortex, and what does reach it is shaped by cortical feedback.

The Lateral Geniculate Nucleus sits between retina and cortex. For decades, neuroscientists treated it as a simple relay that passes signals through unchanged. Sherman and Guillery showed that only 5–10% of the input to LGN relay cells comes from the retina; the rest is modulatory, including feedback from layer 6 of visual cortex, and it controls what gets through. If you've built information retrieval systems, this is a familiar pattern: a filter stage that selects what enters the processing pipeline before any expensive downstream computation. In the shader, this gating is instantiated as two binary switches and a multiplication. The structure mask is all-or-nothing; the saliency gate is graded.

Structure Masking

The structure map is packed into a standard RGB texture, reusing an existing GPU data structure. Each pixel stores three signals as color channels, which the shader reads as vec3 components. No custom buffer formats or additional render passes are needed, and the GPU's texture sampling hardware does the interpolation for free.

The LGN stage needs to know what kind of content occupies each region of the page, and how that knowledge is represented constrains which operations are natural downstream. A content analysis pass (content-analysis.js) scans the DOM and encodes three signals into a structure map:

When the LGN stage encounters low density (empty whitespace between content), it suppresses the downstream simulation entirely. Center-surround cells in the retina and LGN respond weakly to uniform regions, so blank space carries little signal; the simulation skips it by zeroing the suppression factor for regions with no visual content to process.

// LGN Structure Masking — processLGN() in peripheral.frag
if (config.lgn_use_structure_mask) {
    if (u_has_structure > 0.5 && signal.density < 0.1) {
        signal.suppressionFactor = 0.0;  // Skip peripheral simulation for empty space
    }
}

Saliency Gating

The LGN stage reads the saliency map (edge detection + color contrast, temporally smoothed; pop-out reference) to decide what deserves processing bandwidth. The visual system faces the same constraint. About 1010 bits/sec reach the retina, but only ~106–107 leave it through the optic nerve (Raichle 2015; Koch et al. 2006). The visual system allocates limited processing resources selectively to high-value input. In the simulation, salient regions receive less peripheral filtering (its analogue of preferential processing), and low-saliency regions are processed cheaply.

LGN Suppression Factor
$$\text{suppression} = \text{suppression} \times \text{lerp}(1.0, \, 0.3, \, \text{saliency})$$

At saliency=1.0, the suppression factor drops to 0.3, so most of the original signal passes through. At saliency=0.0, full peripheral filtering applies.

Dashboard with foveal focus at center
fovea para periph
Dashboard, center focus. Full detail is visible at the gaze point. Peripheral regions are filtered through the full LGN→V1→V4 pipeline.
Dashboard saliency map overlay
Saliency map. Bright = high saliency = more processing bandwidth allocated. Text blocks, faces, and colored status badges get the most resources.
✨
Try it: Which element pops out?
Saliency pop-out search: see how contrast, color, and faces compete for your attention.
→

Stage 2: V1 Feature Extraction

V1 orientation selectivity columns — each cortical column responds to a specific edge orientation
V1 orientation columns. Each cortical column responds to edges at a specific angle (0°, 30°, 60°, 90°, 120°, 150°). This is how the brain decomposes the visual signal into oriented features (Hubel & Wiesel, 1962).

After the LGN gate, the signal that survives enters V1, where the representation changes in kind. Primary visual cortex decomposes the signal into features: orientation, spatial frequency, motion. In the periphery, these features are extracted at progressively lower resolution: receptive fields grow larger, features crowd into each other, and positional certainty degrades.

Scrutinizer's V1 stage implements three peripheral phenomena: positional uncertainty (domain warping), crowding (feature scrambling), and spatial pooling (resolution loss). The LGN stage's suppression factor modulates all of them, with up to a 70% reduction for the most salient content.

Domain Warping: Positional Uncertainty

In the periphery, you can detect that something is there but not where exactly it is. Scrutinizer simulates this with fractal noise displacement: two octaves of Simplex noise at 150x and 300x frequency, with a 2x horizontal bias that approximates the radial anisotropy of crowding (crowding is more severe along the radial axis toward/away from fixation than tangentially; Toet & Levi 1992).

Fractal Warp Displacement
$$\vec{d}_{\text{warp}} = \Big(\text{snoise}(\vec{uv} \cdot 150) + \tfrac{1}{2}\,\text{snoise}(\vec{uv} \cdot 300)\Big) \cdot 0.0024 \cdot s \cdot I$$

Where $s$ = distortion strength (eccentricity-scaled) and $I$ = intensity. The 0.0024 constant sets the warp amplitude in texture (UV) units. Because $s$ grows with the square of eccentricity, displacement is near zero at the foveal boundary and largest in the far periphery.

Crowding: The Fundamental Limit

Crowding is not blur (Pelli, 2008). You can detect a letter in your periphery. You cannot identify it when flanked by other letters. The bottleneck is obligatory feature integration across the receptive field.

Crowding is arguably the most important phenomenon in peripheral vision, and it is an information-theoretic one (crowding reference stimuli, Bouma spacing). It limits what you can separate. Adjacent features are compulsorily pooled (averaged, texture-ified) once they share a receptive field. The individual signals are irreversibly mixed, and the representation can no longer distinguish them. Bouma's law quantifies the critical spacing:

Bouma's Law: Critical Spacing
$$s \approx 0.5 \cdot \phi$$

Where $s$ = minimum spacing to avoid crowding and $\phi$ = eccentricity from fixation. At 10° eccentricity, targets must be ≥5° apart to be individually identified. This linear scaling with eccentricity mirrors cortical magnification. The two express the same constraint.

The shader implements two crowding modes:

// V1 Discrete Scramble — processV1() and applyCutter() in peripheral.frag
float scrambleZone = smoothstep(0.02, 0.15, corticalStrength);
vec2 cellID = floor(uv * cellFreq);
vec2 jitter = hash22(cellID) - 0.5;
vec2 throwDist = vec2(0.008, 0.0016);  // 5:1 H:V ratio
discreteScramble = jitter * throwDist * scrambleZone²;
Article page with foveal focus
fovea para periph
Article, center focus. The V1 crowding stage filters paragraph text in the periphery while headlines receive more bandwidth (larger receptive fields).
E-commerce page with product image focus
fovea para periph
E-commerce, product focus. When you fixate on the product image, the price tag, CTA button, and reviews are filtered through the V1 scrambling stage, which visualizes the feature pooling that limits peripheral object recognition.
🔬
Try it: Crowding stimulus
Isolated vs flanked letters: see crowding destroy letter identity.
→
📏
Try it: Bouma's spacing law
How flanker distance affects recognition, following the 0.5× eccentricity rule.
→

Block Pooling: Making Receptive Fields Visible

Two presentation modes make the pooling geometry tangible. Minecraft quantizes the image into blocks sized by cortical magnification, from 4px at the fovea to 64px in the far periphery. Each block shows the mean color of its receptive field. MC Eyeball does the same with polar sectors radiating from the gaze point, matching the radial elongation of TTM pooling regions (Toet & Levi 1992).

Minecraft Block Pooling — CMF-scaled blocks reveal receptive field sizes
Minecraft (Block Pooling). Blocks grow with eccentricity, showing the cortical magnification function as visible geometry. Fine blocks at the fovea, coarse blocks in the periphery.
MC Eyeball — polar sector pooling regions radiating from gaze
MC Eyeball (Polar Pooling). Wedge-shaped sectors emanate from the gaze point, radially elongated ~2:1. This is the shape of TTM pooling regions, the geometry within which the summary statistics are computed.

Toward Mongrel Textures: DoG Band Decomposition

What does the peripheral representation contain? Rosenholtz et al. (2012) describe it as summary statistics: local texture-like representations that preserve aggregate properties (mean color, dominant orientation, spatial frequency distribution) while discarding individual feature identity.

A lossy compression where the encoder is the visual system itself.

Rosenholtz's mongrel images, synthesized to match these statistics, show what that representation preserves, and observers' performance on mongrels predicts their peripheral performance in crowding tasks (Balas, Nakano & Rosenholtz, 2009). Synthesizing mongrels takes ~30 minutes per image on current hardware (M3 MacBook with MPS acceleration, 300 optimization iterations).

Real-Time Approximation

The shader's DoG band decomposition approximates this at real-time rates. It decomposes the image into spatial frequency bands and attenuates them independently based on eccentricity, without computing full texture statistics. Fine detail drops out before coarse structure, matching the biological attenuation profile in which retinal ganglion cells act as bandpass filters whose size scales with eccentricity (Dacey & Petersen, 1992).

The Approximate Laplacian Pyramid

A MIP chain (from Latin multum in parvo, "much in little") is a series of progressively downsampled copies of a texture that GPUs generate automatically. Level 0 is the full-resolution image; level 1 is half-resolution; level 2 is quarter, etc. GPUs use these for texture filtering at different distances. Hardware MIP generation uses box or bilinear filtering. A true Laplacian pyramid uses Gaussian convolution (Burt & Adelson, 1983). The shader repurposes this existing hardware feature: subtracting adjacent MIP levels produces an approximate Laplacian pyramid, where each level captures a band of spatial frequencies with some spectral leakage between bands.

The shader decomposes the hardware MIP chain into an approximate Laplacian pyramid of 12 half-octave bands, two per octave. Each captures a spatial frequency range (the four finest octaves are shown):

Bands 0–1
1–2 px: serifs, thin strokes
Bands 2–3
2–4 px: letter bodies, small icons
Bands 4–5
4–8 px: words, UI elements
Bands 6–7
8–16 px: buttons, layout blocks
Residual
DC: overall color & luminance (always preserved)
// 12 Half-Octave DoG Bands — peripheral.frag
// 13 MIP levels at LOD 0.0, 0.5, 1.0, ... 6.0 (half-integer = hardware trilinear)
vec4 mip[13];
mip[0] = textureLod(tex, uv, 0.0);
mip[1] = textureLod(tex, uv, 0.5);
// ... mip[2]–mip[11] at LOD 1.0, 1.5, ... 5.5
mip[12] = textureLod(tex, uv, 6.0);

vec4 band[12];
band[0] = mip[0] - mip[1];  // ~5.66 cpd: serifs, fine detail
band[1] = mip[1] - mip[2];  // ~4.0 cpd:  thin strokes
// ... band[2]–band[11]: √2-spaced down to ~0.125 cpd (full-width color fields)
// residual = mip[12]        // ~0.088 cpd: DC, always preserved

M-Scaling: Cortical Magnification per Band

Each band has its own cutoff eccentricity, the distance from the fovea where that frequency band is fully attenuated. With 12 half-octave bands, the cutoffs follow $\sqrt{2}$ spacing, matching the $E_2$ scaling of cortical magnification (tested against Rovamo & Virsu's 1979 contrast sensitivity data: frequency ordering holds, but the fit is partial, r = 0.60 against a 0.9 target; see report):

Per-Band Cutoff Eccentricities
$$c_k = E_2 \times (2^{k/2} - 1) \qquad k \in \{1, 2, \ldots, 12\}$$

Where $E_2$ is the half-resolution eccentricity, the point where spatial resolution drops to half its foveal value. In the shader: u_dog_e2, user-adjustable. Odd-indexed cutoffs ($c_1, c_3, c_5, c_7$) match the original 4-band anchor values. This linear form applies when cortical magnification is off. With it on (the default), the cutoffs follow the logarithmic cortical mapping $c_k = a\,(e^{k w/2} - 1)$, where $a$ = 2.78° and $w$ is set by the viewport's cortical extent (Schwartz, 1980; Blauch, Alvarez & Konkle, 2026).

Each band's weight is computed via smoothstep rolloff, with a transition width controlled by u_dog_sharpness. At sharpness=0, the transitions are wide and gradual (biological). At sharpness=1, they're narrow and crisp (engineering utility mode).

// Per-band weights via smoothstep rolloff
float w[12];
for (int k = 0; k < 12; k++) {
    w[k] = 1.0 - smoothstep(c[k] - c[k]*trans, c[k] + c[k]*trans, normEcc);
}

// Reconstruction: residual + weighted bands
result = mip[12];
for (int k = 0; k < 12; k++) { result += band[k] * w[k]; }
result = clamp(result, 0.0, 1.0);

What This Means in Practice

Fine detail is filtered first, and coarse structure passes through longest. The signal is attenuated selectively by frequency band.

Close to the fovea, all 12 bands survive, so detail is complete. In the parafovea, the finest bands (serifs, thin strokes) drop out first. You can still read words but individual letterforms lose their character. Further out, letter-body bands fade and shapes become blobs. In the far periphery, only the coarsest bands and the DC residual remain: you see buttons and layout blocks but not their labels.

Article structure map
Structure map, article. The LGN stage reads this content analysis. Red channel = text rhythm, Green = density, Blue = element type. DoG band weights are modulated by this structure.
Techmeme with foveal focus
fovea para periph
Techmeme, center focus. Dense news layout. The DoG stage preserves headline structure while filtering individual link text. The data table density is exactly the kind of content where DoG outperforms uniform blur.

Fidelity Gap: What DoG Misses

The DoG decomposition models frequency-selective attenuation. It does not implement the full mongrel texture model. True summary statistics include orientation distributions, phase correlations, and cross-scale feature conjunctions that our isotropic bands discard. The shader does measure local orientation energy (horizontal, vertical, 45°, 135°) and extends band cutoffs for cardinal edges to model the oblique effect, but the bands themselves are not oriented filters and cannot capture the Gabor-like, phase-sensitive receptive fields of real V1. Closing the gap between our real-time approximation and a full Rosenholtz-style synthesis is future work.

🌐
Deep dive: The MIP chain as Laplacian pyramid
Interactive explainer: how hardware texture levels approximate frequency band decomposition.
→
↘
Try it: The oblique effect
Cardinal edges survive further in your periphery than diagonal ones (orientation-selective V1 bands).
→

Stage 3: V4 Color & Aesthetics

Visual area V4 processes color, shape, and object recognition. In the periphery, color perception shifts: cone-opponent sensitivity falls with eccentricity, red-green (L−M) much faster than blue-yellow, which alters hue and saturation (per-channel chromatic decay validated; see report). The shader's V4 stage simulates these shifts using Oklab color space, rod-spectrum tinting, and selectable aesthetic rendering modes.

Oklab: Perceptually Uniform Desaturation

A color space is a coordinate system for describing colors. RGB maps to hardware (red/green/blue light intensities) but doesn't correspond to human perception: equal RGB steps don't look like equal brightness steps. Perceptually uniform spaces like Oklab are designed so that equal mathematical distances correspond to equal perceived color differences. This matters when you need to smoothly remove color: in RGB, desaturation causes unwanted hue shifts. In Oklab, you can zero out the chrominance channels (a, b) and get clean, hue-stable grayscale.

If you desaturate in RGB or HSL, hue shifts as saturation drops: warm colors skew yellow, cool colors skew cyan. Oklab (Ottosson, 2020) separates lightness (L) from chrominance (a, b) in a perceptually uniform space. Killing a and b channels produces clean grayscale without hue contamination.

L (Lightness) magnocellular pathway a (Red ↔ Green) parvocellular pathway b (Blue ↔ Yellow) koniocellular pathway 0 1 −a 0 +a −b 0 +b survives to far periphery degrades first (~5°) persists further (~10°) Scrutinizer decays a and b channels independently, matching the faster loss of red-green opponency with eccentricity
Oklab separates lightness from chrominance. Each channel maps to a retinal pathway with different eccentricity falloff. The shader kills red-green (a) before blue-yellow (b), matching the faster loss of L−M cone opponency in the periphery (Mullen & Kingdom 2002).
🌈
Try it: Peripheral color decay across the spectrum
Watch a full hue gradient lose saturation as eccentricity increases. Red-green fades before blue-yellow.
→
Oklab Desaturation
$$L_{ab} \cdot \begin{pmatrix} 1 \\ 1 - f \\ 1 - f \end{pmatrix} \quad \text{where } f = \text{smoothstep}(r_{\text{fovea}}, \, 5\,r_{\text{fovea}}, \, d)^3$$

$f$ = desaturation factor, rising from 0 at the foveal edge with a cubic onset; intensity and saliency protection scale it below 1. Lightness is preserved. Only chrominance fades. The per-channel chromatic decay described below suppresses the red-green axis (Oklab a) before blue-yellow (b), matching the faster decay of L−M midget cell opponency with eccentricity (Mullen & Kingdom 2002).

Chromatic Pooling: Why Blue Outlasts Red

The Oklab desaturation above treats both chrominance channels equally. The visual system has two independent color pathways with very different eccentricity profiles:

The shader models this asymmetry with independent decay rates per channel. The table below lists practical consequences for web design.

Element At 5° At 10° At 15°
Large blue background Full color Full color ~90%
Small red badge (12px) Uncertain Low Gone
Green success icon Moderate Low Gone
Yellow warning banner Full color Full color ~85%

Blue and yellow signals persist in the periphery. Red and green degrade early for small elements. Always provide a luminance difference alongside color, because luminance contrast survives chromatic decay.

🎨
Try it: Which colors survive in your periphery?
Labeled color patches showing saturation loss by hue family at increasing eccentricity.
→

Magnocellular Pathway: Luminance Contrast Preservation

The visual system processes information through parallel streams from the retina onward. Parasol ganglion cells (large, fast) feed the magnocellular (M) layers of the LGN (layers 1–2), carrying luminance contrast and motion signals. Midget ganglion cells (small, slower) feed the parvocellular (P) layers (layers 3–6), carrying color and fine spatial detail. Livingstone & Hubel (1988) proposed that the streams stay segregated into cortex, the M-stream feeding motion perception (dorsal/where pathway) and the P-stream object recognition (ventral/what pathway). Later work found substantial mixing of M and P inputs in V1 and in both cortical streams (Merigan & Maunsell 1993). The M-stream's sensitivity to luminance contrast and motion still explains why you can detect motion in far peripheral vision where color and form have long since degraded.

The magnocellular (M) pathway is fast, achromatic, and motion-sensitive, and it preserves luminance contrast even as the parvocellular (P) pathway loses color and detail. The shader simulates this by sampling the clean (undistorted) image, computing a luminance ratio, and blending it back into the simulated output.

// Magnocellular Pathway — processV4() in peripheral.frag
float cleanLuma = dot(cleanSample, vec3(0.299, 0.587, 0.114));
float distortedLuma = dot(col, vec3(0.299, 0.587, 0.114));
float lumaRatio = cleanLuma / max(distortedLuma, 0.01);
float contrastPreservation = mix(0.6, 0.1, t);  // t = smoothstep(0, 4 × fovea, eccentricity)
col *= mix(1.0, lumaRatio, contrastPreservation * t);
Techmeme structure map
Structure map, Techmeme. The structure analysis read by the LGN gate stage. Dense news sites show the rhythm/density/type decomposition that the rest of the pipeline uses.
Techmeme saliency map
Saliency map, Techmeme. Edge detection + color contrast in Oklab space. Bright regions receive more processing bandwidth through the simulated LGN gate.

Project Trajectory: 374 commits in 98 days, three shader reverts in 30 minutes, and the gap between biological accuracy and perceptual plausibility. Read the development arc →

Before & after. Original page (left) vs the full LGN→V1→V4 pipeline (right). The foveal region preserves full detail; the periphery is filtered through every stage described above.

What the Pipeline Models

Each stage of the rendering pipeline corresponds to a biological mechanism in the early visual system. For implementation details and full citations, see the scientific literature review.

Biology What You See Key Reference
Foveal cone density Sharp, full-resolution center where you're looking Curcio et al. 1990
Ganglion cell convergence Progressive blur with distance from fixation, as spatial frequencies drop out in bands Curcio & Allen 1990
Ganglion cell receptive fields Detail loss follows center-surround (DoG) structure, not Gaussian smear Kuffler 1953
Cortical magnification Rate of blur increase matches cortical area devoted to each eccentricity Schwartz 1977; Blauch et al. 2026
LGN attentional gating Salient regions (faces, text, high-contrast) stay clearer longer McAlonan et al. 2008
V1 crowding Peripheral letters jumble and swap: you see them but can't read them Pelli 2008; Pelli & Tillman 2008
Positional uncertainty Objects in periphery shift position slightly, worse horizontally Levi & Klein 1996
Red-green opponent falloff Reds fade to gray in the periphery while blues persist Mullen 1991
Rod spectral sensitivity Far periphery takes on a cool, slightly cyan cast (a stylized tint; at screen brightness, peripheral color vision is cone-driven) Wald 1945
Magnocellular pathway Contrast and motion structure preserved even when color and detail are gone Merigan & Maunsell 1993
Saccadic suppression Brief blur during rapid eye movements (you don't notice your own saccades) Burr et al. 1994
Eigengrau Dark regions never go fully black because the visual system has a baseline "gray" Barlow 1957

Mobile: The Smaller Fovea

On mobile, the fovea subtends the same visual angle, but the screen is held closer and the viewport is denser. In the simulation, much of the content on a phone screen sits in the parafoveal zone, the transitional region where feature integration begins to degrade and crowding begins.

Article on iPhone 14 viewport
fovea para periph
iPhone 14, article. The same article page at mobile scale. Much of the content sits in the parafoveal zone, where feature integration starts to pool individual elements into texture.
Dashboard on iPhone 14 viewport
fovea para periph
iPhone 14, dashboard. Data-dense UIs on mobile. Only one card falls in the fovea; most content is in parafoveal territory.
Article on iPad Air viewport
fovea para periph
iPad Air, article. Tablet's larger viewport provides a middle ground. More foveal real estate, but still significant parafoveal load.
Dashboard on iPad Air viewport
fovea para periph
iPad Air, dashboard. The dense data table is an ideal test case for the DoG band decomposition. Rows fade by spatial frequency.

Select References

Further Reading

About the Author

Andy Edmonds studied cognitive science at Carnegie Mellon, Georgia Tech, and Clemson, then left academia in 1995 for what became two decades of machine learning at scale, shipping recommendation systems, search relevance, and information retrieval products at eBay, Adobe, Microsoft, and Meta.

CMU · Georgia Tech · Clemson | eBay · Adobe · Microsoft · Meta

Scrutinizer applies a question from that work to the visual system: how does information flow through a system, and what happens to the signal at each stage? The retina decomposes, the LGN gates, V1 pools, and V4 recolors, and each stage maps onto GPU operations.