Realistic Motion blur in Godot? [Need Help]

Godot Version

4.1 or later

Question

Hi, I am creating a horror game, I want to add motion blur in my game. I added it. But I want to off motion blur while walking, so overall question is how can I create realistic motion blur like unreal engine.
Here is the codes:

shader_type spatial;
render_mode depth_test_disabled, depth_draw_never, unshaded, cull_disabled;

uniform vec3 linear_velocity; 
uniform vec3 angular_velocity; //rads
uniform int iteration_count : hint_range(2, 50);
uniform float intensity : hint_range(0, 1);
uniform float startRadius;

uniform sampler2D DEPTH_TEXTURE : hint_depth_texture, filter_linear_mipmap, repeat_disable;
uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap, repeat_disable;

void fragment()
{ 
	float depth = texture(DEPTH_TEXTURE, SCREEN_UV).r;
	
	//Turn the current pixel from ndc to world coordinates
	vec3 pixel_pos_ndc = vec3(SCREEN_UV*2.0-1.0, depth*2.0-1.0); 
    vec4 pixel_pos_clip = INV_PROJECTION_MATRIX * vec4(pixel_pos_ndc,1.0);
    vec3 pixel_pos_cam = pixel_pos_clip.xyz / pixel_pos_clip.w;
	vec3 pixel_pos_world = (inverse(INV_VIEW_MATRIX) * vec4(pixel_pos_cam, 1.0)).xyz;
	
	//Calculate total velocity which combines linear velocity and angular velocity
	vec3 cam_pos = inverse(INV_VIEW_MATRIX)[3].xyz; //Correct
	vec3 r = pixel_pos_world - cam_pos;
	vec3 total_velocity = linear_velocity + cross(angular_velocity, r);
	
	//Offset the world pos by the total velocity, then project back to ndc coordinates
	vec3 pixel_prevpos_world = pixel_pos_world - total_velocity;
	vec3 pixel_prevpos_cam =  ((INV_VIEW_MATRIX) * vec4(pixel_prevpos_world, 1.0)).xyz;
	vec4 pixel_prevpos_clip =  PROJECTION_MATRIX * vec4(pixel_prevpos_cam, 1.0);
	vec3 pixel_prevpos_ndc = pixel_prevpos_clip.xyz / pixel_prevpos_clip.w;
	
	//Calculate how much the pixel moved in ndc space
	vec2 pixel_diff_ndc = pixel_prevpos_ndc.xy - pixel_pos_ndc.xy; 
	
	vec3 col = vec3(0.0);
	float counter = 0.0;
	if(length(r) >= startRadius){
		for (int i = 0; i < iteration_count; i++)
		{
			vec2 offset = pixel_diff_ndc * (float(i) / float(iteration_count) - 0.5) * intensity; 
			col += textureLod(SCREEN_TEXTURE, SCREEN_UV + offset,0.0).rgb;
			counter++;
		}
		ALBEDO = col / counter;
	}
	else
		ALBEDO = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0).rgb;
}

i think just put conditional if variable on your shader code, and have that variable be a uniform, so you can set it on and off, whether to motion blur or not? else load the gdshader or shadermaterial as a resource then reapply the motion blur when needed, else set the shader material to null

1 Like

Thanks I will do it with shader and I have tried with gdscript but its not looking good, feels like the screen reduce a little bit of brightness

1 Like