Random 2D Lightning Strikes

This shader creates a realistic lightning strike effect on a Sprite2D in Godot 4. It simulates multiple lightning bolts appearing randomly with a diffuse glow effect, making the lightning look natural and dynamic. The shader parameters allow for customization of the lightning’s appearance, frequency, and glow intensity.

Parameters

  • lightning_color (vec4): Defines the color and transparency of the lightning.
    • Default: vec4(0.97, 0.89, 0.85, 0.65)
  • size (float): Controls the thickness of the lightning bolts.
    • Range: 0.0 to 1.0
    • Default: 0.005
  • width (float): Adjusts the width of the lightning bolts.
    • Range: 0.0 to 1.0
    • Default: 0.4
  • speed (float): Determines the speed at which the lightning strikes animate.
    • Default: 1.0
  • cycle (float): Controls the frequency of the lightning pattern repetition.
    • Default: 0.17
  • ratio (float): Modifies the randomness of the lightning strikes’ blinking on and off.
    • Default: 3.0
  • time_shift (float): Adds an additional time offset to the lightning animation for more variation.
    • Default: 0.5
  • strike_count (int): Specifies the number of lightning strikes to display.
    • Default: 5
  • strike_delay (float): Sets the delay between each lightning strike to make the strikes more perceptible.
    • Default: 0.25
  • glow_intensity (float): Adjusts the intensity of the glow effect around the lightning bolts.
    • Range: 0.0 to 1.0
    • Default: 0.9

 

Shader code
shader_type canvas_item;

uniform vec4 lightning_color : source_color = vec4(0.97, 0.89, 0.85, 0.65);
uniform float size : hint_range(0.0, 1.0) = 0.005;
uniform float width : hint_range(0.0, 1.0) = 0.4;
uniform float speed = 1.0;
uniform float cycle = 0.17;
uniform float ratio = 3.0;
uniform float time_shift = 0.5;
uniform int strike_count = 5;
uniform float strike_delay = 0.25;
uniform float glow_intensity : hint_range(0.0, 1.0) = 0.9;

float rand(float x) {
    return fract(sin(x) * 100000.0);
}

void fragment() {
    float wave = 0.0;
    float time = TIME * speed;

    for (int i = 0; i < strike_count; i++) {
        float strike_offset = float(i) / float(strike_count);
        float strike_time = floor(time / strike_delay) + strike_offset;
        float strike_phase = mod(time, strike_delay) / strike_delay;

        // Delay the strike based on its offset
        if (strike_phase < strike_offset) {
            continue;
        }

        float bolt = abs(mod(UV.y * cycle + (rand(strike_time) + time_shift) * -1.0, 0.5) - 0.25) - 0.125;
        bolt *= 4.0 * width;

        bolt *= (0.5 - abs(UV.y - 0.5)) * 2.0;

        float strike_position = rand(strike_time * 10.0) - 0.5;
        float lightning = 1.0 - step(size * 0.5, abs(UV.x - 0.5 + strike_position + bolt));
        wave += lightning;
    }

    wave = clamp(wave, 0.0, 1.0);

    // Make strikes blink on and off
    float blink = step(rand(floor(time / strike_delay)) * ratio, 0.5);
    wave *= blink;

    // Create a radial gradient for the glow effect
    float dist = distance(UV, vec2(0.5, 0.5));
    float glow = smoothstep(0.0, glow_intensity, 1.0 - dist);

    vec4 display = lightning_color * vec4(wave);
    display.rgb += glow * lightning_color.rgb * wave;

    COLOR = vec4(display.rgb, display.a * wave);
}
Tags
2d, lightning, lightning strike, storm, thunderstorm
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

2D lightning

2D Lightning, Electric Arc, plasma

Lightning Ball

Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments