God Rays shader – inspired by pend00 – Godot 4.5

a godot 4.5 version of the god rays created by pend00

Instructions
This shader is all code, no noise textures. So just paste the code into a new shader for a Sprite node or a ColorRect. Sprite nodes need a base texture.

  • Angle – The angle of the rays.
  • Position – Move the rays left and right.
  • Spread – Should the rays be parallel or spread out.
  • Cut off – The width of the effect.
  • Fall off – Fade to transparent towards the bottom.
  • Edge fade – The edges can be sharp or blurry.
  • Speed – Speed of the “shimmer” animation.
  • Ray 1 density – The effect has two layers of rays. This is how compact the back layer is, e.g how close together the gaps are. For best effect have the Ray 1 be wide and Ray 2 more compact.
  • Ray 2 density – This is how compact the top layer is.
  • Ray 2 intensity – Opacity of the top layer.
Shader code
shader_type canvas_item;

uniform float ray_angle = -0.3;
uniform float ray_position = -0.2;
uniform float spread : hint_range(0.0, 1.0) = 0.5;
uniform float cutoff : hint_range(-1.0, 1.0) = 0.1;
uniform float falloff : hint_range(0.0, 1.0) = 0.2;
uniform float edge_fade : hint_range(0.0, 1.0) = 0.15;

uniform float speed = 1.0;
uniform float ray1_density = 8.0;
uniform float ray2_density = 30.0;
uniform float ray2_intensity : hint_range(0.0, 1.0) = 0.3;

uniform vec4 color = vec4(1.0, 0.9, 0.65, 0.8);

uniform bool hdr = false;
uniform float seed = 5.0;


uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap;

float random(vec2 uv) {
    return fract(sin(dot(uv, vec2(12.9898, 78.233))) * 43758.5453123);
}


float noise(vec2 uv) {
    vec2 i = floor(uv);
    vec2 f = fract(uv);
    
    float a = random(i);
    float b = random(i + vec2(1.0, 0.0));
    float c = random(i + vec2(0.0, 1.0));
    float d = random(i + vec2(1.0, 1.0));
    
    vec2 u = f * f * (3.0 - 2.0 * f);
    
    return mix(mix(a, b, u.x), mix(c, d, u.x), u.y);
}


mat2 create_rotation_matrix(float rot_angle) {
    float s = sin(rot_angle);
    float c = cos(rot_angle);
    return mat2(vec2(c, -s), vec2(s, c));
}


vec3 screen_blend(vec3 base, vec3 blend) {
    return 1.0 - (1.0 - base) * (1.0 - blend);
}

void fragment() {

    vec2 centered_uv = UV - vec2(0.5, ray_position);
    vec2 transformed_uv = create_rotation_matrix(ray_angle) * centered_uv;
    

    transformed_uv.y = transformed_uv.y / (transformed_uv.y * spread + 1.0);
    transformed_uv += vec2(0.5);
    
    float time_factor = TIME * speed;
    vec2 ray1_uv = vec2(
        transformed_uv.x * ray1_density + sin(time_factor * 0.1) * (ray1_density * 0.2) + seed,
        transformed_uv.y
    );
    
    vec2 ray2_uv = vec2(
        transformed_uv.x * ray2_density + sin(time_factor * 0.2) * (ray1_density * 0.2) + seed,
        transformed_uv.y
    );
    
    float cut_x = smoothstep(cutoff - 0.1, cutoff + 0.1, transformed_uv.x) * 
                 smoothstep(1.0 + cutoff + 0.1, 1.0 + cutoff - 0.1, transformed_uv.x);

    float ray1 = noise(ray1_uv);
    float ray2 = noise(ray2_uv) * ray2_intensity;
    
    float rays;
    if (hdr) {
        rays = ray1 + ray2;
    } else {
        rays = clamp(ray1 + ray2, 0.0, 1.0);
    }
    

    rays *= cut_x;
    rays *= smoothstep(0.0, falloff, 1.0 - UV.y);
    rays *= smoothstep(0.0, edge_fade, transformed_uv.x);
    rays *= smoothstep(0.0, edge_fade, 1.0 - transformed_uv.x);
    

    vec3 final_color = vec3(rays) * color.rgb;

    vec3 screen_color = texture(SCREEN_TEXTURE, SCREEN_UV).rgb;
    final_color = screen_blend(screen_color, final_color * color.a);
    
    COLOR = vec4(final_color, rays * color.a);
}
Live Preview
Tags
effect, Enviroment, light, shine
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

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments