Friday, February 28, 2020

CRT shader masks

There are 3 main types of masks used by CRT displays:
Slot Mask staggered grid

slot masks - also known by the brand name "Cromaclear" and/or "in-line shadow mask". These are probably the mask you're most familiar with, as they were used on most consumer televisions. They are characterized by the familiar staggered grid of red, green and blue phosphors.

Aperture Grille wires
aperture grille  - also known by Sony's brand name "Trinitron", this technology was also manufactured by other companies under slightly different names, such as Mitsubish's DiamondTron and ViewSonic's SonicTron. This mask technology is especially popular among retro-gaming crowds as a result of its brightness and vibrancy.


Shadow Mask Triad
shadow mask - the "triad" form of which is most commonly seen in PC monitors. The nomenclature on slot and shadow masks is apparently interchangeable, for the most part, though in retro-gaming, they're usually disambiguated such that "shadow mask" only refers to the triad type and "slot mask" only refers to the rectangular grid type.

When we attempt to reproduce these masks on modern displays, the simplest solution is to take an image of the phosphor layout, shrink it down and tile it across the image, then combine the game image with the phosphor image in some way (multiplication or screen combine are common). This is a simple and straightforward strategy that works well at very high resolutions, but it can become a real mess at lower resolutions as a result of the physical display's subpixel structure (see the pink and green patterns in CRT-Royale's mask at 1080p).

CRT-Royale's tiled images of phosphor layouts at 1080p


Just like a CRT, LCD monitors display colors by shining light through tiny lenses at various intensities and they combine to form the colors you see. These phosphors are usually much smaller than what you find on a CRT TV, but very fine details can still be distorted by these structures. Very small text is probably the place where we encounter these limitations most often and, back in the late 1990s, companies started trying to improve the situation using subpixel-based rendering techniques under the names ClearType, FreeType, etc. These techniques work with the LCD subpixel structure to give the illusion of higher resolution than the monitor is actually capable of displaying cleanly.

We can use some of these same tricks in our CRT reproduction shaders to produce better mask effects at lower resolutions, without the chromatic aberration caused by averaging together colors at the subpixel level. These patterns rely on the physical pixel structure of the display monitor, so they need to be tiled using gl_FragCoord (or texCoord.st * OutputSize.xy) so the tiling always matches up.

cgwg's crt-geom subpx aperture grille
 The most basic mask that exploits the RGB subpixel structure is a simple alternating green and magenta pattern. When displayed on a normal RGB screen, it makes perfectly evenly spaced lines of red, green and blue, which results in a very passable aperture grille, even at 1080p. This pattern was popularized by cgwg's venerable CRT shader (aka crt-geom).

At 1080p, this looks analogous to a low-TVL Trinitron TV (shader on the left, PVM on the right):
PVM shot from here, perspective-corrected in GIMP
While at 4K, it looks very much like a high-TVL monitor, like a BVM (click to see more details):
 The next simplest pattern is just that same pattern doubled vertically and mirrored horizontally on each successive line, for a green and magenta checkerboard. This results in a pretty decent shadow mask triad pattern that looks pretty legit at 1080p, though it's probably too tight for anything much larger than that. That is, at 4K and higher, it's pretty much invisible unless your nose is right on the screen.


 Here's a detail comparing the subpixel-respecting strategy with a naive tiling approach at 1080p:
 
By extending the pattern and adding in some black pixels, we can get an okay/not great slot mask. As with the previous patterns, the RGB pattern looks good, but since we're limited by the physical pixel size, the black crossbars are unfortunately over-represented, making the image significantly darker than it should be. However, we can compensate for this somewhat just by reducing the strength of the mask effect within the shader.
 At 1080p, the TVL of the simulated display is unrealistically low (like, maybe a really crummy portable TV or something), but at 4K this mask gets more realistic in terms of scale.

At 8K, though, you can start drawing much better, more accurate phoshor patterns while still maintaining a realistically usable TVL, though the tiled patterns start getting pretty weird.

Funky slot mask pattern
The results look good, but it's worth noting that at these resolutions, naive tiling doesn't look too shabby, either, especially with a few feet of distance between the viewer and the monitor.







crt-lottes rotated mask
Another totally different strategy is to flip the phosphor grid 90-degrees to avoid the uneven subpixel spacing altogether. This isn't "accurate" to the way CRT masks actually look, but it sidesteps a lot of the problems caused by trying to reproduce them on modern displays, including problems caused by variations in subpixel layouts (that is, not all LCDs use nice, clean R,G,B arrays; some use RGBW, RGBY or BGR and some, like OLEDs, use a crazy layout that looks totally alien; see here for more: https://geometrian.com/programming/reference/subpixelzoo/index.php). This strategy is used in Timothy Lottes' "FixingPixelArt" shadertoy, on which the crt-lottes shader is based.

Many subpixel-respecting mask patterns can be found in LUT form alongside cgwg's crt-geom-deluxe shader, including some of these and some others I didn't mention (mostly aperture grille variations that work at higher resolutions, like 4K and 8K. You can also find these and others in my subpixel_masks shader snippet, which is designed to be #include-d in other shaders for easy mask-generation and uses an expensive but very informative array-based syntax so the patterns are easier to visualize and understand.