Lightweight CRT Effect

This shader is a lightweight and optimized CRT effect, designed to balance visual quality and performance. I originally created it for a mobile game, as most CRT shaders I tried were too resource-intensive and drained the battery too quickly.

This shader offers a subtle CRT look while remaining efficient, making it ideal for mobile devices or performance-sensitive projects. Several parameters allow you to fine-tune the effect to match your needs:

  • scan_line_amount – Adjusts the intensity of scanlines.
  • warp_amount – Controls screen curvature distortion.
  • vignette_amount & vignette_intensity – Fine-tunes the vignette effect.
  • grille_amount – Simulates a pixel grid for a retro feel.
  • brightness_boost – Enhances screen brightness.

How to Apply the Shader:

  1. Create a CanvasLayer at the top of your scene to ensure the effect is applied globally.
  2. Add a ColorRect node as a child of the CanvasLayer.
  3. Set the ColorRect size to match the screen resolution.
  4. Apply the CRT shader to the ColorRect’s material.
  5. Enable “Expand” to ensure it covers the screen.
Shader code
shader_type canvas_item;

uniform sampler2D SCREEN_TEXTURE : hint_screen_texture;
uniform vec2 resolution = vec2(320.0, 180.0);

uniform float scan_line_amount : hint_range(0.0, 1.0) = 0.5;
uniform float warp_amount : hint_range(0.0, 1.0) = 0.05;
uniform float vignette_amount : hint_range(0.0, 1.0) = 0.5;
uniform float vignette_intensity : hint_range(0.0, 1.0) = 0.3;
uniform float grille_amount : hint_range(0.0, 1.0) = 0.05;
uniform float brightness_boost : hint_range(1.0, 2.0) = 1.2;

void fragment() {
    vec2 uv = SCREEN_UV;
    
    vec2 delta = uv - 0.5;
    float warp_factor = dot(delta, delta) * warp_amount;
    uv += delta * warp_factor;
    
    float scanline = sin(uv.y * resolution.y * PI) * 0.5 + 0.5;
    scanline = mix(1.0, scanline, scan_line_amount * 0.5); // Réduit l'impact
    
    float grille = mod(uv.x * resolution.x, 3.0) < 1.5 ? 0.95 : 1.05;
    grille = mix(1.0, grille, grille_amount * 0.5);
    
    vec3 color = texture(SCREEN_TEXTURE, uv).rgb * scanline * grille;
    
    vec2 v_uv = uv * (1.0 - uv.xy);
    float vignette = v_uv.x * v_uv.y * 15.0;
    vignette = mix(1.0, vignette, vignette_amount * 0.7);

    color *= vignette * brightness_boost;

    COLOR.rgb = color;
    COLOR.a = 1.0;
}
Live Preview
Tags
2d, CRT, mobile
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

Related shaders

guest

4 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Frogman
Frogman
10 months ago

amazing CRT shader, best one yet IMO. however, there does seem to be a bit of a blurry artifact due to the shader, which idk if thats changable but its nice none the less

also, would be nice to add a black border when you up the warp amount, so it doesnt stretch on the edges 🙂

8/10 😀

beebster
9 months ago

Nice one, definitely reduces the load on mobile GPU. In fact I commented out other effects and just kept scanline to shave a fraction more off.

Scrython
Scrython
2 months ago

I just wanna say – this is THE BEST CTR SHADER out there!! I had lots of trouble with the other ones, but this one works so well, and is so simple! Thanks!!