Gaussian blur for Godot 4.3 Canvase layer

I made it with Chat GPT … I don’t know how it works … but i know that Chat GPT needed alot of help to get here so here you go …

 

EDIT: the one pass shader made my fps go down from 700 to 16 … so i updated it to 2 pass shader and a static kernel … this got things back up to 400 fps … not great for a blur but this is my best

you will have to create a canvase stack and 2 shader one vertical and the other horzantail … it is a smiple uncomment in the code … I also added a soft blur transtion to non blured … the varubles are exproted and the preview tells the full story …

2025/01/04 edit: godot 4.5
fixed the Horizontal blur being a veritcal blur 

notes:
– if you are looking for a static 5 pixel Gaussian blur just go with godot documented shader 
godot shader docs
after testing this shader drops the fps at 5 pixels from 600 to 300 while godot shader holds it at 400
– both shaders tank fps from 70 to 10 on moblie so they are not recommended
– using this shader in two passes causes major problems with button and ui, espcially when using custom viewports, even after looking into the layer order in the scene tree or the canvas custome proparty
– this shader breaks when used in viewports, it simply show a dark side untile you change the window size a bunch (shaking the game viewport in engine) then it start working, and somtimes it just works then breaks when the viewport size changes, most importantly it is broken in a relese build 

though i am dropping the effect in my project because none of the gaussian blur effects tested had good proformnacei still know that it can be done as unreal has an blur effect that has almost no impact on proformance, so it can be done I just don’t know how 

Shader code
// A Gaussian blur shader for Godot 4.3 - 4.5
shader_type canvas_item;


uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap;

// The radius of the blur effect (number of pixels to blur, NOT USED).
uniform int blur_radius : hint_range(1, 32) = 8;

// Controls the intensity of the blur. (NOT USED)
uniform float blur_strength : hint_range(0.1, 10.0) = 10.0;

// Direction of the fade: 0 = left, 1 = right, 2 = top, 3 = bottom.
uniform int fade_direction : hint_range(0, 3) = 0;

// Sets the cutoff point for the blur fade (0.0 to 1.0).
uniform float fade_cutoff : hint_range(0.0, 1.0) = 0.2;

// Controls the sharpness of the fade transition.
uniform float fade_intensity : hint_range(0.1, 10.0) = 2.0;


// Precomputed weights for the Gaussian kernel. (NOT USED)
float gaussian_weight(float i, float sigma) {
    return exp(-0.5 * (i * i) / (sigma * sigma));
}

// Precomputes the weights for the Gaussian kernel.
void calculate_kernel(out float kernel[32], int radius, float sigma) {
    float sum = 0.0;
    for (int i = 0; i <= radius; i++) {
        kernel[i] = gaussian_weight(float(i), sigma);
        sum += i == 0 ? kernel[i] : 2.0 * kernel[i];
    }
    for (int i = 0; i <= radius; i++) {
        kernel[i] /= sum;
    }
}

// Computes the fade factor based on the direction and UV coordinates.
float calculate_fade(vec2 uv) {
    float fade = 0.0;
    if (fade_direction == 0) {
        fade = uv.x; // Left to right
    } else if (fade_direction == 1) {
        fade = 1.0 - uv.x; // Right to left
    } else if (fade_direction == 2) {
        fade = uv.y; // Top to bottom
    } else {
        fade = 1.0 - uv.y; // Bottom to top
    }

    // Normalize fade based on cutoff and intensity.
    if (fade < fade_cutoff) {
        return 1.0; // Full blur
    }

    // Scale fade factor smoothly to 0 at the edge.
    fade = (fade - fade_cutoff) / (1.0 - fade_cutoff);
    return clamp(pow(1.0 - fade*2.0, fade_intensity), 0.0, 1.0);
}




void fragment() {
    vec2 resolution = SCREEN_PIXEL_SIZE;
    vec2 uv = SCREEN_UV;


	// Calculate the fade factor.
    float fade_factor = calculate_fade(uv);
    // Gaussian kernel weights.
    float kernel[32] ;//= gaussian_32; // remove this varuble and enable the next line
    calculate_kernel(kernel, blur_radius, blur_strength);

	 vec4 final_color = vec4(0.0);

    // Horizontal blur pass.
    //for (int i = -blur_radius; i <= blur_radius; i++) {
        //final_color += texture(SCREEN_TEXTURE, uv + vec2(float(i),0.0) * resolution, 0.0).rgba * kernel[abs(i)];
    //}


    // Vertical blur pass.
    //for (int i = -blur_radius; i <= blur_radius; i++) {
        //final_color += texture(SCREEN_TEXTURE, uv + vec2(0.0, float(i)) * resolution).rgba * kernel[abs(i)];
    //}


	//One pass blur ... ***VERY BAD PROFORMANCE***
    for (int x = -blur_radius; x <= blur_radius; x++) {
        for (int y = -blur_radius; y <= blur_radius; y++) {
            float weight = kernel[abs(x)] * kernel[abs(y)];
            vec2 offset = vec2(float(x), float(y)) * resolution;
            final_color += texture(SCREEN_TEXTURE, uv + offset).rgba * weight;
        }
    }

    // Output the blurred color.
	final_color.a = fade_factor;
	COLOR = final_color;
}
Live Preview
Tags
blur, gaussian blur
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

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
michael hunt
michael hunt
8 months ago

“i used chatgpt and it runs bad” what a shock