Please show off what crt shaders can do!


The shader has a very interesting effect that is kind of hard to explain. Whenever the screen fades to black the image visibly shrinks, it is pretty cool actually.


Yeah, slang has access to a previous shaded frame (feedback), but both formats have access to previous un-shaded frames, which can be used for motionblur, etc. Check out the motionblur-simple shader to see a basic implementation. I did a feedback-based phosphor glow-trail shader that you can take a look at, too, if you like.

I read over a few of the posts discussing phosphor decay on the other forum and thought I would add: red phosphors are the ones that actually hang around for a fairly long time (on the order of up to a couple of seconds), while blue and green decay in milliseconds. IIRC, this is one of the reasons the SNES’ SuperScope peripheral tracked red pixels. However, I know from looking at my own CRTs that the decaying phosphors don’t really glow visibly red but rather the afterimage is a gray/colorless blob (i.e., without distinct details).

I notice in your preset there that you have 3 stock passes at half size and then the avglum pass. If you don’t mind requiring GLSL #version 130, you could replace those with one call to:

textureLod(sampler, coord, miplevel_int); // lvl 8 is enough to get the average of all pixels, I think

You just have to add mipmap_inputX = “true” to the pass that uses that function. It’s implemented in GL backend and Vulkan backend but is missing in D3D10/11/12 backend.

@Arviel yeah, that’s a real thing called “raster bloom” (not to be confused with the faux HDR “bloom” post-proc effect) caused by poor-quality (or failing) voltage-regulation in the monitor.


Any way to convert this shader to slang? would love to try it with beetle-HW and parallel.

Handheld games using this shader.


@Arviel - good stuff as usual, those look splendid. Did you tweak the preset or left it as it is out of the box? The high resolution you are using (1568 pixels tall I can see) goes very well with this shader.

@Nesguy - welcome to Blurland haha. That is actually really nice!

@guest.r & @hunterk - could you please explain to me what the stock shader is doing in this scenario? I notice 3x scale = 0.5 and another scale = 8. I understand the first 3 are halving the output resolution 3 times and the last one is used to bring things back to normal, but I don’t get why it’s done this way. Also, what does scale_type = viewport do?


For reference / comparison, here are some shots from an actual 29" Trinitron. FWIW, this is the reference I’ve been using for my own shader setup.

Notice how the scanlines are clearly visible over white, and become gradually thinner over darker colors. The visible lines never bloom to the point where they become completely connected, as in the shader examples.

The last close-up of the vine shows off the phosphors well.

These images are not my own, and were taken from here:


The only change i made was making the image flat for the handheld games, everything else is the default.

@nesguy Those are a good reference point, thanks for posting.

The scanlines on this shader have a very light touch which i find work great with handheld games.


could you please explain to me what the stock shader is doing in this scenario? I notice 3x scale = 0.5 and another scale = 8. I understand the first 3 are halving the output resolution 3 times and the last one is used to bring things back to normal, but I don’t get why it’s done this way. I have the impression that if I get to understand how the scale parameter works, I might finally be able to get good crt results at increased internal resolutions. Also, what does scale_type = viewport do?

Ah, it’s a way to calculate the average color / luminance of a frame. If i used greater steps lot of pixels would be left out. But @hunterk suggested a better trick with mipmaps, which is working great already.

About the 8x scale afterwards: the preset actually affects the buffer sizes, shaders cannot do this in my understanding. Without the 8x source based scale the next pass couldn’t use normal, 1x scale, it’s a cheap way to align scaling back to normal, and coordinates too.

Using scale type viewport is needed for multipass crt’s, since it scales to your actuall output resolution. Without this exact scaling option masks would get smeared etc. If using 1 pass shader and scaling isn’t defined (like source, 1x) it’s scaling to viewport anyway.

@hunterk as mentioned, i used the mipmap trick to calculate the “average color”. Working great. But i wanted to ask again about unshaded previous frames in GLSL as the only examples i found were in slang.

I guess defining extra options in presets isn’t needed. I tried with:

uniform sampler2D PassFeedback#


uniform sampler2D OriginalHistory#

Always returning current frame.


Feedback gives you access to a single shaded frame, while PrevXTexture gives you access to 7(?) previous unshaded frames:

uniform sampler2D PrevTexture; // previous frame
uniform sampler2D Prev1Texture;
uniform sampler2D Prev2Texture;
uniform sampler2D Prev3Texture;
uniform sampler2D Prev4Texture;
uniform sampler2D Prev5Texture;
uniform sampler2D Prev6Texture;

I don’t think you need to add anything to the preset for this to work. Just declare them alongside the normal ‘Texture’ and then call them up as normal.


Cool, thank you again guest!

By the way, I have finally achieved that hi-res look that I have been struggling with for increased IR stuff. Still using external methods (reshade) combined with RA for that, but I love the output.


I know we’re all excited about guest.r’s new shader, but has torridgristle’s recent work been converted to GLSL / added to the repository yet?


Settings please??? I’m really into how that looks.


Not yet. I was waiting until he’s completely finished with it, but if he is done with it, I just need to get the latest version from him.


The crt shader i’ve been forking on with dr. Venom got finished i guess. Afterglow was added, average luminance is calculated fast and pretty now (cheers @hunterk :+1:).

I was a bit tempted to use a lanczos filter for the shader since it looks nice with cgwg’s phosphor mask , but OTOH gaussian looks better with heavy lottes ones at low sharpness. Instead i added an option called “Substractive sharpness” which makes pixel edges more crisp (similar to cubic/lanczos) and it’s optional so don’t forget to tweak the shader.

I posted the shader here:

Thanks for the nice feedback/suggestions and happy crt-ing. :video_game::grinning:


@guest.r Awesome work. Would it be possible to also release a slang version?


Some screenshots from CRT Aperture,best CRT Shader for me


Yeah, I’ll get it slanged up pretty soon.

@TayTayo nice, one of my favorites, too :slight_smile:


@guest.r @hunterk

Is this supposed to happen? Using the latest version of the shader. Happens with every game i’ve tried whenever there is movement on the screen.


Hmm, looks like the raster bloom is going a little bonkers.


Needs more mask and integer scale IMO, but that’s a nice shader. I think it really needs 4k to shine, though.

Without the mask, shaders always look too smooth and not right at all to me. Without integer scaling you get scaling artifacts and odd looking scanlines, although some shaders are better at handling non-integer scales than others (scanline.glsl and CRT-Easymode are the best for non-integer scales)


I set Blooming to 0.0 as default, this makes it also usable with integer scaling (makes bonkering go away). Strangely i tested it on an AMD and nVidia system and it went fine. You can re-download the shaders at same link as before. If anyone else experiences the same issue then i’ll have to think it out.