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: Generate the CRT mask texture
- Screen Texture Generation: Generate the full-resolution CRT-style overlay
- Diffusion Texture Generation: Generate a blurred version of the input image to emulate the diffusion of photons through the glass of a CRT
- Final Output: Put it all together into the final Cathode Retro image.
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.
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.
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.
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.
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.