Under the glass
How Phosphors works
Phosphors doesn't add a "CRT filter" to your video. It rebuilds the picture from scratch by simulating the physics of a real cathode-ray tube: an electron beam, a phosphor-coated screen, and the glass in front. Everything you see emerges from that simulation.
1. Simulate the hardware, don't fake the look
Most "retro CRT" tools draw scanlines and a glow on top of your image. Phosphors works the way the tube did: it fires a simulated electron beam at a simulated phosphor screen and shows you what lights up. Scanlines, bloom, smeared motion trails, the rolling hum bar, the fine mask texture: none of them are painted on. They happen, the same way they happened in 1985.
The consequence that drives the whole architecture: the phosphor buffer is the screen. It is a GPU-resident image of the current brightness of every phosphor on the tube. Your Mac's display is just a window onto that buffer. The host monitor's refresh rate is irrelevant to the physics. The beam scans at the CRT's rate and phosphors decay at their real-world rates, both driven by an independent clock.
That is also why the look stays physically correct at any resolution, from a 13-inch portable to a 4K master, instead of breaking down like a fixed overlay would. More resolution means more phosphors and a finer beam, so the picture gets sharper, not blockier.
- Your video Any clip macOS can decode. Conformed to a small SDR frame on the media engine, because the tube is standard definition and HDR is an output property.
- Broadcast encode and decode The frame is encoded into a baseband composite signal (or routed through the VGA path), pushed through a tuner with realistic noise behaviour, and demodulated back to RGB scanlines by a receiver.
- Phosphor simulation kernel Reads the decoded signal, advances the beam, excites and decays every phosphor. Output: a state buffer with one brightness per phosphor.
- Display pass Applies mask geometry, afterglow colour, vignette, hum bar and HDR headroom at the output resolution. This is the picture, on screen and in the recording.
2. The signal path
Before anything reaches the tube it travels the way a broadcast did. Each input on a television preset is a different chain with its own real artifacts, dirtiest to cleanest:
- RF. A simulated tuner: narrowest bandwidth, snow when the signal is weak, and an RF Tuning dial that detunes toward a slightly-off channel.
- Composite. Luma and chroma share one wire and have to be combed apart. The Comb Filter dial sets how cleanly; lower leaves more cross-colour rainbowing on fine detail and dot crawl on edges.
- S-Video. Luma and chroma on separate wires. No cross-colour.
- Component. Clean YPbPr, and progressive 480p, so every line is drawn every frame.
- Retro Console. 240p over RF. Consoles from the Famicom on emitted 262 whole lines per field instead of 262.5, which defeats interlace: every field lands on the same 240 raster positions. See below for what that does on the glass.
The NTSC Tint knob exists for the same reason it did on a real set: hue was a real artifact of how colour was encoded. Monitors take a clean digital or RGB feed and hide the whole section. The Bandwidth dial models the analog video chain before the tube: lower is crisper horizontal detail with authentic edge ringing, like a wide-band amplifier; higher rolls off softer, like a long cheap cable.
3. The electron beam
A clock, not a frame counter
The beam is driven by a monotonic clock independent of the host display. Fields are dispatched at the preset's rate: 59.94 Hz for NTSC, 50 to 85 Hz for monitors. The simulation is correct whether your Mac runs at 60, 120 or 144 Hz.
Arrival time is per scanline
The beam paints top to bottom over one field period, so each scanline has its own arrival time within the field. Top lines are fresher than bottom lines. That is the physical basis for the rolling brightness gradient, for correct interaction with persistence, and for the Shutter control: at 1.00 you are the rested eye and everything fuses; lower it and you watch through an ever-faster camera shutter, and the rolling band of filmed CRT footage appears.
The beam's horizontal landing point per line is offset by the sync-PLL result plus jitter, so losing horizontal lock bends individual lines exactly as a real tube does.
Shape: a Gaussian with a Nyquist floor
The crucial parameter is σ, the beam width. It is derived from the Sharpness dial's falloff ratio and clamped to a floor of half a pixel: below that, a point-sampled Gaussian aliases against the sample grid and the scanline pattern beats. So Phosphors keeps the beam exactly as sharp as the render resolution allows without aliasing. Scanlines read as crisp glowing lines at 480p and dissolve into a smooth field at 4K, which is also how a real set looks lined up close and seamless from across the room.
σ ≥ 0.5 px
Imperfections, all physically motivated
- H-Focus is the focus pot. At 0 the beam's crossover lands on the phosphor plane; turn it either way and the focal point moves in front of or behind the screen and the spot widens. Both directions defocus, like rocking a real monitor's focus adjustment through its sweet spot.
- Convergence. The three guns don't land perfectly on top of each other. Red and blue shift by an amount that grows with distance from centre, and shadow-mask tubes additionally get a vertical offset, reproducing fringing that worsens toward the corners.
- Edge Focus. σ widens with the square of the distance from centre, the way a deflection yoke loses focus off-axis.
- Beam Bloom. σ widens with local brightness. Space-charge repulsion makes bright areas swell.
- Noise. High-frequency jitter, mains-coupled deflection, slow thermal drift, and per-pixel shot noise on the deposited energy.
4. Phosphor excitation and decay
Where the beam lands, it lifts the phosphor's brightness. The phosphor state is updated with a maximum, not an accumulation: a phosphor decays autonomously every frame, and a fresh beam pass only lifts it if the new excitation is brighter. That makes the steady-state image independent of how many times or in what order the kernel runs, which is what keeps the simulation correct across wildly different host frame rates.
A two-component exponential
brightness = max(brightness · decay, excitation)
The presets are real phosphor data
Decay rates and amplitudes are not tuning knobs invented for looks. They come from documented phosphor types, and each colour channel can decay at its own rate.
| Preset | Compound | Used in | Character |
|---|---|---|---|
| P22 | Y₂O₂S:Eu (R) · ZnS:Cu,Al (G) · ZnS:Ag (B) | Colour TV and monitors | Per-channel decay. Red slow, blue fast, which is why moving edges on a colour tube tint the way they do. |
| P4 | ZnS:Ag + (Zn,Cd)S:Ag | Black-and-white TV, white terminals | Fast white with a short power-law tail. |
| P39 | Zn₂SiO₄:Mn,As | IBM MDA, long-persistence green | Arsenic trap-state tail lasting two to three seconds. 34.5% remaining at 30 ms. |
| P1 | Zn₂SiO₄:Mn | Classic green terminals and scopes | Medium green, T10 ≈ 24 ms. |
| P31 | ZnS:Cu | Modern oscilloscopes | Three times brighter than P1, very short persistence. |
| P3 | Zn₈BeSi₅O₁₉:Mn | Amber terminals | Warm 602 nm amber, medium persistence. |
| P4G | ZnS:Ag, green-tinted | DEC VT220 | Short-persistence green TV phosphor. |
The display stage also applies a small decay-dependent afterglow colour shift, so as each channel fades its emission drifts the way the real compound does. The red Y₂O₂S:Eu tail warms toward orange.
5. Fields, interlace and the retro console
Monitors are progressive: every scanline is painted every field. Televisions are interlaced, and the visible region is mapped through the vertical blanking interval so framing matches the standard, roughly 480 visible lines of 525 for NTSC. Because each scanline carries its own arrival time and each phosphor its own decay since excitation, brightness naturally varies down the frame. The scan gradient is a consequence of per-line timing, not an overlay.
The Retro Console input models what a 240p signal does on a 480-line tube. The electron spot is a property of the tube, not the signal: a 240p feed keeps the native thin beam while the line spacing doubles, so the positions a 480i raster would visit in between stay dark. Those gaps are the retro scanline look. One thin beam per content line, never a fattened beam, never two beams, every line refreshed at 60 Hz with no interlace flicker.
6. The shadow mask
Up close, a colour CRT isn't made of pixels. It is a fine lattice of red, green and blue phosphors behind a perforated metal mask. Phosphors models the real geometries rather than a generic grid:
- Aperture grille. Continuous vertical R-G-B stripes, as in a Trinitron.
- Shadow mask. Delta-triad round dots in a honeycomb, each row offset half a triad, leaving a black matrix between them.
- Slot mask. Stripes broken into short slots, the hybrid most colour TVs used. The row pitch is locked to a whole multiple of the scanline pitch so it registers to the scan with no beat at any resolution.
- Triode. No mask at all. The picture the three guns paint, with the scanlines, bloom, persistence and beam softness but no structure over it. The name refers to the tube's three guns, not to a phosphor triad.
Why the pattern is coarser than a real tube's. A 21-inch Trinitron has about 1,700 RGB triads across its width; a colour TV around 750. Drawing one triad takes at least three pixels, one per stripe, so reproducing a real monitor's density would need over 5,000 pixels of width for the pattern alone. Phosphors draws the pattern at the finest size a pixel grid can hold, and it is deliberately locked to whole pixels so it stays crisp instead of shimmering. What you get is a faithful impression of phosphor structure rather than a one-to-one copy. It also means, exactly as on a real tube, that at 1× you may not see it from a normal viewing distance. Lean in with the viewing zoom, or raise Pattern Scale.
Pattern Scale and Pattern Focus
Pattern Scale is a multiple of the finest lattice that still reads, from 1× to 3×, and it is a multiple rather than a pixel size so the same value looks the same on screen and in a recording even though the two are different resolutions. Pattern Focus states how tightly the beam is focused on a single cell, interpreted per pattern: on stripes it sets how far the spot spills into neighbours, on the shadow mask how wide each dot is. Right is always tighter, purer and more separated; left is softer and fainter.
Focus also protects a recording. A hard-edged stripe is a square wave and carries harmonics, and those are what fold into rainbow moiré when a player scales your video to a window that isn't its native size. A fully blended stripe has a single frequency and nothing left to fold. Softening the pattern at the source beats any filter applied afterwards, because the harmonics are never created in the first place.
The stripe lattice also changes shape with how many pixels a stripe covers. Merged, all three channels light one bar per triad so it reads as white with a thin black line beside it; separated, when zoomed in, it splits into three coloured bars with black between. It is a continuous morph driven by pixels per stripe, and it is why the mask resolves cleanly instead of aliasing as it shrinks.
7. The display pass and HDR
Two passes run per frame. The simulation pass is the tube's state. The display pass is the picture: it samples the phosphor buffer through a mipmapped texture so minification integrates the scanline and mask comb cleanly, applies the mask tile, phosphor colour and afterglow, brightness, vignette and the sinusoidal mains hum bar. The live view and the recording are each their own display pass at their own resolution, fed by the same canonical phosphor image. Recording Preview shows the recording's pass on screen at 1:1, so you judge the file itself.
Output is a 16-bit float image with no clamp at white. With HDR on, the tube's own bright peaks, such as pattern sparkle and small bright areas above full-field white, are allowed to rise into the display's headroom through a per-pass highlight ceiling that is capped by what the panel can deliver right now. The picture itself never gets brighter; only the peaks do, and it cannot blow out. Recordings write HLG (Rec. 2020), chosen because it degrades gracefully: HDR displays show the full range and SDR players get a usable picture straight from the curve, with no tone-mapping metadata.
8. The receiver's audio
On broadcast presets the sound gets the same treatment as the picture. Raw audio goes through a full FM receiver chain implemented as pure DSP: pre-emphasis, phase-accumulator modulation, signal-to-noise phase noise, FM discrimination, de-emphasis, a capture-effect sigmoid, MTS stereo with dbx companding and a signal-tracking stereo blend, a TV speaker biquad, and intercarrier buzz. The receiver's hiss, the stereo image narrowing to mono as a weak signal fades, and the buzzy small-speaker character all emerge from the chain rather than from layered effect plug-ins. The Stereo, Speaker and Shielding dials sit on that chain.
9. Why this approach
Modelling the hardware instead of the output means the artifacts are correct by construction and interact the way the real ones do. Bloom widens the beam, which fattens scanlines, which changes how the mask reads, which the persistence then trails, all from one coherent simulation. Accuracy becomes a function of render resolution rather than of hand-tuned effect stacks, and the same canonical phosphor image feeds both the live preview and the recorder.
Phosphors' display presets are modelled from publicly documented CRT physics, not from any manufacturer's firmware. The result is a look that's correct by construction, and that gets sharper, not blockier, the more resolution you give it.