Cheap Scanlines Effect Tutorial: Real-Time GPU Methods
What this tutorial covers
- Goal: create a cheap, fast scanlines effect that runs in real time on the GPU for games, live visuals, or video playback.
- Targets: fragment shader implementations (GLSL/HLSL), simple Unity and Unreal material setups, and performance tips.
Core approach (single-pass fragment shader)
- Sample the input texture (screen UVs).
- Compute a scanline modulation factor using the fragment’s screen Y coordinate.
- Blend the modulation with the sampled color (multiply or mix).
- Optionally add jitter, color bleed, and subpixel offsets for realism.
Example GLSL fragment shader (WebGL/OpenGL ES compatible):
glsl
precision mediump float; uniform sampler2D u_tex; uniform float u_scanlineWidth;// e.g., 2.0 uniform float u_intensity; // 0.0 - 1.0 uniform float u_time; // for optional jitter varying vec2 v_uv; void main() { vec4 color = texture2D(u_tex, v_uv); // Normalize screen Y to pixel rows float rows = float(u_scanlineWidth); float y = v_uv.y * rows; // Create repeating band pattern float band = fract(y); // Optional jitter per-row float jitter = 0.0; // jitter = 0.1 * sin(u_time + floor(y) * 0.7); // Compute modulation: darker on band < 0.5 float mod = smoothstep(0.0, 0.5, band + jitter) (1.0 - smoothstep(0.5, 1.0, band + jitter)); mod = 1.0 - mod; // invert so center of band is darker // Combine with intensity float factor = mix(1.0, mod, u_intensity); gl_FragColor = vec4(color.rgb factor, color.a); }
Unity (URP/HDRP) quick material setup
- Create an Unlit shader with the fragment logic above or use Shader Graph:
- Sample Screen Position or UV.
- Use a Repeat/Modulo on Y to form bands.
- Remap and smooth (SmoothStep).
- Multiply color and expose Width and Intensity properties.
- Apply as a full-screen post-process or as a UI overlay for minimal cost.
Unreal Engine (Material)
- In a post-process material:
- Use ScreenPosition node (use raw UV Y).
- Multiply by a scalar “Scanline Density”.
- Apply Fraction (Frac) and Smoothstep to shape bands.
- Lerp between 1 and darkened factor using Intensity.
- Use a single multiply with the scene color to keep it cheap.
Variations & realism tricks
- Subpixel color offsets: shift R/G/B by small UV offsets per row for chromatic feel.
- Horizontal noise/jitter: add a small per-row horizontal offset using a hash of floor(y).
- Alpha blend overlay vs multiply: overlay preserves highlights; multiply is darker.
- Vary density with resolution: scale density by screen height to keep look consistent.
- Use a black/transparent texture (1D) if shader math isn’t available — sample and blend.
Performance tips
- Keep it in a single fragment pass; avoid branching.
- Use smoothstep and fract (GPU-friendly).
- Compute per-pixel only simple math; avoid extra texture fetches.
- For mobile, reduce precision and lower scanline density.
- Apply as screen-space post-process; avoid per-object materials unless needed.
Parameters to expose
- Scanline Density (rows per screen)
- Intensity (0–1)
- Width/Softness (smoothstep thresholds)
- Chromatic Offset (R/G/B shift)
- Jitter Amount and Speed
Quick recipe (three knobs)
- Set Density to screenHeight / 4 for obvious lines.
- Intensity = 0.4 for subtle effect.
- Width/Softness = 0.15 for smooth bands.
Date: February 7, 2026
Leave a Reply