CRT Emulation Shaders

Overview

There are four phases to the CRT emulation, two of which run every frame, and two which only need to run when settings or output resolution have changed.

Mask Generation

Mask Generation generates a texture that represents one of the supported CRT mask types (which is, perhaps unsurprisingly, called the Mask Texture).

Each of the three possible shaders generates the same image each time, so this could easily be done as a pre-process, either once at Cathode Retro startup or even once to generate textures to write to file to read back later.

Start Mask type? generate- aperture-grille generate- shadow-mask generate- slot-mask Mask Texture Mask Output Aperture Grille Slot Mask Shadow Mask

Simply pick whichever type of mask you wish to use and run the corresponding shader, ending up with the Mask Texture.

See the following shader documents for more information on each mask type:

Screen Texture Generation

Next, the Mask Texture can be handed to the generate-screen-texture shader to make the Screen Texture.

Start Mask Texture generate-screen-texture Screen Texture Screen Texture Output

This texture is expected to have the same width and height as the final output of the CRT emulation, so must be regenerated whenever the output resolution changes.

(Additionally, of course, it must be regenerated when the screen properties change, like the scale of the CRT mask or the curvature of the screen).

See the generate-screen-texture shader documentation for all of the shader inputs.

Diffusion Texture Generation

If CRT diffusion is enabled (an approximation of the photons bouncing through the glass in front of the CRT phosphors), the Diffusion Texture needs to be generated (per-frame). It is basically a tonemapped and blurred version of the RGB Texture.

Start RGB Texture tonemap-and-downsample downsample-2x (vertical) gaussian-blur (horizontal) gaussian-blur (vertical) Diffusion Texture Diffusion Texture Output

The first step is the downsampling (to make the blur larger), which is coupled with the tonemapping. So first, the tonemap-and-downsample shader runs, which ends up in a texture that with an aspect ratio of screenWidth/2 : screenHeight (i.e. it should be narrower than the actual screen by half).

(This tonemap and downsample pass does not do a perfect downsample, just an approximation using a 2x downsample shader - the goal is to get a texture with the correct aspect ratio - which is then going to be blurred - so it doesn't have to be exact to look good)

Then a straight 2x vertical downsample after that (using the downsample-2x shader), to get the aspect ratio right (so that the blur is circular and not elliptical)

After that, two passes of the gaussian-blur shader are run (one vertical, one horizontal), to result in the final Diffusion Texture.

See the following shader documents for more information:

Final Output

Given the Screen Texture has already been generated (by the Screen Texture Generation step above), the final assembly then is running the above Diffusion Texture Generation step if needed, then running the current RGB Texture the Previous RGB Texture (the RGB texture from the previous frame - only necessary if phosphor persistence is enabled), and the generated Screen Texture and Diffusion Texture into the rgb-to-crt shader.

Start RGB Texture Previous RGB Texture Screen Texture Diffusion Texture Generation rgb-to-crt CRT Texture CRT Output

The output of this shader is the final output of the CRT emulation.

See the rgb-to-crt shader documentation for all of the shader inputs.