From 260e5ec88aff418485b8e1a3b6ebdca9c3a12092 Mon Sep 17 00:00:00 2001 From: sphynx-owner Date: Wed, 14 Aug 2024 23:10:32 +0300 Subject: [PATCH] Multiple fixes, Higher blur Quality - better blending - handle velocity buffer projection edge case - handle blur edge cases --- .../BaseClasses/enhanced_compositor_effect.gd | 91 +++++- .../BaseClasses/mb_compositor_effect.gd | 26 +- .../Debug/ShaderFiles/debug_overlay.glsl | 30 +- .../Debug/post_process_debug.gd | 12 +- .../ShaderFiles/guertin_kino_blur.glsl | 49 +-- .../Guertin/base_guertin_motion_blur.gd | 12 + .../Guertin/guertin_motion_blur.gd | 48 +-- .../ShaderFiles/jf_guertin_tile_max_x.glsl | 15 +- .../ShaderFiles/jf_guertin_tile_max_y.glsl | 10 +- .../ShaderFiles/jf_neighbor_depth_max.glsl | 63 ++++ .../jf_neighbor_depth_max.glsl.import | 14 + .../ShaderFiles/jf_neighbor_max.glsl | 19 +- .../JumpFlood/ShaderFiles/jfp_simple.glsl | 99 +++--- .../ShaderFiles/jump_flood_blur.glsl | 8 - .../ShaderFiles/jump_flood_cache.glsl | 45 +++ .../ShaderFiles/jump_flood_cache.glsl.import | 14 + ...glsl => jump_flood_experimental_blur.glsl} | 69 ++-- .../jump_flood_experimental_blur.glsl.import | 14 + .../jump_flood_new_blur.glsl.import | 14 - .../jump_flood_realistic_blur.glsl | 292 +++++++++++++++++ .../jump_flood_realistic_blur.glsl.import | 14 + .../ShaderFiles/jump_flood_simple_blur.glsl | 240 ++++++++++++++ .../jump_flood_simple_blur.glsl.import | 14 + .../JumpFlood/base_jump_flood_motion_blur.gd | 26 ++ .../JumpFlood/experimental_jf_motion_blur.gd | 298 ++++++++++++++++++ .../experimental_jump_flood_blur_stage.tres | 8 + .../JumpFlood/jump_flood_cache_stage.tres | 8 + .../JumpFlood/jump_flood_motion_blur.gd | 100 +----- .../JumpFlood/realistic_jf_blur_stage.tres | 8 + .../JumpFlood/realistic_jf_motion_blur.gd | 268 ++++++++++++++++ .../JumpFlood/simple_jf_blur_stage.tres | 2 +- .../JumpFlood/simple_jf_motion_blur.gd | 114 +------ addons/SphynxMotionBlurToolkit/LICENSE | 21 ++ .../LinearMotionBlurMesh.gdshader | 152 +++++++++ .../LinearMotionBlurMesh.tscn | 21 ++ .../linear_motion_blur_mesh.gd | 63 ++++ .../McGuire/ShaderFiles/mcguire_blur.glsl | 6 +- .../McGuire/base_mcguire_motion_blur.gd | 4 + .../McGuire/mcguire_motion_blur.gd | 28 +- .../default_camera_movement_component.tres | 9 + .../default_camera_rotation_component.tres | 9 + ...=> default_object_movement_component.tres} | 0 .../PreBlurProcessing/pre_blur_processor.gd | 11 +- .../PreBlurProcessing/pre_blur_processor.glsl | 16 +- .../RadialBlurToolkit/radial_blur_mesh.tscn | 4 +- 45 files changed, 1954 insertions(+), 434 deletions(-) create mode 100644 addons/SphynxMotionBlurToolkit/Guertin/base_guertin_motion_blur.gd create mode 100644 addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_neighbor_depth_max.glsl create mode 100644 addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_neighbor_depth_max.glsl.import create mode 100644 addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_cache.glsl create mode 100644 addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_cache.glsl.import rename addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/{jump_flood_new_blur.glsl => jump_flood_experimental_blur.glsl} (80%) create mode 100644 addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_experimental_blur.glsl.import delete mode 100644 addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_new_blur.glsl.import create mode 100644 addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_realistic_blur.glsl create mode 100644 addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_realistic_blur.glsl.import create mode 100644 addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_simple_blur.glsl create mode 100644 addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_simple_blur.glsl.import create mode 100644 addons/SphynxMotionBlurToolkit/JumpFlood/base_jump_flood_motion_blur.gd create mode 100644 addons/SphynxMotionBlurToolkit/JumpFlood/experimental_jf_motion_blur.gd create mode 100644 addons/SphynxMotionBlurToolkit/JumpFlood/experimental_jump_flood_blur_stage.tres create mode 100644 addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_cache_stage.tres create mode 100644 addons/SphynxMotionBlurToolkit/JumpFlood/realistic_jf_blur_stage.tres create mode 100644 addons/SphynxMotionBlurToolkit/JumpFlood/realistic_jf_motion_blur.gd create mode 100644 addons/SphynxMotionBlurToolkit/LICENSE create mode 100644 addons/SphynxMotionBlurToolkit/LinearBlurToolkit/LinearMotionBlurMesh.gdshader create mode 100644 addons/SphynxMotionBlurToolkit/LinearBlurToolkit/LinearMotionBlurMesh.tscn create mode 100644 addons/SphynxMotionBlurToolkit/LinearBlurToolkit/linear_motion_blur_mesh.gd create mode 100644 addons/SphynxMotionBlurToolkit/McGuire/base_mcguire_motion_blur.gd create mode 100644 addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_camera_movement_component.tres create mode 100644 addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_camera_rotation_component.tres rename addons/SphynxMotionBlurToolkit/PreBlurProcessing/{default_component.tres => default_object_movement_component.tres} (100%) diff --git a/addons/SphynxMotionBlurToolkit/BaseClasses/enhanced_compositor_effect.gd b/addons/SphynxMotionBlurToolkit/BaseClasses/enhanced_compositor_effect.gd index 07d925d..0306df3 100644 --- a/addons/SphynxMotionBlurToolkit/BaseClasses/enhanced_compositor_effect.gd +++ b/addons/SphynxMotionBlurToolkit/BaseClasses/enhanced_compositor_effect.gd @@ -1,5 +1,4 @@ extends CompositorEffect -class_name EnhancedCompositorEffect var rd: RenderingDevice @@ -11,6 +10,26 @@ var context: StringName = "PostProcess" var all_shader_stages : Dictionary +@export var debug : bool = false: + set(value): + if(debug == value): + return + + debug = value + free_shaders.call_deferred() + generate_shaders.call_deferred() + +var debug_1 : String = "debug_1" +var debug_2 : String = "debug_2" +var debug_3 : String = "debug_3" +var debug_4 : String = "debug_4" +var debug_5 : String = "debug_5" +var debug_6 : String = "debug_6" +var debug_7 : String = "debug_7" +var debug_8 : String = "debug_8" + +var all_debug_images : Array[RID] + func _init(): RenderingServer.call_on_render_thread(_initialize_compute) @@ -28,6 +47,18 @@ func _notification(what): if shader_stage.shader.is_valid(): rd.free_rid(shader_stage.shader) +func free_shaders(): + for shader_stage in all_shader_stages.keys(): + if shader_stage.pipeline.is_valid(): + rd.free_rid(shader_stage.pipeline) + if shader_stage.shader.is_valid(): + rd.free_rid(shader_stage.shader) + +func generate_shaders(): + for shader_stage in all_shader_stages.keys(): + generate_shader_stage(shader_stage) + + func subscirbe_shader_stage(shader_stage : ShaderStageResource): if all_shader_stages.has(shader_stage): return @@ -70,11 +101,35 @@ func _initialize_compute(): nearest_sampler = rd.sampler_create(sampler_state) - for shader_stage in all_shader_stages.keys(): - generate_shader_stage(shader_stage) + generate_shaders() + func generate_shader_stage(shader_stage : ShaderStageResource): - var shader_spirv : RDShaderSPIRV = shader_stage.shader_file.get_spirv() + var shader_spirv : RDShaderSPIRV + if debug: + var file = FileAccess.open(shader_stage.shader_file.resource_path, FileAccess.READ) + var split_shader : PackedStringArray = file.get_as_text().split("#[compute]", true, 1) + var content : String = split_shader[min(1, split_shader.size() - 1)] + var all_split_parts : PackedStringArray = content.split("#version 450", true, 1) + content = str(all_split_parts[0], + "#version 450 +#define DEBUG +layout(rgba16f, set = 0, binding = 10) uniform image2D debug_1_image; +layout(rgba16f, set = 0, binding = 11) uniform image2D debug_2_image; +layout(rgba16f, set = 0, binding = 12) uniform image2D debug_3_image; +layout(rgba16f, set = 0, binding = 13) uniform image2D debug_4_image; +layout(rgba16f, set = 0, binding = 14) uniform image2D debug_5_image; +layout(rgba16f, set = 0, binding = 15) uniform image2D debug_6_image; +layout(rgba16f, set = 0, binding = 16) uniform image2D debug_7_image; +layout(rgba16f, set = 0, binding = 17) uniform image2D debug_8_image;", + all_split_parts[1]) + var shader_source : RDShaderSource = RDShaderSource.new() + shader_source.set_stage_source(RenderingDevice.SHADER_STAGE_COMPUTE, content) + shader_spirv = rd.shader_compile_spirv_from_source(shader_source, false) + print(content) + else: + shader_spirv = shader_stage.shader_file.get_spirv() + shader_stage.shader = rd.shader_create_from_spirv(shader_spirv) shader_stage.pipeline = rd.compute_pipeline_create(shader_stage.shader) @@ -91,9 +146,32 @@ func _render_callback(p_effect_callback_type, p_render_data): if render_size.x == 0 or render_size.y == 0: return + + if debug: + ensure_texture(debug_1, render_scene_buffers) + ensure_texture(debug_2, render_scene_buffers) + ensure_texture(debug_3, render_scene_buffers) + ensure_texture(debug_4, render_scene_buffers) + ensure_texture(debug_5, render_scene_buffers) + ensure_texture(debug_6, render_scene_buffers) + ensure_texture(debug_7, render_scene_buffers) + ensure_texture(debug_8, render_scene_buffers) + var view_count = render_scene_buffers.get_view_count() + + for view in range(view_count): + all_debug_images.append(render_scene_buffers.get_texture_slice(context, debug_1, view, 0, 1, 1)) + all_debug_images.append(render_scene_buffers.get_texture_slice(context, debug_2, view, 0, 1, 1)) + all_debug_images.append(render_scene_buffers.get_texture_slice(context, debug_3, view, 0, 1, 1)) + all_debug_images.append(render_scene_buffers.get_texture_slice(context, debug_4, view, 0, 1, 1)) + all_debug_images.append(render_scene_buffers.get_texture_slice(context, debug_5, view, 0, 1, 1)) + all_debug_images.append(render_scene_buffers.get_texture_slice(context, debug_6, view, 0, 1, 1)) + all_debug_images.append(render_scene_buffers.get_texture_slice(context, debug_7, view, 0, 1, 1)) + all_debug_images.append(render_scene_buffers.get_texture_slice(context, debug_8, view, 0, 1, 1)) _render_callback_2(render_size, render_scene_buffers, render_scene_data) + + all_debug_images.clear() func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSceneBuffersRD, render_scene_data : RenderSceneDataRD): pass @@ -128,6 +206,11 @@ func get_sampler_uniform(image: RID, binding: int, linear : bool = true) -> RDUn func dispatch_stage(stage : ShaderStageResource, uniforms : Array[RDUniform], push_constants : PackedByteArray, dispatch_size : Vector3i, label : String = "DefaultLabel", view : int = 0, color : Color = Color(1, 1, 1, 1)): rd.draw_command_begin_label(label + " " + str(view), color) + if debug: + for i in 8: + var debug_image_index = i + view * 8; + uniforms.append(get_image_uniform(all_debug_images[debug_image_index], 10 + i)) + var tex_uniform_set = UniformSetCacheRD.get_cache(stage.shader, 0, uniforms) var compute_list = rd.compute_list_begin() diff --git a/addons/SphynxMotionBlurToolkit/BaseClasses/mb_compositor_effect.gd b/addons/SphynxMotionBlurToolkit/BaseClasses/mb_compositor_effect.gd index f7b9175..bc2743c 100644 --- a/addons/SphynxMotionBlurToolkit/BaseClasses/mb_compositor_effect.gd +++ b/addons/SphynxMotionBlurToolkit/BaseClasses/mb_compositor_effect.gd @@ -1,5 +1,27 @@ -extends EnhancedCompositorEffect -class_name MotionBlurCompositorEffect +extends "res://addons/SphynxMotionBlurToolkit/BaseClasses/enhanced_compositor_effect.gd" + +@export_group("Motion Blur") +# diminishing returns over 16 +@export_range(4, 64) var samples: int = 16 +# you really don't want this over 0.5, but you can if you want to try +@export_range(0, 0.5, 0.001, "or_greater") var intensity: float = 1 +@export_range(0, 1) var center_fade: float = 0.0 + +## wether this motion blur stays the same intensity below +## target_constant_framerate +@export var framerate_independent : bool = true + +## Description: Removes clamping on motion blur scale to allow framerate independent motion +## blur to scale longer than realistically possible when render framerate is higher +## than target framerate.[br][br] +## [color=yellow]Warning:[/color] Turning this on would allow over-blurring of pixels, which +## produces inaccurate results, and would likely cause nausea in players over +## long exposure durations, use with caution and out of artistic intent +@export var uncapped_independence : bool = false + +## if framerate_independent is enabled, the blur would simulate +## sutter speeds at that framerate, and up. +@export var target_constant_framerate : float = 30 func _init(): set_deferred("context", "MotionBlur") diff --git a/addons/SphynxMotionBlurToolkit/Debug/ShaderFiles/debug_overlay.glsl b/addons/SphynxMotionBlurToolkit/Debug/ShaderFiles/debug_overlay.glsl index 958ce73..196953e 100644 --- a/addons/SphynxMotionBlurToolkit/Debug/ShaderFiles/debug_overlay.glsl +++ b/addons/SphynxMotionBlurToolkit/Debug/ShaderFiles/debug_overlay.glsl @@ -9,14 +9,6 @@ layout(rgba16f, set = 0, binding = 0) uniform image2D past_color_image; layout(rgba16f, set = 0, binding = 1) uniform image2D output_color_image; layout(set = 0, binding = 2) uniform sampler2D color_sampler; -layout(set = 0, binding = 3) uniform sampler2D debug_sampler_1; -layout(set = 0, binding = 4) uniform sampler2D debug_sampler_2; -layout(set = 0, binding = 5) uniform sampler2D debug_sampler_3; -layout(set = 0, binding = 6) uniform sampler2D debug_sampler_4; -layout(set = 0, binding = 7) uniform sampler2D debug_sampler_5; -layout(set = 0, binding = 8) uniform sampler2D debug_sampler_6; -layout(set = 0, binding = 9) uniform sampler2D debug_sampler_7; -layout(set = 0, binding = 10) uniform sampler2D debug_sampler_8; layout(push_constant, std430) uniform Params { @@ -66,22 +58,24 @@ void main() vec4 bl_col; vec4 br_col; - + +#ifdef DEBUG if(params.debug_page == 0) { - tl_col = textureLod(debug_sampler_1, uvn, 0.0); - tr_col = textureLod(debug_sampler_2, uvn, 0.0); - bl_col = textureLod(debug_sampler_3, uvn, 0.0); - br_col = textureLod(debug_sampler_4, uvn, 0.0); + tl_col = imageLoad(debug_1_image, uvi); + tr_col = imageLoad(debug_2_image, uvi); + bl_col = imageLoad(debug_3_image, uvi); + br_col = imageLoad(debug_4_image, uvi); } if(params.debug_page == 1) { - tl_col = textureLod(debug_sampler_5, uvn, 0.0); - tr_col = textureLod(debug_sampler_6, uvn, 0.0); - bl_col = textureLod(debug_sampler_7, uvn, 0.0); - br_col = textureLod(debug_sampler_8, uvn, 0.0); + tl_col = imageLoad(debug_5_image, uvi); + tr_col = imageLoad(debug_6_image, uvi); + bl_col = imageLoad(debug_7_image, uvi); + br_col = imageLoad(debug_8_image, uvi); } - +#endif + imageStore(output_color_image, uvi / 2, tl_col); imageStore(output_color_image, uvi / 2 + ivec2(vec2(0.5, 0.5) * render_size), br_col); imageStore(output_color_image, uvi / 2 + ivec2(vec2(0.0, 0.5) * render_size), bl_col); diff --git a/addons/SphynxMotionBlurToolkit/Debug/post_process_debug.gd b/addons/SphynxMotionBlurToolkit/Debug/post_process_debug.gd index 7aefdd9..455fd9f 100644 --- a/addons/SphynxMotionBlurToolkit/Debug/post_process_debug.gd +++ b/addons/SphynxMotionBlurToolkit/Debug/post_process_debug.gd @@ -1,4 +1,4 @@ -extends EnhancedCompositorEffect +extends "res://addons/SphynxMotionBlurToolkit/BaseClasses/enhanced_compositor_effect.gd" class_name DebugCompositorEffect @export var overlay_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/Debug/debug_overlay_shader_stage.tres"): @@ -15,21 +15,13 @@ class_name DebugCompositorEffect ## and depth buffers debug views @export var debug_page : int = 0 -@export var debug_1 : String = "debug_1" -@export var debug_2 : String = "debug_2" -@export var debug_3 : String = "debug_3" -@export var debug_4 : String = "debug_4" -@export var debug_5 : String = "debug_5" -@export var debug_6 : String = "debug_6" -@export var debug_7 : String = "debug_7" -@export var debug_8 : String = "debug_8" - var past_color : StringName = "past_color" var freeze : bool = false func _init(): set_deferred("context", "MotionBlur") + set_deferred("debug", true) super() func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSceneBuffersRD, render_scene_data : RenderSceneDataRD): diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_kino_blur.glsl b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_kino_blur.glsl index 2b877e3..2a5b905 100644 --- a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_kino_blur.glsl +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_kino_blur.glsl @@ -6,16 +6,11 @@ #define M_PI 3.1415926535897932384626433832795 layout(set = 0, binding = 0) uniform sampler2D color_sampler; -layout(set = 0, binding = 1) uniform sampler2D depth_sampler; -layout(set = 0, binding = 2) uniform sampler2D velocity_sampler; -layout(set = 0, binding = 3) uniform sampler2D neighbor_max; -layout(set = 0, binding = 4) uniform sampler2D tile_variance; -layout(rgba16f, set = 0, binding = 5) uniform writeonly image2D output_color; -layout(rgba16f, set = 0, binding = 6) uniform image2D past_color_image; -layout(rgba16f, set = 0, binding = 6) uniform image2D debug_1_image; -layout(rgba16f, set = 0, binding = 7) uniform image2D debug_2_image; -layout(rgba16f, set = 0, binding = 8) uniform image2D debug_3_image; -layout(rgba16f, set = 0, binding = 9) uniform image2D debug_4_image; +layout(set = 0, binding = 1) uniform sampler2D velocity_sampler; +layout(set = 0, binding = 2) uniform sampler2D neighbor_max; +layout(set = 0, binding = 3) uniform sampler2D tile_variance; +layout(rgba16f, set = 0, binding = 4) uniform writeonly image2D output_color; + layout(push_constant, std430) uniform Params { @@ -53,7 +48,7 @@ float cylinder(float T, float v) // ---------------------------------------------------------- float z_compare(float a, float b, float sze) { - return clamp(1. - sze * (a - b) / min(a, b), 0, 1); + return clamp(1. - sze * (a - b), 0, 1); } // ---------------------------------------------------------- @@ -73,7 +68,7 @@ float interleaved_gradient_noise(vec2 uv){ vec2 safenorm(vec2 v) { float l = max(length(v), 1e-6); - return v / l * int(1 >= 0.5); + return v / l * int(l >= 0.5); } vec2 jitter_tile(vec2 uvi) @@ -100,7 +95,9 @@ void main() float j = interleaved_gradient_noise(uvi) * 2. - 1.; - vec2 vn = textureLod(neighbor_max, x + jitter_tile(uvi), 0.0).xy * render_size / 2.; + vec4 vnzw = textureLod(neighbor_max, x + jitter_tile(uvi), 0.0) * vec4(render_size / 2., 1, 1); + + vec2 vn = vnzw.xy; float vn_length = length(vn); @@ -109,16 +106,20 @@ void main() if(vn_length < 0.5) { imageStore(output_color, uvi, base_color); +#ifdef DEBUG imageStore(debug_1_image, uvi, base_color); imageStore(debug_2_image, uvi, vec4(vn / render_size * 2, 0, 1)); imageStore(debug_3_image, uvi, vec4(0)); imageStore(debug_4_image, uvi, vec4(0)); +#endif return; } vec2 wn = safenorm(vn); - vec2 vx = textureLod(velocity_sampler, x, 0.0).xy * render_size / 2.; + vec4 vxzw = textureLod(velocity_sampler, x, 0.0) * vec4(render_size / 2., 1, 1); + + vec2 vx = vxzw.xy; float vx_length = max(0.5, length(vx)); @@ -133,7 +134,7 @@ void main() vec2 wc = safenorm(mix(wp, wx, clamp((vx_length - 0.5) / params.minimum_user_threshold, 0, 1))); - float zx = -0.05 / max(FLT_MIN, textureLod(depth_sampler, x, 0.0).x); + float zx = vxzw.w; float total_weight = params.sample_count / (params.importance_bias * vx_length); @@ -145,6 +146,8 @@ void main() vec2 d = ((i % 2) > 0) ? vx : vn; + float dz = ((i % 2) > 0) ? vxzw.z : vnzw.z; + vec2 wd = safenorm(d); float T = abs(t * vn_length); @@ -153,14 +156,16 @@ void main() float wa = dot(wc, wd); - vec2 vy = textureLod(velocity_sampler, y, 0.0).xy * render_size / 2; + vec4 vyzw = textureLod(velocity_sampler, y, 0.0) * vec4(render_size / 2, 1, 1); + + vec2 vy = vyzw.xy - dz * t; float vy_length = max(0.5, length(vy)); - float zy = -0.05 / max(FLT_MIN, textureLod(depth_sampler, y, 0.0).x); + float zy = vyzw.w; - float f = z_compare(zy, zx, 15); - float b = z_compare(zx, zy, 15); + float f = z_compare(-zy, -zx, 20000); + float b = z_compare(-zx, -zy, 20000); float wb = abs(dot(vy / vy_length, wd)); @@ -177,8 +182,10 @@ void main() sum /= total_weight; imageStore(output_color, uvi, sum); +#ifdef DEBUG imageStore(debug_1_image, uvi, sum); imageStore(debug_2_image, uvi, vec4(vn / render_size * 2, 0, 1)); - imageStore(debug_3_image, uvi, vec4(0)); - imageStore(debug_4_image, uvi, vec4(0)); + imageStore(debug_3_image, uvi, vnzw); + imageStore(debug_4_image, uvi, vxzw); +#endif } \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/Guertin/base_guertin_motion_blur.gd b/addons/SphynxMotionBlurToolkit/Guertin/base_guertin_motion_blur.gd new file mode 100644 index 0000000..58c32e6 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/base_guertin_motion_blur.gd @@ -0,0 +1,12 @@ +extends "res://addons/SphynxMotionBlurToolkit/BaseClasses/mb_compositor_effect.gd" + +@export_group("Shader Parameters") +@export var tile_size : int = 40 + +@export var linear_falloff_slope : float = 1 + +@export var importance_bias : float = 40 + +@export var maximum_jitter_value : float = 0.95 + +@export var minimum_user_threshold : float = 1.5 diff --git a/addons/SphynxMotionBlurToolkit/Guertin/guertin_motion_blur.gd b/addons/SphynxMotionBlurToolkit/Guertin/guertin_motion_blur.gd index a4e879d..a284885 100644 --- a/addons/SphynxMotionBlurToolkit/Guertin/guertin_motion_blur.gd +++ b/addons/SphynxMotionBlurToolkit/Guertin/guertin_motion_blur.gd @@ -1,13 +1,7 @@ -extends MotionBlurCompositorEffect +extends "res://addons/SphynxMotionBlurToolkit/Guertin/base_guertin_motion_blur.gd" class_name GuertinMotionBlur -@export_group("Motion Blur", "motion_blur_") -# diminishing returns over 16 -@export_range(4, 64) var motion_blur_samples: int = 25 -# you really don't want this over 0.5, but you can if you want to try -@export_range(0, 0.5, 0.001, "or_greater") var motion_blur_intensity: float = 1 -@export_range(0, 1) var motion_blur_center_fade: float = 0.0 - +@export_group("Shader Stages") @export var blur_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/Guertin/guertin_blur_stage.tres"): set(value): unsubscribe_shader_stage(blur_stage) @@ -44,16 +38,6 @@ class_name GuertinMotionBlur tile_variance_stage = value subscirbe_shader_stage(value) -@export var tile_size : int = 40 - -@export var linear_falloff_slope : float = 1 - -@export var importance_bias : float = 40 - -@export var maximum_jitter_value : float = 0.95 - -@export var minimum_user_threshold : float = 1.5 - var output_color: StringName = "output_color" var tile_max_x : StringName = "tile_max_x" @@ -66,11 +50,6 @@ var tile_variance : StringName = "tile_variance" var custom_velocity : StringName = "custom_velocity" -var debug_1 : StringName = "debug_1" -var debug_2 : StringName = "debug_2" -var debug_3 : StringName = "debug_3" -var debug_4 : StringName = "debug_4" - var freeze : bool = false func _get_max_dilation_range() -> float: @@ -83,10 +62,6 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce ensure_texture(tile_variance, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / tile_size, 1. / tile_size)) ensure_texture(custom_velocity, render_scene_buffers) ensure_texture(output_color, render_scene_buffers) - ensure_texture(debug_1, render_scene_buffers) - ensure_texture(debug_2, render_scene_buffers) - ensure_texture(debug_3, render_scene_buffers) - ensure_texture(debug_4, render_scene_buffers) rd.draw_command_begin_label("Motion Blur", Color(1.0, 1.0, 1.0, 1.0)) @@ -158,7 +133,7 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce ] var int_blur_push_constants : PackedInt32Array = [ tile_size, - motion_blur_samples, + samples, Engine.get_frames_drawn() % 8, 0 ] @@ -176,10 +151,6 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce var neighbor_max_image := render_scene_buffers.get_texture_slice(context, neighbor_max, view, 0, 1, 1) var tile_variance_image := render_scene_buffers.get_texture_slice(context, tile_variance, view, 0, 1, 1) var custom_velocity_image := render_scene_buffers.get_texture_slice(context, custom_velocity, view, 0, 1, 1) - var debug_1_image := render_scene_buffers.get_texture_slice(context, debug_1, view, 0, 1, 1) - var debug_2_image := render_scene_buffers.get_texture_slice(context, debug_2, view, 0, 1, 1) - var debug_3_image := render_scene_buffers.get_texture_slice(context, debug_3, view, 0, 1, 1) - var debug_4_image := render_scene_buffers.get_texture_slice(context, debug_4, view, 0, 1, 1) var x_groups := floori((render_size.x / tile_size - 1) / 16 + 1) var y_groups := floori((render_size.y - 1) / 16 + 1) @@ -234,15 +205,10 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce dispatch_stage(blur_stage, [ get_sampler_uniform(color_image, 0, false), - get_sampler_uniform(depth_image, 1, false), - get_sampler_uniform(custom_velocity_image, 2, false), - get_sampler_uniform(neighbor_max_image, 3, false), - get_sampler_uniform(tile_variance_image, 4, true), - get_image_uniform(output_color_image, 5), - get_image_uniform(debug_1_image, 6), - get_image_uniform(debug_2_image, 7), - get_image_uniform(debug_3_image, 8), - get_image_uniform(debug_4_image, 9) + get_sampler_uniform(custom_velocity_image, 1, false), + get_sampler_uniform(neighbor_max_image, 2, false), + get_sampler_uniform(tile_variance_image, 3, true), + get_image_uniform(output_color_image, 4), ], blur_push_constants_byte_array, Vector3i(x_groups, y_groups, 1), diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_x.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_x.glsl index 84b1645..fc6c26c 100644 --- a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_x.glsl +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_x.glsl @@ -5,8 +5,7 @@ #define FLT_MIN 1.175494351e-38 layout(set = 0, binding = 0) uniform sampler2D velocity_sampler; -layout(set = 0, binding = 1) uniform sampler2D depth_sampler; -layout(rgba16f, set = 0, binding = 2) uniform writeonly image2D tile_max_x; +layout(rgba16f, set = 0, binding = 1) uniform writeonly image2D tile_max_x; layout(push_constant, std430) uniform Params { @@ -40,16 +39,22 @@ void main() vec4 max_velocity = vec4(0); float max_velocity_length = -1; + + //bool foreground = false; for(int i = 0; i < tile_size; i++) { vec2 current_uv = uvn + vec2(float(i) / render_size.x, 0); - vec3 velocity_sample = textureLod(velocity_sampler, current_uv, 0.0).xyz; + vec4 velocity_sample = textureLod(velocity_sampler, current_uv, 0.0); float current_velocity_length = dot(velocity_sample.xy, velocity_sample.xy); - if(current_velocity_length > max_velocity_length) + if(current_velocity_length > max_velocity_length)// || (velocity_sample.w > 0 && !foreground)) { max_velocity_length = current_velocity_length; - max_velocity = vec4(velocity_sample, textureLod(depth_sampler, current_uv, 0.0).x); + max_velocity = vec4(velocity_sample); +// if(velocity_sample.w > 0) +// { +// foreground = true; +// } } } imageStore(tile_max_x, uvi, max_velocity); diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_y.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_y.glsl index 2ea1f74..7ba3975 100644 --- a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_y.glsl +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_y.glsl @@ -40,15 +40,21 @@ void main() float max_velocity_length = -1; + //bool foreground = false; + for(int i = 0; i < tile_size; i++) { vec2 current_uv = uvn + vec2(0, float(i) / render_size.y); vec4 velocity_sample = textureLod(tile_max_x, current_uv, 0.0); float current_velocity_length = dot(velocity_sample.xy, velocity_sample.xy); - if(current_velocity_length > max_velocity_length) + if(current_velocity_length > max_velocity_length)// || (velocity_sample.w > 0 && !foreground)) { max_velocity_length = current_velocity_length; - max_velocity = velocity_sample; + max_velocity = vec4(velocity_sample); +// if(velocity_sample.w > 0) +// { +// foreground = true; +// } } } imageStore(tile_max, uvi, max_velocity); diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_neighbor_depth_max.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_neighbor_depth_max.glsl new file mode 100644 index 0000000..146851a --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_neighbor_depth_max.glsl @@ -0,0 +1,63 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 + +layout(set = 0, binding = 0) uniform sampler2D tile_max; +layout(set = 0, binding = 1) uniform sampler2D tile_max_map; +layout(rgba16f, set = 0, binding = 2) uniform writeonly image2D neighbor_max; + +layout(push_constant, std430) uniform Params +{ + float nan5; + float nan6; + float nan7; + float nan8; + int nan1; + int nan2; + int nan3; + int nan4; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + + +void main() +{ + ivec2 render_size = ivec2(textureSize(tile_max, 0)); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y)) + { + return; + } + + vec2 uvn = (vec2(uvi) + vec2(0.5)) / render_size; + + vec2 max_neighbor_velocity = vec2(0); + + float max_neighbor_depth = -1; + + for(int i = -1; i < 2; i++) + { + for(int j = -1; j < 2; j++) + { + vec2 current_offset = vec2(1) / vec2(render_size) * vec2(i, j); + vec2 current_uv = uvn + current_offset; + if(current_uv.x < 0 || current_uv.x > 1 || current_uv.y < 0 || current_uv.y > 1) + { + continue; + } + + vec3 current_neighbor_sample = textureLod(tile_max_map, current_uv, 0.0).xyz; + + if(current_neighbor_sample.z > max_neighbor_depth) + { + max_neighbor_depth = current_neighbor_sample.z; + max_neighbor_velocity = current_neighbor_sample.xy; + } + } + } + + imageStore(neighbor_max, uvi, vec4(max_neighbor_velocity, 0, 1)); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_neighbor_depth_max.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_neighbor_depth_max.glsl.import new file mode 100644 index 0000000..b679130 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_neighbor_depth_max.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://bcivntgn7ipwo" +path="res://.godot/imported/jf_neighbor_depth_max.glsl-412337591574185d763ac95625cd98ac.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_neighbor_depth_max.glsl" +dest_files=["res://.godot/imported/jf_neighbor_depth_max.glsl-412337591574185d763ac95625cd98ac.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_neighbor_max.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_neighbor_max.glsl index 5f20780..17376b5 100644 --- a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_neighbor_max.glsl +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_neighbor_max.glsl @@ -34,7 +34,7 @@ void main() vec2 uvn = (vec2(uvi) + vec2(0.5)) / render_size; - vec2 max_neighbor_velocity = vec2(0); + vec2 best_sample_uv = vec2(uvn); float max_neighbor_velocity_length = -1; @@ -49,20 +49,19 @@ void main() continue; } - bool is_diagonal = (abs(i) + abs(j) == 2); + vec2 velocity_map_sample = textureLod(tile_max_map, current_uv, 0.0).xy; - vec2 current_neighbor_sample = textureLod(tile_max_map, current_uv, 0.0).xy; + vec4 velocity_sample = textureLod(tile_max, velocity_map_sample, 0.0); - vec2 current_neighbor_velocity = textureLod(tile_max, current_neighbor_sample, 0.0).xy; - - float current_neighbor_velocity_length = dot(current_neighbor_velocity, current_neighbor_velocity); - if(current_neighbor_velocity_length > max_neighbor_velocity_length) + float current_velocity_length = dot(velocity_sample.xy, velocity_sample.xy); + + if(current_velocity_length > max_neighbor_velocity_length) { - max_neighbor_velocity_length = current_neighbor_velocity_length; - max_neighbor_velocity = current_neighbor_sample; + max_neighbor_velocity_length = current_velocity_length; + best_sample_uv = velocity_map_sample; } } } - imageStore(neighbor_max, uvi, vec4(max_neighbor_velocity, 0, 1)); + imageStore(neighbor_max, uvi, vec4(best_sample_uv, 0, 1)); } \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_simple.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_simple.glsl index 02338eb..3e97b62 100644 --- a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_simple.glsl +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_simple.glsl @@ -57,18 +57,6 @@ vec2 get_value(bool a, vec2 uv) } } -//vec4 get_value(bool a, ivec2 uvi) -//{ -// if(a) -// { -// return imageLoad(buffer_a, uvi); -// } -// else -// { -// return imageLoad(buffer_b, uvi); -// } -//} - void set_value(bool a, ivec2 uvi, vec4 value) { if(a) @@ -81,48 +69,52 @@ void set_value(bool a, ivec2 uvi, vec4 value) } } -// Motion similarity -// ---------------------------------------------------------- -float get_motion_difference(vec2 V, vec2 V2) -{ - return clamp(dot(V - V2, V) / dot(V, V), 0, 1); -// vec2 VO = V - V2; -// float parallel = dot(VO, V) / dot(V, V); -// return clamp(parallel, 0, 1); -} -// ---------------------------------------------------------- - void sample_fitness(vec2 uv_offset, vec4 uv_sample, vec2 render_size, inout vec4 current_sample_fitness) { vec2 sample_velocity = -uv_sample.xy; - // if velocity is 0, we never reach it (steps never smaller than 1) if (dot(sample_velocity, sample_velocity) <= FLT_MIN || uv_sample.w == 0) { - current_sample_fitness = vec4(FLT_MAX, FLT_MAX, FLT_MAX, -1); + current_sample_fitness = vec4(10, 10, 0, 0); return; } - // velocity space distance (projected pixel offset onto velocity vector) float velocity_space_distance = dot(sample_velocity, uv_offset) / dot(sample_velocity, sample_velocity); - // the velcity space distance to gravitate the JFA to (found more relieable than doing a 0 - 1 range) - float mid_point = params.motion_blur_intensity / 2; - // centralize the velocity space distance around that mid point + + float mid_point = params.motion_blur_intensity / 2 + 1e-5; + float absolute_velocity_space_distance = abs(velocity_space_distance - mid_point); - // if that distance is half the original, its within range (we centered around a mid point) + float within_velocity_range = step(absolute_velocity_space_distance, mid_point); - // perpendicular offset + float side_offset = abs(dot(vec2(uv_offset.y, -uv_offset.x), sample_velocity)) / dot(sample_velocity, sample_velocity); - // arbitrary perpendicular limit (lower means tighter dilation, but less reliable) + float within_perpen_error_range = step(side_offset, params.perpen_error_thresh * params.motion_blur_intensity); - // store relevant data for use in conditions - current_sample_fitness = vec4(absolute_velocity_space_distance, velocity_space_distance, uv_sample.w + uv_sample.z * velocity_space_distance, within_velocity_range * within_perpen_error_range); + + current_sample_fitness = vec4(/*max(absolute_velocity_space_distance, side_offset)*/absolute_velocity_space_distance, velocity_space_distance, uv_sample.w + uv_sample.z * velocity_space_distance, within_velocity_range * within_perpen_error_range); } float is_sample_better(vec4 a, vec4 b) { - // see explanation at end of code - return mix(1. - step(b.x * a.w, a.x * b.w), step(b.z, a.z), step(0.5, b.w) * step(0.5, a.w));//1. - step(a.x * a.w, b.x * b.w);//(a.x > b.x) ? 1 : 0;//1. - step(b.x * a.w, a.x * b.w);// + return 1. - step(b.x * a.w, a.x * b.w);//mix(1. - step(b.x * a.w, a.x * b.w), step(b.z, a.z), step(0.5, b.w) * step(0.5, a.w)); +} + +vec4 backtrack_sample(vec2 chosen_uv, vec4 best_sample_fitness) +{ + vec4 velocity = textureLod(tile_max_sampler, chosen_uv, 0.0); + + vec2 uv_candidate = chosen_uv + velocity.xy; + + vec4 velocity_candidate = textureLod(tile_max_sampler, uv_candidate, 0.0); + + if((dot(velocity, velocity_candidate) / dot(velocity, velocity)) > 0.5 && velocity_candidate.w > 0) + { + return vec4(uv_candidate, 0, 0); + } + else + { + return vec4(chosen_uv, 0, 0); + } } void main() @@ -134,12 +126,11 @@ void main() return; } - // must be on pixel center for whole values vec2 uvn = (vec2(uvi) + vec2(0.5)) / render_size; vec2 uv_step = vec2(round(params.step_size)) / render_size; - vec4 best_sample_fitness = vec4(FLT_MAX, FLT_MAX, FLT_MAX, 0); + vec4 best_sample_fitness = vec4(10, 10, 0, 0); vec2 chosen_uv = uvn; @@ -174,19 +165,29 @@ void main() sample_fitness(step_offset, uv_sample, render_size, current_sample_fitness); - if (is_sample_better(current_sample_fitness, best_sample_fitness) > 0.5) - { - best_sample_fitness = current_sample_fitness; - chosen_uv = check_uv; - } + float sample_better = 1. - step(best_sample_fitness.x * current_sample_fitness.w, current_sample_fitness.x * best_sample_fitness.w); + best_sample_fitness = mix(best_sample_fitness, current_sample_fitness, sample_better); + chosen_uv = mix(chosen_uv, check_uv, sample_better); + } - set_value(set_a, uvi, vec4(chosen_uv, 0, 0)); -} -// -// if((a.w == b.w) && (a.w == 1)) +// if(params.iteration_index < params.last_iteration_index) // { -// return a.z < b.z ? 0. : 1.; +// set_value(set_a, uvi, vec4(chosen_uv, 0, 0)); +// return; // } +// +// float depth = textureLod(tile_max_sampler, uvn, 0.0).w; // -// return a.x * b.w < b.x * a.w ? 1. : 0.; \ No newline at end of file +// if(params.iteration_index == params.last_iteration_index && (best_sample_fitness.w < 0.5 || depth > best_sample_fitness.z)) +// { +// set_value(set_a, uvi, vec4(uvn, 0, 0)); +// return; +// } + + set_value(set_a, uvi, vec4(chosen_uv, 0, 0)); + +// vec4 backtracked_sample = backtrack_sample(chosen_uv, best_sample_fitness); +// +// set_value(set_a, uvi, backtracked_sample); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_blur.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_blur.glsl index 469b14e..9b3c001 100644 --- a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_blur.glsl +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_blur.glsl @@ -11,14 +11,6 @@ layout(set = 0, binding = 1) uniform sampler2D depth_sampler; layout(set = 0, binding = 2) uniform sampler2D vector_sampler; layout(set = 0, binding = 3) uniform sampler2D velocity_map; layout(rgba16f, set = 0, binding = 4) uniform writeonly image2D output_image; -layout(rgba16f, set = 0, binding = 5) uniform writeonly image2D debug_1_image; -layout(rgba16f, set = 0, binding = 6) uniform writeonly image2D debug_2_image; -layout(rgba16f, set = 0, binding = 7) uniform writeonly image2D debug_3_image; -layout(rgba16f, set = 0, binding = 8) uniform writeonly image2D debug_4_image; -layout(rgba16f, set = 0, binding = 9) uniform writeonly image2D debug_5_image; -layout(rgba16f, set = 0, binding = 10) uniform writeonly image2D debug_6_image; -layout(rgba16f, set = 0, binding = 11) uniform writeonly image2D debug_7_image; -layout(rgba16f, set = 0, binding = 12) uniform writeonly image2D debug_8_image; layout(push_constant, std430) uniform Params { diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_cache.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_cache.glsl new file mode 100644 index 0000000..22283d4 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_cache.glsl @@ -0,0 +1,45 @@ +#[compute] +#version 450 + +layout(set = 0, binding = 0) uniform sampler2D velocity_sampler; +layout(set = 0, binding = 1) uniform sampler2D color_sampler; +layout(rgba16f, set = 0, binding = 2) uniform image2D past_velocity; +layout(rgba16f, set = 0, binding = 3) uniform image2D past_color; + +// Guertin's functions https://research.nvidia.com/sites/default/files/pubs/2013-11_A-Fast-and/Guertin2013MotionBlur-small.pdf +// ---------------------------------------------------------- +float z_compare(float a, float b, float sze) +{ + return clamp(1. - sze * (a - b) / min(a, b), 0, 1); +} +// ---------------------------------------------------------- + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; +void main() +{ + ivec2 render_size = ivec2(textureSize(velocity_sampler, 0)); + ivec2 uv = ivec2(gl_GlobalInvocationID.xy); + if ((uv.x >= render_size.x) || (uv.y >= render_size.y)) + { + return; + } + + vec2 x = (vec2(uv) + 0.5) / render_size; + + vec4 past_vx = textureLod(velocity_sampler, x, 0.0); + + vec4 past_vx_vx = textureLod(velocity_sampler, x + past_vx.xy, 0.0); + + vec4 past_col_vx = textureLod(color_sampler, x + past_vx.xy, 0.0); + + vec4 past_col_x = textureLod(color_sampler, x, 0.0); + + float alpha = 1 - z_compare(past_vx_vx.w, past_vx.w, 15); + + vec4 final_past_col = mix(past_col_vx, past_col_x, alpha); + + vec4 final_past_vx = mix(past_vx_vx, past_vx, alpha); + + imageStore(past_color, uv, final_past_col); + imageStore(past_velocity, uv, final_past_vx); +} diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_cache.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_cache.glsl.import new file mode 100644 index 0000000..d72bc96 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_cache.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://quuyr2q5w5kx" +path="res://.godot/imported/jump_flood_cache.glsl-f4eae7ab471d126e0587a3e727d847f6.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_cache.glsl" +dest_files=["res://.godot/imported/jump_flood_cache.glsl-f4eae7ab471d126e0587a3e727d847f6.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_new_blur.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_experimental_blur.glsl similarity index 80% rename from addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_new_blur.glsl rename to addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_experimental_blur.glsl index 81112f6..a76a39d 100644 --- a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_new_blur.glsl +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_experimental_blur.glsl @@ -10,15 +10,9 @@ layout(set = 0, binding = 1) uniform sampler2D depth_sampler; layout(set = 0, binding = 2) uniform sampler2D vector_sampler; layout(set = 0, binding = 3) uniform sampler2D velocity_map; layout(rgba16f, set = 0, binding = 4) uniform writeonly image2D output_image; -layout(rgba16f, set = 0, binding = 5) uniform writeonly image2D debug_1_image; -layout(rgba16f, set = 0, binding = 6) uniform writeonly image2D debug_2_image; -layout(rgba16f, set = 0, binding = 7) uniform writeonly image2D debug_3_image; -layout(rgba16f, set = 0, binding = 8) uniform writeonly image2D debug_4_image; -layout(rgba16f, set = 0, binding = 9) uniform writeonly image2D debug_5_image; -layout(rgba16f, set = 0, binding = 10) uniform writeonly image2D debug_6_image; -layout(rgba16f, set = 0, binding = 11) uniform writeonly image2D debug_7_image; -layout(rgba16f, set = 0, binding = 12) uniform writeonly image2D debug_8_image; -layout(set = 0, binding = 13) uniform sampler2D tile_max; +layout(set = 0, binding = 5) uniform sampler2D tile_max; +layout(set = 0, binding = 6) uniform sampler2D past_color_sampler; +layout(set = 0, binding = 7) uniform sampler2D past_velocity_sampler; layout(push_constant, std430) uniform Params { @@ -131,18 +125,33 @@ void main() vec3 vxz = textureLod(vector_sampler, x, 0.0).xyz * vec3(render_size, 1);// * 2; vec2 vx = vxz.xy; + + vec3 past_vxz = textureLod(past_velocity_sampler, x, 0.0).xyz * vec3(render_size, 1); + + vec2 past_vx = past_vxz.xy; + + float velocity_match = pow(clamp(dot(vx, vn) / dot(vn, vn), 0, 1), 0.5); + + vn = mix(vn, vx, velocity_match); + + vnz = mix(vnz, vxz, velocity_match); + + vec4 past_col_x = textureLod(past_color_sampler, x, 0.0); if(vn_length <= 0.5) { imageStore(output_image, uvi, col_x); + +#ifdef DEBUG imageStore(debug_1_image, uvi, col_x); imageStore(debug_2_image, uvi, abs(vec4(vn / render_size * 10, vnz.z * 100, 1))); imageStore(debug_3_image, uvi, abs(vec4(velocity_map_sample - x, 0, 1))); imageStore(debug_4_image, uvi, abs(vec4(vx / render_size * 10, vxz.z * 100, 1))); - imageStore(debug_5_image, uvi, 10 * abs(textureLod(tile_max, x, 0.0))); - imageStore(debug_6_image, uvi, 10 * abs(textureLod(tile_max, textureLod(velocity_map, x, 0.0).xy, 0.0))); - imageStore(debug_7_image, uvi, 10 * abs(textureLod(velocity_map, x, 0.0))); - imageStore(debug_8_image, uvi, abs(textureLod(velocity_map, x, 0.0) / 10)); + imageStore(debug_5_image, uvi, col_x); + imageStore(debug_6_image, uvi, past_col_x); + imageStore(debug_7_image, uvi, past_col_x); + imageStore(debug_8_image, uvi, abs(vec4(past_vx / render_size * 10, past_vxz.z * 100, 1))); +#endif return; } @@ -191,6 +200,8 @@ void main() float nai_dz = vxz.z; + vec2 past_nai_d = past_vx; + float dz = vnz.z;//sample_main_v ? vnz.z : vxz.z; vec2 wd = safenorm(d); @@ -199,6 +210,8 @@ void main() vec2 nai_y = x + (nai_d / render_size) * t; + vec2 past_nai_y = x + (past_nai_d / render_size) * t; + float nai_y_length = max(0.5, length(nai_y)); vec2 vy = textureLod(vector_sampler, y, 0.0).xy * render_size;// * 2; @@ -234,25 +247,27 @@ void main() float nai_cone_y = cone(T, nai_vy_length); - float ay = max(f * wa * step(FLT_MIN, cone_y), b * wb * cone_x); + float ay_trail = f * wa * step(FLT_MIN, cone_y); + + float ay_lead = (1 - f) * wb * step(FLT_MIN, cone_x); - float nai_ay = nai_b; + float nai_ay = nai_b;//max(nai_b, nai_f * nai_wa * step(FLT_MIN, nai_cone_y)); vec4 col_y = textureLod(color_sampler, y, 0.0); + vec4 past_col_y = textureLod(past_color_sampler, past_nai_y, 0.0); + vec4 nai_col_y = textureLod(color_sampler, nai_y, 0.0); vec4 col_back = nai_col_y; - float back_weight = mix(0, 1, nai_ay); + total_back_weight += nai_ay; - total_back_weight += back_weight; + back_sum += col_back * nai_ay; - back_sum += col_back * back_weight; + weight += ay_trail + ay_lead; - weight += ay; - - sum += col_y * ay; + sum += col_y * ay_trail + past_col_y * ay_lead; } back_sum *= (params.motion_blur_samples - weight) / total_back_weight; @@ -262,13 +277,15 @@ void main() back_sum /= params.motion_blur_samples; imageStore(output_image, uvi, sum + back_sum); - + +#ifdef DEBUG imageStore(debug_1_image, uvi, sum + back_sum); imageStore(debug_2_image, uvi, abs(vec4(vn / render_size * 10, vnz.z * 100, 1))); imageStore(debug_3_image, uvi, abs(vec4(velocity_map_sample - x, 0, 1))); imageStore(debug_4_image, uvi, abs(vec4(vx / render_size * 10, vxz.z * 100, 1))); - imageStore(debug_5_image, uvi, 10 * abs(textureLod(tile_max, x, 0.0))); - imageStore(debug_6_image, uvi, 10 * abs(textureLod(tile_max, textureLod(velocity_map, x, 0.0).xy, 0.0))); - imageStore(debug_7_image, uvi, 10 * abs(textureLod(velocity_map, x, 0.0))); - imageStore(debug_8_image, uvi, abs(textureLod(velocity_map, x, 0.0) / 10)); + imageStore(debug_5_image, uvi, col_x);//sum + back_sum); + imageStore(debug_6_image, uvi, past_col_x); + imageStore(debug_7_image, uvi, past_col_x); + imageStore(debug_8_image, uvi, abs(vec4(past_vx / render_size * 10, past_vxz.z * 100, 1))); +#endif } \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_experimental_blur.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_experimental_blur.glsl.import new file mode 100644 index 0000000..8f395d3 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_experimental_blur.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://bud4a7eh5sqr8" +path="res://.godot/imported/jump_flood_experimental_blur.glsl-27880bed814a937f2189c48828ca161e.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_experimental_blur.glsl" +dest_files=["res://.godot/imported/jump_flood_experimental_blur.glsl-27880bed814a937f2189c48828ca161e.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_new_blur.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_new_blur.glsl.import deleted file mode 100644 index effe9a4..0000000 --- a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_new_blur.glsl.import +++ /dev/null @@ -1,14 +0,0 @@ -[remap] - -importer="glsl" -type="RDShaderFile" -uid="uid://bdm5t4l1y3ts7" -path="res://.godot/imported/jump_flood_new_blur.glsl-ebfb8c41097767aad8ea133e2ff78878.res" - -[deps] - -source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_new_blur.glsl" -dest_files=["res://.godot/imported/jump_flood_new_blur.glsl-ebfb8c41097767aad8ea133e2ff78878.res"] - -[params] - diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_realistic_blur.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_realistic_blur.glsl new file mode 100644 index 0000000..476c256 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_realistic_blur.glsl @@ -0,0 +1,292 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 +#define M_PI 3.1415926535897932384626433832795 + +layout(set = 0, binding = 0) uniform sampler2D color_sampler; +layout(set = 0, binding = 1) uniform sampler2D depth_sampler; +layout(set = 0, binding = 2) uniform sampler2D velocity_sampler; +layout(set = 0, binding = 3) uniform sampler2D velocity_map; +layout(rgba16f, set = 0, binding = 4) uniform writeonly image2D output_image; +layout(set = 0, binding = 5) uniform sampler2D tile_max; + +layout(push_constant, std430) uniform Params +{ + float motion_blur_samples; + float motion_blur_intensity; + float motion_blur_center_fade; + float frame; + float last_iteration_index; + float sample_step_multiplier; + float step_exponent_modifier; + float max_dilation_radius; + int nan0; + int nan1; + int nan2; + int nan3; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + +// McGuire's functions https://docs.google.com/document/d/1IIlAKTj-O01hcXEdGxTErQbCHO9iBmRx6oFUy_Jm0fI/edit +// ---------------------------------------------------------- +float soft_depth_compare(float depth_X, float depth_Y, float sze) +{ + return clamp(1 - (depth_X - depth_Y) / sze, 0, 1); +} + +float cone(float T, float v) +{ + return clamp(1 - T / v, 0, 1); +} + +float cylinder(float T, float v) +{ + return 1.0 - smoothstep(0.95 * v, 1.05 * v, T); +} +// ---------------------------------------------------------- + +// Guertin's functions https://research.nvidia.com/sites/default/files/pubs/2013-11_A-Fast-and/Guertin2013MotionBlur-small.pdf +// ---------------------------------------------------------- +float z_compare(float a, float b, float sze) +{ + return clamp(1. - sze * (a - b), 0, 1); +} +// ---------------------------------------------------------- + +// from https://www.shadertoy.com/view/ftKfzc +// ---------------------------------------------------------- +float interleaved_gradient_noise(vec2 uv){ + uv += float(params.frame) * (vec2(47, 17) * 0.695); + + vec3 magic = vec3( 0.06711056, 0.00583715, 52.9829189 ); + + return fract(magic.z * fract(dot(uv, magic.xy))); +} +// ---------------------------------------------------------- + +// from https://github.com/bradparks/KinoMotion__unity_motion_blur/tree/master +// ---------------------------------------------------------- +vec2 safenorm(vec2 v) +{ + float l = max(length(v), 1e-6); + return v / l * int(l >= 0.5); +} + +vec2 jitter_tile(vec2 uvi) +{ + float rx, ry; + float angle = interleaved_gradient_noise(uvi + vec2(2, 0)) * M_PI * 2; + rx = cos(angle); + ry = sin(angle); + return vec2(rx, ry) / textureSize(tile_max, 0) / 4; +} +// ---------------------------------------------------------- + +void main() +{ + ivec2 render_size = ivec2(textureSize(color_sampler, 0)); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y)) + { + return; + } + + vec2 x = (vec2(uvi) + vec2(0.5)) / vec2(render_size); + + vec2 velocity_map_sample = textureLod(velocity_map, x + jitter_tile(uvi), 0.0).xy; + + vec3 vnz = textureLod(tile_max, velocity_map_sample, 0.0).xyz * vec3(render_size, 1); + + float vn_length = max(0.5, length(vnz.xy)); + + float multiplier = clamp(vn_length, 0, min(params.max_dilation_radius, vn_length * params.motion_blur_intensity)) / max(FLT_MIN, vn_length); + + vnz.xyz *= multiplier; + + vn_length *= multiplier; + + vec2 vn = vnz.xy; + + vec4 col_x = textureLod(color_sampler, x, 0.0); + + vec2 wn = safenorm(vn); + + vec4 vxz = textureLod(velocity_sampler, x, 0.0) * vec4(render_size, 1, 1); + + float vx_length = max(0.5, length(vxz.xy)); + + multiplier = clamp(vx_length, 0, min(params.max_dilation_radius, vn_length * params.motion_blur_intensity)) / max(FLT_MIN, vx_length); + + vxz.xyz *= multiplier; + + vx_length *= multiplier; + + vec2 vx = vxz.xy; + + if(vn_length <= 0.5) + { + imageStore(output_image, uvi, col_x); + +#ifdef DEBUG + imageStore(debug_1_image, uvi, col_x); + imageStore(debug_2_image, uvi, abs(vec4(vn / render_size * 10, vnz.z * 100, 1))); + imageStore(debug_3_image, uvi, abs(vec4(velocity_map_sample - x, 0, 1))); + imageStore(debug_4_image, uvi, abs(vec4(vx / render_size * 10, vxz.z * 100, 1))); + imageStore(debug_5_image, uvi, col_x); +#endif + + return; + } + + float velocity_match = pow(clamp(dot(vx, vn) / dot(vn, vn), 0, 1), 0.25); + + vn = mix(vn, vx, velocity_match); + + vnz = mix(vnz, vxz.xyz, velocity_match); + + float zx = vxz.w; + + vec2 wx = safenorm(vx); + + float weight = 0; + + vec4 sum = col_x * weight; + + float total_back_weight = 1e-10; + + vec4 back_sum = col_x * total_back_weight; + + float j = interleaved_gradient_noise(uvi) - 0.5; + + int back_amount = 0; + + int nai_back_i = 1; + + for(int i = 0; i < params.motion_blur_samples; i++) + { + float nai_t = mix(0., -1., (i + j + 1.0) / (params.motion_blur_samples + 1.0)); + + float nai_T = abs(nai_t * vx_length); + + vec2 nai_y = x + (vx / render_size) * nai_t; + + float nai_zy = textureLod(depth_sampler, nai_y, 0.0).x - vxz.z * nai_t; + + float nai_b = z_compare(-zx, -nai_zy, 20000); + + float nai_f = z_compare(-nai_zy, -zx, 20000); + + vec4 nai_vy = textureLod(velocity_sampler, nai_y, 0.0) * vec4(render_size, 1, 1); + + float nai_vy_length = max(0.5, length(nai_vy.xy)); + + float nai_ay = nai_b; + + float nai_wb = abs(max(0, dot(nai_vy.xy / nai_vy_length, wx))); + + float nai_ay_f = nai_f * step(nai_T, nai_vy_length * nai_wb); + + if(nai_y.x < 0 || nai_y.x > 1 || nai_y.y < 0 || nai_y.y > 1 || nai_ay + nai_ay_f <= 1e-5) + { + nai_t = mix(0., 1., (nai_back_i + j + 1.0) / (params.motion_blur_samples + 1.0)); + + nai_T = abs(nai_t * vx_length); + + nai_y = x + (vx / render_size) * nai_t; + + nai_zy = textureLod(depth_sampler, nai_y, 0.0).x - vxz.z * nai_t; + + nai_b = z_compare(-zx, -nai_zy, 20000); + + nai_f = z_compare(-nai_zy, -zx, 20000); + + nai_vy = textureLod(velocity_sampler, nai_y, 0.0) * vec4(render_size, 1, 1); + + nai_vy_length = max(0.5, length(nai_vy.xy)); + + nai_ay = nai_b; + + nai_wb = abs(max(0, dot(nai_vy.xy / nai_vy_length, wx))); + + nai_ay_f = nai_f * step(nai_T, nai_vy_length * nai_wb); + + nai_back_i++; + } + + vec4 nai_col_y = textureLod(color_sampler, nai_y, 0.0); + + total_back_weight += nai_ay; + + back_sum += nai_col_y * nai_ay; + + float t = mix(0., -1., (i - back_amount + j + 1.0) / (params.motion_blur_samples + 1.0)); + + float T = abs(t * vn_length); + + vec2 y = x + (vn / render_size) * t; + + if(y.x < 0 || y.x > 1 || y.y < 0 || y.y > 1) + { + continue; +// vn = -vn; +// vnz = -vnz; +// wn = -wn; +// back_amount = i; + } + + vec4 vy = textureLod(velocity_sampler, y, 0.0) * vec4(render_size, 1, 1); + + float vy_length = max(0.5, length(vy.xy)); + + float zy = vy.w - vnz.z * t; + + float f = z_compare(-zy, -zx, 20000); + + float wa = abs(max(0, dot(vy.xy / vy_length, wn))); + + float ay_trail = f * step(T, vy_length * wa); + + vec4 col_y = textureLod(color_sampler, y, 0.0); + + vec2 back_y = x + (vn / render_size) * -t; + + vec4 back_vy = textureLod(velocity_sampler, back_y, 0.0) * vec4(render_size, 1, 1); + + float back_vy_length = max(0.5, length(back_vy.xy)); + + float back_zy = back_vy.w - vnz.z * -t; + + float back_wa = abs(max(0, dot(back_vy.xy / back_vy_length, -wn))); + + float back_f = z_compare(-back_zy, -zx, 20000); + + float back_ay_trail = back_f * step(T, back_vy_length * back_wa); + + vec4 back_col_y = textureLod(color_sampler, back_y, 0.0); + + weight += back_ay_trail + (back_ay_trail > 0 ? 0 : ay_trail); + + sum += back_col_y * back_ay_trail + (back_ay_trail > 0 ? vec4(0) : col_y * ay_trail); + + + } + + back_sum *= (params.motion_blur_samples - weight) / total_back_weight; + + sum /= params.motion_blur_samples; + + back_sum /= params.motion_blur_samples; + + imageStore(output_image, uvi, sum + back_sum); + +#ifdef DEBUG + imageStore(debug_1_image, uvi, sum + back_sum); + imageStore(debug_2_image, uvi, abs(vec4(vn / render_size * 10, vnz.z * 100, 1))); + imageStore(debug_3_image, uvi, abs(vec4(velocity_map_sample - x, 0, 1))); + imageStore(debug_4_image, uvi, abs(vec4(vx / render_size * 10, vxz.z * 100, 1))); + imageStore(debug_5_image, uvi, col_x); +#endif +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_realistic_blur.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_realistic_blur.glsl.import new file mode 100644 index 0000000..4859444 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_realistic_blur.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://b1fr5qhhrbpst" +path="res://.godot/imported/jump_flood_realistic_blur.glsl-c7d6d91d942d788c7b2fc3bc2c1c8e38.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_realistic_blur.glsl" +dest_files=["res://.godot/imported/jump_flood_realistic_blur.glsl-c7d6d91d942d788c7b2fc3bc2c1c8e38.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_simple_blur.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_simple_blur.glsl new file mode 100644 index 0000000..db880f7 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_simple_blur.glsl @@ -0,0 +1,240 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 +#define M_PI 3.1415926535897932384626433832795 + +layout(set = 0, binding = 0) uniform sampler2D color_sampler; +layout(set = 0, binding = 1) uniform sampler2D depth_sampler; +layout(set = 0, binding = 2) uniform sampler2D velocity_sampler; +layout(set = 0, binding = 3) uniform sampler2D velocity_map; +layout(rgba16f, set = 0, binding = 4) uniform writeonly image2D output_image; +layout(set = 0, binding = 5) uniform sampler2D tile_max; + +layout(push_constant, std430) uniform Params +{ + float motion_blur_samples; + float motion_blur_intensity; + float motion_blur_center_fade; + float frame; + float last_iteration_index; + float sample_step_multiplier; + float step_exponent_modifier; + float max_dilation_radius; + int nan0; + int nan1; + int nan2; + int nan3; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + +// McGuire's functions https://docs.google.com/document/d/1IIlAKTj-O01hcXEdGxTErQbCHO9iBmRx6oFUy_Jm0fI/edit +// ---------------------------------------------------------- +float soft_depth_compare(float depth_X, float depth_Y, float sze) +{ + return clamp(1 - (depth_X - depth_Y) / sze, 0, 1); +} + +float cone(float T, float v) +{ + return clamp(1 - T / v, 0, 1); +} + +float cylinder(float T, float v) +{ + return 1.0 - smoothstep(0.95 * v, 1.05 * v, T); +} +// ---------------------------------------------------------- + +// Guertin's functions https://research.nvidia.com/sites/default/files/pubs/2013-11_A-Fast-and/Guertin2013MotionBlur-small.pdf +// ---------------------------------------------------------- +float z_compare(float a, float b, float sze) +{ + return clamp(1. - sze * (a - b), 0, 1); +} +// ---------------------------------------------------------- + +// from https://www.shadertoy.com/view/ftKfzc +// ---------------------------------------------------------- +float interleaved_gradient_noise(vec2 uv){ + uv += float(params.frame) * (vec2(47, 17) * 0.695); + + vec3 magic = vec3( 0.06711056, 0.00583715, 52.9829189 ); + + return fract(magic.z * fract(dot(uv, magic.xy))); +} +// ---------------------------------------------------------- + +// from https://github.com/bradparks/KinoMotion__unity_motion_blur/tree/master +// ---------------------------------------------------------- +vec2 safenorm(vec2 v) +{ + float l = max(length(v), 1e-6); + return v / l * int(l >= 0.5); +} + +vec2 jitter_tile(vec2 uvi) +{ + float rx, ry; + float angle = interleaved_gradient_noise(uvi + vec2(2, 0)) * M_PI * 2; + rx = cos(angle); + ry = sin(angle); + return vec2(rx, ry) / textureSize(tile_max, 0) / 4; +} +// ---------------------------------------------------------- + +void main() +{ + ivec2 render_size = ivec2(textureSize(color_sampler, 0)); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y)) + { + return; + } + + vec2 x = (vec2(uvi) + vec2(0.5)) / vec2(render_size); + + vec2 velocity_map_sample = textureLod(velocity_map, x + jitter_tile(uvi), 0.0).xy; + + vec3 vnz = textureLod(tile_max, velocity_map_sample, 0.0).xyz * vec3(render_size, 1); + + float vn_length = max(0.5, length(vnz.xy)); + + float multiplier = clamp(vn_length, 0, min(params.max_dilation_radius, vn_length * params.motion_blur_intensity)) / max(FLT_MIN, vn_length); + + vnz.xyz *= multiplier; + + vn_length *= multiplier; + + vec2 vn = vnz.xy; + + vec4 col_x = textureLod(color_sampler, x, 0.0); + + vec2 wn = safenorm(vn); + + vec4 vxz = textureLod(velocity_sampler, x, 0.0) * vec4(render_size, 1, 1); + + float vx_length = max(0.5, length(vxz.xy)); + + multiplier = clamp(vx_length, 0, min(params.max_dilation_radius, vn_length * params.motion_blur_intensity)) / max(FLT_MIN, vx_length); + + vxz.xyz *= multiplier; + + vx_length *= multiplier; + + vec2 vx = vxz.xy; + + if(vn_length <= 0.5) + { + imageStore(output_image, uvi, col_x); + +#ifdef DEBUG + imageStore(debug_1_image, uvi, col_x); + imageStore(debug_2_image, uvi, abs(vec4(vn / render_size * 10, vnz.z * 100, 1))); + imageStore(debug_3_image, uvi, abs(vec4(velocity_map_sample - x, 0, 1))); + imageStore(debug_4_image, uvi, abs(vec4(vx / render_size * 10, vxz.z * 100, 1))); + imageStore(debug_5_image, uvi, col_x); +#endif + + return; + } + + float velocity_match = pow(clamp(dot(vx, vn) / dot(vn, vn), 0, 1), 0.25); + + vn = mix(vn, vx, velocity_match); + + vnz = mix(vnz, vxz.xyz, velocity_match); + + float zx = vxz.w; + + vec2 wx = safenorm(vx); + + float weight = 0; + + vec4 sum = col_x * weight; + + float total_back_weight = 1e-10; + + vec4 back_sum = col_x * total_back_weight; + + float j = interleaved_gradient_noise(uvi) - 0.5; + + int back_amount = 0; + + int nai_back_i = 1; + + for(int i = 0; i < params.motion_blur_samples; i++) + { + float nai_t = mix(0., -1., (i + j + 1.0) / (params.motion_blur_samples + 1.0)); + + float nai_T = abs(nai_t * vx_length); + + vec2 nai_y = x + (vx / render_size) * nai_t; + + if(nai_y.x < 0 || nai_y.x > 1 || nai_y.y < 0 || nai_y.y > 1) + { + continue; + } + + float nai_zy = textureLod(depth_sampler, nai_y, 0.0).x - vxz.z * nai_t; + + float nai_b = z_compare(-zx, -nai_zy, 20000); + + vec4 nai_vy = textureLod(velocity_sampler, nai_y, 0.0) * vec4(render_size, 1, 1); + + float nai_ay = nai_b; + + vec4 nai_col_y = textureLod(color_sampler, nai_y, 0.0); + + total_back_weight += nai_ay; + + back_sum += nai_col_y * nai_ay; + + float t = mix(0., -1., (i - back_amount + j + 1.0) / (params.motion_blur_samples + 1.0)); + + float T = abs(t * vn_length); + + vec2 y = x + (vn / render_size) * t; + + if(y.x < 0 || y.x > 1 || y.y < 0 || y.y > 1) + { + continue; + } + + vec4 vy = textureLod(velocity_sampler, y, 0.0) * vec4(render_size, 1, 1); + + float vy_length = max(0.5, length(vy.xy)); + + float zy = vy.w - vnz.z * t; + + float f = z_compare(-zy, -zx, 20000); + + float wa = abs(max(0, dot(vy.xy / vy_length, wn))); + + float ay_trail = f * step(T, vy_length * wa); + + vec4 col_y = textureLod(color_sampler, y, 0.0); + + weight += ay_trail; + + sum += col_y * ay_trail; + } + + back_sum *= (params.motion_blur_samples - weight) / total_back_weight; + + sum /= params.motion_blur_samples; + + back_sum /= params.motion_blur_samples; + + imageStore(output_image, uvi, sum + back_sum); + +#ifdef DEBUG + imageStore(debug_1_image, uvi, sum + back_sum); + imageStore(debug_2_image, uvi, abs(vec4(vn / render_size * 10, vnz.z * 100, 1))); + imageStore(debug_3_image, uvi, abs(vec4(velocity_map_sample - x, 0, 1))); + imageStore(debug_4_image, uvi, abs(vec4(vx / render_size * 10, vxz.z * 100, 1))); + imageStore(debug_5_image, uvi, col_x); +#endif +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_simple_blur.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_simple_blur.glsl.import new file mode 100644 index 0000000..6ef1a5c --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_simple_blur.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://bdm5t4l1y3ts7" +path="res://.godot/imported/jump_flood_simple_blur.glsl-cf442320d0e724df4bd151fec5d94fae.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_simple_blur.glsl" +dest_files=["res://.godot/imported/jump_flood_simple_blur.glsl-cf442320d0e724df4bd151fec5d94fae.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/base_jump_flood_motion_blur.gd b/addons/SphynxMotionBlurToolkit/JumpFlood/base_jump_flood_motion_blur.gd new file mode 100644 index 0000000..a3af9d6 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/base_jump_flood_motion_blur.gd @@ -0,0 +1,26 @@ +extends "res://addons/SphynxMotionBlurToolkit/BaseClasses/mb_compositor_effect.gd" + +@export_group("Shader Parameters") +## the portion of speed that is allowed for side bleed of velocities +## during the jfa dilation passes and before backtracking. Getting this a higher value +## would make it so that meshes at movement blur more reliably, but also bleed +## further perpendicularly to their velocity, thus wash elemets behind them out. +@export var perpen_error_threshold : float = 0.5 + +## an initial step size that can increase the dilation radius proportionally, at the +## sacrifice of some quality in the final resolution of the dilation.[br][br] +## the formula for the maximum radius of the dilation (in pixels) is: pow(2 + step_exponent_modifier, JFA_pass_count) * sample_step_multiplier +@export var sample_step_multiplier : int = 16 + +## by default, the jump flood makes samples along distances that start +## at 2 to the power of the pass count you want to perform, which is also +## the dilation radius you desire. You can change it to values higher than +## 2 with this variable, and reach higher dilation radius at the sacrifice of +## some accuracy in the dilation. +## the formula for the maximum radius of the dilation (in pixels) is: pow(2 + step_exponent_modifier, JFA_pass_count) * sample_step_multiplier +@export var step_exponent_modifier : float = 1 + +## the number of passes performed by the jump flood algorithm based dilation, +## each pass added doubles the maximum radius of dilation available.[br][br] +## the formula for the maximum radius of the dilation (in pixels) is: pow(2 + step_exponent_modifier, JFA_pass_count) * sample_step_multiplier +@export var JFA_pass_count : int = 3 diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/experimental_jf_motion_blur.gd b/addons/SphynxMotionBlurToolkit/JumpFlood/experimental_jf_motion_blur.gd new file mode 100644 index 0000000..4233be8 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/experimental_jf_motion_blur.gd @@ -0,0 +1,298 @@ +extends "res://addons/SphynxMotionBlurToolkit/JumpFlood/base_jump_flood_motion_blur.gd" +class_name ExperimentalJumpFloodMotionBlur + +@export_group("Shader Stages") +@export var tile_max_x_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_tile_max_x_stage.tres"): + set(value): + unsubscribe_shader_stage(tile_max_x_stage) + tile_max_x_stage = value + subscirbe_shader_stage(value) + +@export var tile_max_y_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_tile_max_y_stage.tres"): + set(value): + unsubscribe_shader_stage(tile_max_y_stage) + tile_max_y_stage = value + subscirbe_shader_stage(value) + +@export var construct_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jf_simple_stage.tres"): + set(value): + unsubscribe_shader_stage(construct_stage) + construct_stage = value + subscirbe_shader_stage(value) + +@export var neighbor_max_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_neighbor_max_stage.tres"): + set(value): + unsubscribe_shader_stage(neighbor_max_stage) + neighbor_max_stage = value + subscirbe_shader_stage(value) + +@export var blur_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/experimental_jump_flood_blur_stage.tres"): + set(value): + unsubscribe_shader_stage(blur_stage) + blur_stage = value + subscirbe_shader_stage(value) + +@export var cache_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_cache_stage.tres"): + set(value): + unsubscribe_shader_stage(cache_stage) + cache_stage = value + subscirbe_shader_stage(value) + +@export var overlay_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_overlay_stage.tres"): + set(value): + unsubscribe_shader_stage(overlay_stage) + overlay_stage = value + subscirbe_shader_stage(value) + +var tile_max_x : StringName = "tile_max_x" + +var tile_max : StringName = "tile_max" + +var neighbor_max : StringName = "neighbor_max" + +var output_color : StringName = "output_color" + +var past_color : StringName = "past_color_cache" + +var past_velocity : StringName = "past_velocity_cache" + +var buffer_a : StringName = "buffer_a" +var buffer_b : StringName = "buffer_b" + +var custom_velocity : StringName = "custom_velocity" + +var temp_intensity : float + +var previous_time : float = 0 + +func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSceneBuffersRD, render_scene_data : RenderSceneDataRD): + var time : float = float(Time.get_ticks_msec()) / 1000 + + var delta_time : float = time - previous_time + + previous_time = time + + temp_intensity = intensity + + if framerate_independent: + var capped_frame_time : float = 1 / target_constant_framerate + + if !uncapped_independence: + capped_frame_time = min(capped_frame_time, delta_time) + + temp_intensity = intensity * capped_frame_time / delta_time + + ensure_texture(custom_velocity, render_scene_buffers) + ensure_texture(tile_max_x, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1.)) + ensure_texture(tile_max, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier)) + ensure_texture(buffer_a, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier)) + ensure_texture(buffer_b, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier)) + ensure_texture(neighbor_max, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier)) + ensure_texture(output_color, render_scene_buffers) + ensure_texture(past_color, render_scene_buffers) + ensure_texture(past_velocity, render_scene_buffers) + + rd.draw_command_begin_label("Motion Blur", Color(1.0, 1.0, 1.0, 1.0)) + + var last_iteration_index : int = JFA_pass_count - 1; + + var max_dilation_radius : float = pow(2 + step_exponent_modifier, last_iteration_index) * sample_step_multiplier / intensity; + + var tile_max_x_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_tile_max_x_push_constants : PackedInt32Array = [ + sample_step_multiplier, + 0, + 0, + 0 + ] + var tile_max_x_push_constants_byte_array = tile_max_x_push_constants.to_byte_array() + tile_max_x_push_constants_byte_array.append_array(int_tile_max_x_push_constants.to_byte_array()) + + var tile_max_y_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_tile_max_y_push_constants : PackedInt32Array = [ + sample_step_multiplier, + 0, + 0, + 0 + ] + var tile_max_y_push_constants_byte_array = tile_max_y_push_constants.to_byte_array() + tile_max_y_push_constants_byte_array.append_array(int_tile_max_y_push_constants.to_byte_array()) + var neighbor_max_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_neighbor_max_push_constants : PackedInt32Array = [ + 0, + 0, + 0, + 0 + ] + var neighbor_max_push_constants_byte_array = neighbor_max_push_constants.to_byte_array() + neighbor_max_push_constants_byte_array.append_array(int_neighbor_max_push_constants.to_byte_array()) + + var push_constant: PackedFloat32Array = [ + samples, + temp_intensity, + center_fade, + Engine.get_frames_drawn() % 8, + last_iteration_index, + sample_step_multiplier, + step_exponent_modifier, + max_dilation_radius, + ] + var int_push_constant : PackedInt32Array = [ + 0, + 0, + 0, + 0 + ] + var byte_array = push_constant.to_byte_array() + byte_array.append_array(int_push_constant.to_byte_array()) + + var view_count = render_scene_buffers.get_view_count() + for view in range(view_count): + var color_image := render_scene_buffers.get_color_layer(view) + var depth_image := render_scene_buffers.get_depth_layer(view) + var output_color_image := render_scene_buffers.get_texture_slice(context, output_color, view, 0, 1, 1) + var past_color_image := render_scene_buffers.get_texture_slice(context, past_color, view, 0, 1, 1) + var past_velocity_image := render_scene_buffers.get_texture_slice(context, past_velocity, view, 0, 1, 1) + var buffer_a_image := render_scene_buffers.get_texture_slice(context, buffer_a, view, 0, 1, 1) + var buffer_b_image := render_scene_buffers.get_texture_slice(context, buffer_b, view, 0, 1, 1) + var custom_velocity_image := render_scene_buffers.get_texture_slice(context, custom_velocity, view, 0, 1, 1) + var tile_max_x_image := render_scene_buffers.get_texture_slice(context, tile_max_x, view, 0, 1, 1) + var tile_max_image := render_scene_buffers.get_texture_slice(context, tile_max, view, 0, 1, 1) + var neighbor_max_image := render_scene_buffers.get_texture_slice(context, neighbor_max, view, 0, 1, 1) + + var x_groups := floori((render_size.x / sample_step_multiplier - 1) / 16 + 1) + var y_groups := floori((render_size.y - 1) / 16 + 1) + + dispatch_stage(tile_max_x_stage, + [ + get_sampler_uniform(custom_velocity_image, 0, false), + get_sampler_uniform(depth_image, 1, false), + get_image_uniform(tile_max_x_image, 2) + ], + tile_max_x_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "TileMaxX", + view) + + x_groups = floori((render_size.x / sample_step_multiplier - 1) / 16 + 1) + y_groups = floori((render_size.y / sample_step_multiplier - 1) / 16 + 1) + + dispatch_stage(tile_max_y_stage, + [ + get_sampler_uniform(tile_max_x_image, 0, false), + get_image_uniform(tile_max_image, 1) + ], + tile_max_y_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "TileMaxY", + view) + + for i in JFA_pass_count: + var jf_push_constants : PackedInt32Array = [ + i, + last_iteration_index, + 0, + 16 + ] + + var step_size : float = round(pow(2 + step_exponent_modifier, last_iteration_index - i)); + + var jf_float_push_constants_test : PackedFloat32Array = [ + perpen_error_threshold, + sample_step_multiplier, + temp_intensity, + 0, + 0, + 0, + 0, + step_exponent_modifier, + step_size, + max_dilation_radius, + 0, + 0 + ] + + var jf_byte_array = jf_push_constants.to_byte_array() + jf_byte_array.append_array(jf_float_push_constants_test.to_byte_array()) + + dispatch_stage(construct_stage, + [ + get_sampler_uniform(tile_max_image, 0, false), + get_image_uniform(buffer_a_image, 1), + get_image_uniform(buffer_b_image, 2), + get_sampler_uniform(buffer_a_image, 3, false), + get_sampler_uniform(buffer_b_image, 4, false) + ], + jf_byte_array, + Vector3i(x_groups, y_groups, 1), + "Construct Blur", + view) + + dispatch_stage(neighbor_max_stage, + [ + get_sampler_uniform(tile_max_image, 0, false), + get_sampler_uniform(buffer_b_image if last_iteration_index % 2 else buffer_a_image, 1, false), + get_image_uniform(neighbor_max_image, 2) + ], + neighbor_max_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "NeighborMax", + view) + + x_groups = floori((render_size.x - 1) / 16 + 1) + y_groups = floori((render_size.y - 1) / 16 + 1) + + dispatch_stage(blur_stage, + [ + get_sampler_uniform(color_image, 0, false), + get_sampler_uniform(depth_image, 1, false), + get_sampler_uniform(custom_velocity_image, 2, false), + get_sampler_uniform(neighbor_max_image, 3, false), + get_image_uniform(output_color_image, 4), + get_sampler_uniform(tile_max_image, 5, false), + get_sampler_uniform(past_color_image, 6, false), + get_sampler_uniform(past_velocity_image, 7, false) + ], + byte_array, + Vector3i(x_groups, y_groups, 1), + "Compute Blur", + view) + + dispatch_stage(cache_stage, + [ + get_sampler_uniform(custom_velocity_image, 0), + get_sampler_uniform(color_image, 1), + get_image_uniform(past_velocity_image, 2), + get_image_uniform(past_color_image, 3), + ], + [], + Vector3i(x_groups, y_groups, 1), + "Past Color Copy", + view) + + dispatch_stage(overlay_stage, + [ + get_sampler_uniform(output_color_image, 0), + get_image_uniform(color_image, 1), + ], + [], + Vector3i(x_groups, y_groups, 1), + "Overlay Result", + view) + + rd.draw_command_end_label() diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/experimental_jump_flood_blur_stage.tres b/addons/SphynxMotionBlurToolkit/JumpFlood/experimental_jump_flood_blur_stage.tres new file mode 100644 index 0000000..54650bc --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/experimental_jump_flood_blur_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://cvavvqqstnm1j"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_3q423"] +[ext_resource type="RDShaderFile" uid="uid://bud4a7eh5sqr8" path="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_experimental_blur.glsl" id="2_8flx6"] + +[resource] +script = ExtResource("1_3q423") +shader_file = ExtResource("2_8flx6") diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_cache_stage.tres b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_cache_stage.tres new file mode 100644 index 0000000..c5b760d --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_cache_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://bq18dhoelcexm"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_3clo0"] +[ext_resource type="RDShaderFile" uid="uid://quuyr2q5w5kx" path="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_cache.glsl" id="2_val47"] + +[resource] +script = ExtResource("1_3clo0") +shader_file = ExtResource("2_val47") diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_motion_blur.gd b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_motion_blur.gd index f5a1f2b..db046ce 100644 --- a/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_motion_blur.gd +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_motion_blur.gd @@ -1,13 +1,7 @@ -extends MotionBlurCompositorEffect +extends "res://addons/SphynxMotionBlurToolkit/JumpFlood/base_jump_flood_motion_blur.gd" class_name SphynxOldJumpFloodMotionBlur -@export_group("Motion Blur", "motion_blur_") -# diminishing returns over 16 -@export_range(4, 64) var motion_blur_samples: int = 8 -# you really don't want this over 0.5, but you can if you want to try -@export_range(0, 0.5, 0.001, "or_greater") var motion_blur_intensity: float = 1 -@export_range(0, 1) var motion_blur_center_fade: float = 0.0 - +@export_group("Shader Stages") @export var blur_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_blur_stage.tres"): set(value): unsubscribe_shader_stage(blur_stage) @@ -26,25 +20,6 @@ class_name SphynxOldJumpFloodMotionBlur construct_stage = value subscirbe_shader_stage(value) -## the portion of speed that is allowed for side bleed of velocities -## during the jfa dilation passes and before backtracking. Getting this a higher value -## would make it so that meshes at movement blur more reliably, but also bleed -## further perpendicularly to their velocity, thus wash elemets behind them out. -@export var perpen_error_threshold : float = 0.5 - -## an initial step size that can increase the dilation radius proportionally, at the -## sacrifice of some quality in the final resolution of the dilation.[br][br] -## the formula for the maximum radius of the dilation (in pixels) is: pow(2 + step_exponent_modifier, JFA_pass_count) * sample_step_multiplier -@export var sample_step_multiplier : float = 16 - -## by default, the jump flood makes samples along distances that start -## at 2 to the power of the pass count you want to perform, which is also -## the dilation radius you desire. You can change it to values higher than -## 2 with this variable, and reach higher dilation radius at the sacrifice of -## some accuracy in the dilation. -## the formula for the maximum radius of the dilation (in pixels) is: pow(2 + step_exponent_modifier, JFA_pass_count) * sample_step_multiplier -@export var step_exponent_modifier : float = 1 - ## how many steps along a range of 2 velocities from the ## dilation target velocity space do we go along to find a better fitting velocity sample ## higher samples meaning higher detail getting captured and blurred @@ -65,27 +40,6 @@ class_name SphynxOldJumpFloodMotionBlur ## considered (in NDC space) @export var backtracbing_depth_match_threshold : float = 0.001 -## the number of passes performed by the jump flood algorithm based dilation, -## each pass added doubles the maximum radius of dilation available.[br][br] -## the formula for the maximum radius of the dilation (in pixels) is: pow(2 + step_exponent_modifier, JFA_pass_count) * sample_step_multiplier -@export var JFA_pass_count : int = 3 - -## wether this motion blur stays the same intensity below -## target_constant_framerate -@export var framerate_independent : bool = true - -## Description: Removes clamping on motion blur scale to allow framerate independent motion -## blur to scale longer than realistically possible when render framerate is higher -## than target framerate.[br][br] -## [color=yellow]Warning:[/color] Turning this on would allow over-blurring of pixels, which -## produces inaccurate results, and would likely cause nausea in players over -## long exposure durations, use with caution and out of artistic intent -@export var uncapped_independence : bool = false - -## if framerate_independent is enabled, the blur would simulate -## sutter speeds at that framerate, and up. -@export var target_constant_framerate : float = 30 - var texture: StringName = "texture" var buffer_a : StringName = "buffer_a" @@ -93,16 +47,7 @@ var buffer_b : StringName = "buffer_b" var custom_velocity : StringName = "custom_velocity" -@export var debug_1 : String = "debug_1" -@export var debug_2 : String = "debug_2" -@export var debug_3 : String = "debug_3" -@export var debug_4 : String = "debug_4" -@export var debug_5 : String = "debug_5" -@export var debug_6 : String = "debug_6" -@export var debug_7 : String = "debug_7" -@export var debug_8 : String = "debug_8" - -var temp_motion_blur_intensity : float +var temp_intensity : float var previous_time : float = 0 @@ -113,7 +58,7 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce previous_time = time - temp_motion_blur_intensity = motion_blur_intensity + temp_intensity = intensity if framerate_independent: var capped_frame_time : float = 1 / target_constant_framerate @@ -121,7 +66,7 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce if !uncapped_independence: capped_frame_time = min(capped_frame_time, delta_time) - temp_motion_blur_intensity = motion_blur_intensity * capped_frame_time / delta_time + temp_intensity = intensity * capped_frame_time / delta_time ensure_texture(texture, render_scene_buffers) @@ -129,25 +74,16 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce ensure_texture(buffer_b, render_scene_buffers)#, RenderingDevice.DATA_FORMAT_R16G16_SFLOAT) ensure_texture(custom_velocity, render_scene_buffers) - ensure_texture(debug_1, render_scene_buffers) - ensure_texture(debug_2, render_scene_buffers) - ensure_texture(debug_3, render_scene_buffers) - ensure_texture(debug_4, render_scene_buffers) - ensure_texture(debug_5, render_scene_buffers) - ensure_texture(debug_6, render_scene_buffers) - ensure_texture(debug_7, render_scene_buffers) - ensure_texture(debug_8, render_scene_buffers) - rd.draw_command_begin_label("Motion Blur", Color(1.0, 1.0, 1.0, 1.0)) var last_iteration_index : int = JFA_pass_count - 1; - var max_dilation_radius : float = pow(2 + step_exponent_modifier, last_iteration_index) * sample_step_multiplier / motion_blur_intensity; + var max_dilation_radius : float = pow(2 + step_exponent_modifier, last_iteration_index) * sample_step_multiplier / intensity; var push_constant: PackedFloat32Array = [ - motion_blur_samples, - temp_motion_blur_intensity, - motion_blur_center_fade, + samples, + temp_intensity, + center_fade, Engine.get_frames_drawn() % 8, last_iteration_index, sample_step_multiplier, @@ -171,14 +107,6 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce var buffer_a_image := render_scene_buffers.get_texture_slice(context, buffer_a, view, 0, 1, 1) var buffer_b_image := render_scene_buffers.get_texture_slice(context, buffer_b, view, 0, 1, 1) var custom_velocity_image := render_scene_buffers.get_texture_slice(context, custom_velocity, view, 0, 1, 1) - var debug_1_image := render_scene_buffers.get_texture_slice(context, debug_1, view, 0, 1, 1) - var debug_2_image := render_scene_buffers.get_texture_slice(context, debug_2, view, 0, 1, 1) - var debug_3_image := render_scene_buffers.get_texture_slice(context, debug_3, view, 0, 1, 1) - var debug_4_image := render_scene_buffers.get_texture_slice(context, debug_4, view, 0, 1, 1) - var debug_5_image := render_scene_buffers.get_texture_slice(context, debug_5, view, 0, 1, 1) - var debug_6_image := render_scene_buffers.get_texture_slice(context, debug_6, view, 0, 1, 1) - var debug_7_image := render_scene_buffers.get_texture_slice(context, debug_7, view, 0, 1, 1) - var debug_8_image := render_scene_buffers.get_texture_slice(context, debug_8, view, 0, 1, 1) rd.draw_command_begin_label("Construct blur " + str(view), Color(1.0, 1.0, 1.0, 1.0)) @@ -214,7 +142,7 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce var jf_float_push_constants_test : PackedFloat32Array = [ perpen_error_threshold, sample_step_multiplier, - temp_motion_blur_intensity, + temp_intensity, backtracking_velocity_match_threshold, backtracking_velocity_match_parallel_sensitivity, backtracking_velcoity_match_perpendicular_sensitivity, @@ -243,14 +171,6 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce get_sampler_uniform(custom_velocity_image, 2, false), get_sampler_uniform(buffer_b_image if last_iteration_index % 2 else buffer_a_image, 3, false), get_image_uniform(texture_image, 4), - get_image_uniform(debug_1_image, 5), - get_image_uniform(debug_2_image, 6), - get_image_uniform(debug_3_image, 7), - get_image_uniform(debug_4_image, 8), - get_image_uniform(debug_5_image, 9), - get_image_uniform(debug_6_image, 10), - get_image_uniform(debug_7_image, 11), - get_image_uniform(debug_8_image, 12), ], byte_array, Vector3i(x_groups, y_groups, 1), diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/realistic_jf_blur_stage.tres b/addons/SphynxMotionBlurToolkit/JumpFlood/realistic_jf_blur_stage.tres new file mode 100644 index 0000000..9a28052 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/realistic_jf_blur_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://ceav72kvj4qbw"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_qdmen"] +[ext_resource type="RDShaderFile" uid="uid://b1fr5qhhrbpst" path="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_realistic_blur.glsl" id="2_bdp68"] + +[resource] +script = ExtResource("1_qdmen") +shader_file = ExtResource("2_bdp68") diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/realistic_jf_motion_blur.gd b/addons/SphynxMotionBlurToolkit/JumpFlood/realistic_jf_motion_blur.gd new file mode 100644 index 0000000..cfcce2c --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/realistic_jf_motion_blur.gd @@ -0,0 +1,268 @@ +extends "res://addons/SphynxMotionBlurToolkit/JumpFlood/base_jump_flood_motion_blur.gd" +class_name SphynxRealisticJumpFloodMotionBlur + +@export_group("Shader Stages") +@export var tile_max_x_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_tile_max_x_stage.tres"): + set(value): + unsubscribe_shader_stage(tile_max_x_stage) + tile_max_x_stage = value + subscirbe_shader_stage(value) + +@export var tile_max_y_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_tile_max_y_stage.tres"): + set(value): + unsubscribe_shader_stage(tile_max_y_stage) + tile_max_y_stage = value + subscirbe_shader_stage(value) + +@export var construct_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jf_simple_stage.tres"): + set(value): + unsubscribe_shader_stage(construct_stage) + construct_stage = value + subscirbe_shader_stage(value) + +@export var neighbor_max_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_neighbor_max_stage.tres"): + set(value): + unsubscribe_shader_stage(neighbor_max_stage) + neighbor_max_stage = value + subscirbe_shader_stage(value) + +@export var blur_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/realistic_jf_blur_stage.tres"): + set(value): + unsubscribe_shader_stage(blur_stage) + blur_stage = value + subscirbe_shader_stage(value) + +@export var overlay_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_overlay_stage.tres"): + set(value): + unsubscribe_shader_stage(overlay_stage) + overlay_stage = value + subscirbe_shader_stage(value) + +var tile_max_x : StringName = "tile_max_x" + +var tile_max : StringName = "tile_max" + +var neighbor_max : StringName = "neighbor_max" + +var output_color : StringName = "output_color" + +var buffer_a : StringName = "buffer_a" +var buffer_b : StringName = "buffer_b" + +var custom_velocity : StringName = "custom_velocity" +var temp_intensity : float + +var previous_time : float = 0 + +func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSceneBuffersRD, render_scene_data : RenderSceneDataRD): + var time : float = float(Time.get_ticks_msec()) / 1000 + + var delta_time : float = time - previous_time + + previous_time = time + + temp_intensity = intensity + + if framerate_independent: + var capped_frame_time : float = 1 / target_constant_framerate + + if !uncapped_independence: + capped_frame_time = min(capped_frame_time, delta_time) + + temp_intensity = intensity * capped_frame_time / delta_time + + ensure_texture(custom_velocity, render_scene_buffers) + ensure_texture(tile_max_x, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1.)) + ensure_texture(tile_max, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier)) + ensure_texture(buffer_a, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier)) + ensure_texture(buffer_b, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier)) + ensure_texture(neighbor_max, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier)) + ensure_texture(output_color, render_scene_buffers) + + rd.draw_command_begin_label("Motion Blur", Color(1.0, 1.0, 1.0, 1.0)) + + var last_iteration_index : int = JFA_pass_count - 1; + + var max_dilation_radius : float = pow(2 + step_exponent_modifier, last_iteration_index) * sample_step_multiplier; + + var tile_max_x_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_tile_max_x_push_constants : PackedInt32Array = [ + sample_step_multiplier, + 0, + 0, + 0 + ] + var tile_max_x_push_constants_byte_array = tile_max_x_push_constants.to_byte_array() + tile_max_x_push_constants_byte_array.append_array(int_tile_max_x_push_constants.to_byte_array()) + + var tile_max_y_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_tile_max_y_push_constants : PackedInt32Array = [ + sample_step_multiplier, + 0, + 0, + 0 + ] + var tile_max_y_push_constants_byte_array = tile_max_y_push_constants.to_byte_array() + tile_max_y_push_constants_byte_array.append_array(int_tile_max_y_push_constants.to_byte_array()) + var neighbor_max_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_neighbor_max_push_constants : PackedInt32Array = [ + 0, + 0, + 0, + 0 + ] + var neighbor_max_push_constants_byte_array = neighbor_max_push_constants.to_byte_array() + neighbor_max_push_constants_byte_array.append_array(int_neighbor_max_push_constants.to_byte_array()) + + var push_constant: PackedFloat32Array = [ + samples, + temp_intensity, + center_fade, + Engine.get_frames_drawn() % 8, + last_iteration_index, + sample_step_multiplier, + step_exponent_modifier, + max_dilation_radius, + ] + var int_push_constant : PackedInt32Array = [ + 0, + 0, + 0, + 0 + ] + var byte_array = push_constant.to_byte_array() + byte_array.append_array(int_push_constant.to_byte_array()) + + var view_count = render_scene_buffers.get_view_count() + for view in range(view_count): + var color_image := render_scene_buffers.get_color_layer(view) + var depth_image := render_scene_buffers.get_depth_layer(view) + var output_color_image := render_scene_buffers.get_texture_slice(context, output_color, view, 0, 1, 1) + var buffer_a_image := render_scene_buffers.get_texture_slice(context, buffer_a, view, 0, 1, 1) + var buffer_b_image := render_scene_buffers.get_texture_slice(context, buffer_b, view, 0, 1, 1) + var custom_velocity_image := render_scene_buffers.get_texture_slice(context, custom_velocity, view, 0, 1, 1) + var tile_max_x_image := render_scene_buffers.get_texture_slice(context, tile_max_x, view, 0, 1, 1) + var tile_max_image := render_scene_buffers.get_texture_slice(context, tile_max, view, 0, 1, 1) + var neighbor_max_image := render_scene_buffers.get_texture_slice(context, neighbor_max, view, 0, 1, 1) + + var x_groups := floori((render_size.x / sample_step_multiplier - 1) / 16 + 1) + var y_groups := floori((render_size.y - 1) / 16 + 1) + + dispatch_stage(tile_max_x_stage, + [ + get_sampler_uniform(custom_velocity_image, 0, false), + get_image_uniform(tile_max_x_image, 1) + ], + tile_max_x_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "TileMaxX", + view) + + x_groups = floori((render_size.x / sample_step_multiplier - 1) / 16 + 1) + y_groups = floori((render_size.y / sample_step_multiplier - 1) / 16 + 1) + + dispatch_stage(tile_max_y_stage, + [ + get_sampler_uniform(tile_max_x_image, 0, false), + get_image_uniform(tile_max_image, 1) + ], + tile_max_y_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "TileMaxY", + view) + + for i in JFA_pass_count: + var jf_push_constants : PackedInt32Array = [ + i, + last_iteration_index, + 0, + 16 + ] + + var step_size : float = round(pow(2 + step_exponent_modifier, last_iteration_index - i)); + + var jf_float_push_constants_test : PackedFloat32Array = [ + perpen_error_threshold, + sample_step_multiplier, + temp_intensity, + 0, + 0, + 0, + 0, + step_exponent_modifier, + step_size, + max_dilation_radius, + 0, + 0 + ] + + var jf_byte_array = jf_push_constants.to_byte_array() + jf_byte_array.append_array(jf_float_push_constants_test.to_byte_array()) + + dispatch_stage(construct_stage, + [ + get_sampler_uniform(tile_max_image, 0, false), + get_image_uniform(buffer_a_image, 1), + get_image_uniform(buffer_b_image, 2), + get_sampler_uniform(buffer_a_image, 3, false), + get_sampler_uniform(buffer_b_image, 4, false), + ], + jf_byte_array, + Vector3i(x_groups, y_groups, 1), + "Construct Blur", + view) + + dispatch_stage(neighbor_max_stage, + [ + get_sampler_uniform(tile_max_image, 0, false), + get_sampler_uniform(buffer_b_image if last_iteration_index % 2 else buffer_a_image, 1, false), + get_image_uniform(neighbor_max_image, 2) + ], + neighbor_max_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "NeighborMax", + view) + + x_groups = floori((render_size.x - 1) / 16 + 1) + y_groups = floori((render_size.y - 1) / 16 + 1) + + dispatch_stage(blur_stage, + [ + get_sampler_uniform(color_image, 0, false), + get_sampler_uniform(depth_image, 1, false), + get_sampler_uniform(custom_velocity_image, 2, false), + get_sampler_uniform(neighbor_max_image, 3, false), + get_image_uniform(output_color_image, 4), + get_sampler_uniform(tile_max_image, 5, false), + ], + byte_array, + Vector3i(x_groups, y_groups, 1), + "Compute Blur", + view) + + dispatch_stage(overlay_stage, + [ + get_sampler_uniform(output_color_image, 0), + get_image_uniform(color_image, 1), + ], + [], + Vector3i(x_groups, y_groups, 1), + "Overlay Result", + view) + + rd.draw_command_end_label() diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/simple_jf_blur_stage.tres b/addons/SphynxMotionBlurToolkit/JumpFlood/simple_jf_blur_stage.tres index 7ac34ee..5a4145a 100644 --- a/addons/SphynxMotionBlurToolkit/JumpFlood/simple_jf_blur_stage.tres +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/simple_jf_blur_stage.tres @@ -1,7 +1,7 @@ [gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://bk5yd5plopwi2"] [ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_ljx3c"] -[ext_resource type="RDShaderFile" uid="uid://bdm5t4l1y3ts7" path="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_new_blur.glsl" id="2_ase62"] +[ext_resource type="RDShaderFile" uid="uid://bdm5t4l1y3ts7" path="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_simple_blur.glsl" id="2_ase62"] [resource] script = ExtResource("1_ljx3c") diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/simple_jf_motion_blur.gd b/addons/SphynxMotionBlurToolkit/JumpFlood/simple_jf_motion_blur.gd index 6c98583..450fcaa 100644 --- a/addons/SphynxMotionBlurToolkit/JumpFlood/simple_jf_motion_blur.gd +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/simple_jf_motion_blur.gd @@ -1,13 +1,6 @@ -extends MotionBlurCompositorEffect +extends "res://addons/SphynxMotionBlurToolkit/JumpFlood/base_jump_flood_motion_blur.gd" class_name SphynxSimpleJumpFloodMotionBlur - -@export_group("Motion Blur", "motion_blur_") -# diminishing returns over 16 -@export_range(4, 64) var motion_blur_samples: int = 16 -# you really don't want this over 0.5, but you can if you want to try -@export_range(0, 0.5, 0.001, "or_greater") var motion_blur_intensity: float = 1 -@export_range(0, 1) var motion_blur_center_fade: float = 0.0 - +@export_group("Shader Stages") @export var tile_max_x_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_tile_max_x_stage.tres"): set(value): unsubscribe_shader_stage(tile_max_x_stage) @@ -44,46 +37,6 @@ class_name SphynxSimpleJumpFloodMotionBlur overlay_stage = value subscirbe_shader_stage(value) -## the portion of speed that is allowed for side bleed of velocities -## during the jfa dilation passes and before backtracking. Getting this a higher value -## would make it so that meshes at movement blur more reliably, but also bleed -## further perpendicularly to their velocity, thus wash elemets behind them out. -@export var perpen_error_threshold : float = 0.5 - -## an initial step size that can increase the dilation radius proportionally, at the -## sacrifice of some quality in the final resolution of the dilation.[br][br] -## the formula for the maximum radius of the dilation (in pixels) is: pow(2 + step_exponent_modifier, JFA_pass_count) * sample_step_multiplier -@export var sample_step_multiplier : int = 16 - -## by default, the jump flood makes samples along distances that start -## at 2 to the power of the pass count you want to perform, which is also -## the dilation radius you desire. You can change it to values higher than -## 2 with this variable, and reach higher dilation radius at the sacrifice of -## some accuracy in the dilation. -## the formula for the maximum radius of the dilation (in pixels) is: pow(2 + step_exponent_modifier, JFA_pass_count) * sample_step_multiplier -@export var step_exponent_modifier : float = 1 - -## the number of passes performed by the jump flood algorithm based dilation, -## each pass added doubles the maximum radius of dilation available.[br][br] -## the formula for the maximum radius of the dilation (in pixels) is: pow(2 + step_exponent_modifier, JFA_pass_count) * sample_step_multiplier -@export var JFA_pass_count : int = 3 - -## wether this motion blur stays the same intensity below -## target_constant_framerate -@export var framerate_independent : bool = true - -## Description: Removes clamping on motion blur scale to allow framerate independent motion -## blur to scale longer than realistically possible when render framerate is higher -## than target framerate.[br][br] -## [color=yellow]Warning:[/color] Turning this on would allow over-blurring of pixels, which -## produces inaccurate results, and would likely cause nausea in players over -## long exposure durations, use with caution and out of artistic intent -@export var uncapped_independence : bool = false - -## if framerate_independent is enabled, the blur would simulate -## sutter speeds at that framerate, and up. -@export var target_constant_framerate : float = 30 - var tile_max_x : StringName = "tile_max_x" var tile_max : StringName = "tile_max" @@ -96,17 +49,7 @@ var buffer_a : StringName = "buffer_a" var buffer_b : StringName = "buffer_b" var custom_velocity : StringName = "custom_velocity" - -var debug_1 : String = "debug_1" -var debug_2 : String = "debug_2" -var debug_3 : String = "debug_3" -var debug_4 : String = "debug_4" -var debug_5 : String = "debug_5" -var debug_6 : String = "debug_6" -var debug_7 : String = "debug_7" -var debug_8 : String = "debug_8" - -var temp_motion_blur_intensity : float +var temp_intensity : float var previous_time : float = 0 @@ -117,7 +60,7 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce previous_time = time - temp_motion_blur_intensity = motion_blur_intensity + temp_intensity = intensity if framerate_independent: var capped_frame_time : float = 1 / target_constant_framerate @@ -125,7 +68,7 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce if !uncapped_independence: capped_frame_time = min(capped_frame_time, delta_time) - temp_motion_blur_intensity = motion_blur_intensity * capped_frame_time / delta_time + temp_intensity = intensity * capped_frame_time / delta_time ensure_texture(custom_velocity, render_scene_buffers) ensure_texture(tile_max_x, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1.)) @@ -134,20 +77,12 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce ensure_texture(buffer_b, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier)) ensure_texture(neighbor_max, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier)) ensure_texture(output_color, render_scene_buffers) - ensure_texture(debug_1, render_scene_buffers) - ensure_texture(debug_2, render_scene_buffers) - ensure_texture(debug_3, render_scene_buffers) - ensure_texture(debug_4, render_scene_buffers) - ensure_texture(debug_5, render_scene_buffers) - ensure_texture(debug_6, render_scene_buffers) - ensure_texture(debug_7, render_scene_buffers) - ensure_texture(debug_8, render_scene_buffers) rd.draw_command_begin_label("Motion Blur", Color(1.0, 1.0, 1.0, 1.0)) var last_iteration_index : int = JFA_pass_count - 1; - var max_dilation_radius : float = pow(2 + step_exponent_modifier, last_iteration_index) * sample_step_multiplier / motion_blur_intensity; + var max_dilation_radius : float = pow(2 + step_exponent_modifier, last_iteration_index) * sample_step_multiplier; var tile_max_x_push_constants: PackedFloat32Array = [ 0, @@ -194,9 +129,9 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce neighbor_max_push_constants_byte_array.append_array(int_neighbor_max_push_constants.to_byte_array()) var push_constant: PackedFloat32Array = [ - motion_blur_samples, - temp_motion_blur_intensity, - motion_blur_center_fade, + samples, + temp_intensity, + center_fade, Engine.get_frames_drawn() % 8, last_iteration_index, sample_step_multiplier, @@ -223,14 +158,6 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce var tile_max_x_image := render_scene_buffers.get_texture_slice(context, tile_max_x, view, 0, 1, 1) var tile_max_image := render_scene_buffers.get_texture_slice(context, tile_max, view, 0, 1, 1) var neighbor_max_image := render_scene_buffers.get_texture_slice(context, neighbor_max, view, 0, 1, 1) - var debug_1_image := render_scene_buffers.get_texture_slice(context, debug_1, view, 0, 1, 1) - var debug_2_image := render_scene_buffers.get_texture_slice(context, debug_2, view, 0, 1, 1) - var debug_3_image := render_scene_buffers.get_texture_slice(context, debug_3, view, 0, 1, 1) - var debug_4_image := render_scene_buffers.get_texture_slice(context, debug_4, view, 0, 1, 1) - var debug_5_image := render_scene_buffers.get_texture_slice(context, debug_5, view, 0, 1, 1) - var debug_6_image := render_scene_buffers.get_texture_slice(context, debug_6, view, 0, 1, 1) - var debug_7_image := render_scene_buffers.get_texture_slice(context, debug_7, view, 0, 1, 1) - var debug_8_image := render_scene_buffers.get_texture_slice(context, debug_8, view, 0, 1, 1) var x_groups := floori((render_size.x / sample_step_multiplier - 1) / 16 + 1) var y_groups := floori((render_size.y - 1) / 16 + 1) @@ -238,8 +165,7 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce dispatch_stage(tile_max_x_stage, [ get_sampler_uniform(custom_velocity_image, 0, false), - get_sampler_uniform(depth_image, 1, false), - get_image_uniform(tile_max_x_image, 2) + get_image_uniform(tile_max_x_image, 1) ], tile_max_x_push_constants_byte_array, Vector3i(x_groups, y_groups, 1), @@ -272,7 +198,7 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce var jf_float_push_constants_test : PackedFloat32Array = [ perpen_error_threshold, sample_step_multiplier, - temp_motion_blur_intensity, + temp_intensity, 0, 0, 0, @@ -293,17 +219,13 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce get_image_uniform(buffer_a_image, 1), get_image_uniform(buffer_b_image, 2), get_sampler_uniform(buffer_a_image, 3, false), - get_sampler_uniform(buffer_b_image, 4, false) + get_sampler_uniform(buffer_b_image, 4, false), ], jf_byte_array, Vector3i(x_groups, y_groups, 1), "Construct Blur", view) - - - rd.draw_command_end_label() - dispatch_stage(neighbor_max_stage, [ get_sampler_uniform(tile_max_image, 0, false), @@ -325,15 +247,7 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce get_sampler_uniform(custom_velocity_image, 2, false), get_sampler_uniform(neighbor_max_image, 3, false), get_image_uniform(output_color_image, 4), - get_image_uniform(debug_1_image, 5), - get_image_uniform(debug_2_image, 6), - get_image_uniform(debug_3_image, 7), - get_image_uniform(debug_4_image, 8), - get_image_uniform(debug_5_image, 9), - get_image_uniform(debug_6_image, 10), - get_image_uniform(debug_7_image, 11), - get_image_uniform(debug_8_image, 12), - get_sampler_uniform(tile_max_image, 13, false) + get_sampler_uniform(tile_max_image, 5, false), ], byte_array, Vector3i(x_groups, y_groups, 1), @@ -343,7 +257,7 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce dispatch_stage(overlay_stage, [ get_sampler_uniform(output_color_image, 0), - get_image_uniform(color_image, 1) + get_image_uniform(color_image, 1), ], [], Vector3i(x_groups, y_groups, 1), diff --git a/addons/SphynxMotionBlurToolkit/LICENSE b/addons/SphynxMotionBlurToolkit/LICENSE new file mode 100644 index 0000000..2dea453 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 sphynx-owner + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/addons/SphynxMotionBlurToolkit/LinearBlurToolkit/LinearMotionBlurMesh.gdshader b/addons/SphynxMotionBlurToolkit/LinearBlurToolkit/LinearMotionBlurMesh.gdshader new file mode 100644 index 0000000..d0e2929 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/LinearBlurToolkit/LinearMotionBlurMesh.gdshader @@ -0,0 +1,152 @@ +shader_type spatial; + +render_mode unshaded, depth_draw_always, fog_disabled; + +uniform sampler2D screen_texture : hint_screen_texture, filter_nearest; +uniform sampler2D depth_texture : hint_depth_texture, filter_nearest; + +uniform vec3 local_stretch_axis = vec3(0, 1, 0); + +uniform float movement_speed = 0; + +uniform int sample_count = 8; + +uniform float debug_toggle = 0; + +uniform vec4 debug_color : source_color = vec4(0); + +//https://www.shadertoy.com/view/fdtfWM +vec3 rotate(float angle, vec3 axis, vec3 point) // NOTE: axis must be unit! +{ + float c = cos(angle); + float s = sin(angle); + return c * point + s * cross(axis, point) + (1.0 - c) * (dot(point, axis) * axis); // Rodrigues' Rotation Formula +} + +// from https://www.shadertoy.com/view/ftKfzc +float interleaved_gradient_noise(vec2 uv, int FrameId){ + uv += float(FrameId) * (vec2(47, 17) * 0.695); + + vec3 magic = vec3( 0.06711056, 0.00583715, 52.9829189 ); + + return fract(magic.z * fract(dot(uv, magic.xy))); +} + +vec3 get_projection_onto_plane(vec3 plane_origin, vec3 normal, vec3 vector) +{ + float plane_distance = dot(plane_origin, normal); + return vector * plane_distance / dot(normal, vector); +} + +float soft_depth_compare(float x, float y, float sze) +{ + return clamp(1. - (x - y) / sze, 0., 1.); +} + +vec2 intersect_cylinder(vec3 eye_point, vec3 end_point, vec3 origin, vec3 axis, float radius) +{ + eye_point -= axis * dot(eye_point - origin, axis) + origin; + + end_point -= axis * dot(end_point - origin, axis) + origin; + + vec3 direction = end_point - eye_point; + + float A = dot(direction, direction); + float B = 2. * dot(eye_point, direction); + float C = dot(eye_point, eye_point) - radius * radius; + + float square_component = sqrt(B * B - 4. * A * C); + + return vec2(-B + square_component, -B - square_component) / (2. * A); +} + +vec2 within_cylinder(vec3 point, vec3 origin, vec3 axis, float radius, float depth, float axis_offset) +{ + float within_depth = step(abs(dot(point - origin - axis * axis_offset, axis)), depth / 2.); + vec3 perpendicular_component = point - axis * dot(axis, point - origin) - origin; + float within_radius = step(dot(perpendicular_component, perpendicular_component), radius * radius); + + return vec2(within_depth * within_radius, step(0, dot(point - origin, axis))); +} + +vec3 color_corrected(vec3 color) +{ + return color / mix( + pow((vec3(1.) + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), + vec3(1.) * (1.0 / 12.92), + lessThan(vec3(1.), vec3(0.04045))); +} + +void fragment() { + vec2 screen_uv = SCREEN_UV; + + float depth = texture(depth_texture, screen_uv).x; + vec3 ndc = vec3(screen_uv * 2.0 - 1.0, depth); + vec4 world_position = INV_VIEW_MATRIX * INV_PROJECTION_MATRIX * vec4(ndc, 1.0); + world_position.xyz /= world_position.w; + + vec4 world_mesh_position = INV_VIEW_MATRIX * INV_PROJECTION_MATRIX * vec4(screen_uv * 2.0 - 1.0, FRAGCOORD.z, 1.0); + world_mesh_position.xyz /= world_mesh_position.w; + + vec3 node_relative_position = world_position.xyz - NODE_POSITION_WORLD; + + vec3 camera_node_position = NODE_POSITION_WORLD - CAMERA_POSITION_WORLD; + + vec3 camera_relative_position = world_position.xyz - CAMERA_POSITION_WORLD; + + float on_mesh = 1.; + + vec3 raw_clamped_difference = vec3(0.); + + node_relative_position = world_mesh_position.xyz - NODE_POSITION_WORLD; + + float noise_variation = interleaved_gradient_noise(SCREEN_UV * vec2(textureSize(screen_texture, 0)), int(TIME * 100.)) / float(sample_count); + + float sum = 1.; + + vec4 base_sample = texture(screen_texture, screen_uv); + + vec4 col = base_sample; + + float original_depth = 0.05 / depth; + + for(int i = 0; i < sample_count; i++) + { + vec3 node_rotated_sample = node_relative_position.xyz + mat3(MODEL_MATRIX) * vec3(movement_speed * (local_stretch_axis * (float(i) / float(sample_count) + noise_variation))); + + vec4 current_ndc = (PROJECTION_MATRIX * VIEW_MATRIX * (vec4(node_rotated_sample, 1) + vec4(NODE_POSITION_WORLD, 0))); + + current_ndc.xyz /= current_ndc.w; + + vec2 current_uv_sample = ((current_ndc + 1.) / 2.).xy ; + + float current_depth = texture(depth_texture, current_uv_sample).x; + + vec4 current_world_position = INV_VIEW_MATRIX * INV_PROJECTION_MATRIX * vec4(vec3(current_ndc.xy, current_depth), 1.0); + + current_world_position.xyz /= current_world_position.w; + + current_depth = 0.05 / current_depth; + + float current_sample_depth = 0.05 / current_ndc.z; + + if (current_uv_sample.x < 0. || current_uv_sample.x > 1. || current_uv_sample.y < 0. || current_uv_sample.y > 1.) + { + continue; + } + + float is_inside = step(current_depth - current_sample_depth, 1); + + float original_inside = 1. - step(current_depth - original_depth, 1); + + float revert_texture = max(is_inside, original_inside); + + float weight = 1.; + sum += weight; + col += mix(base_sample, texture(screen_texture, current_uv_sample), revert_texture) * weight; + } + + col /= sum; + + ALBEDO = col.xyz + debug_color.xyz;//vec3(depth * 10.);// +} diff --git a/addons/SphynxMotionBlurToolkit/LinearBlurToolkit/LinearMotionBlurMesh.tscn b/addons/SphynxMotionBlurToolkit/LinearBlurToolkit/LinearMotionBlurMesh.tscn new file mode 100644 index 0000000..d2153b3 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/LinearBlurToolkit/LinearMotionBlurMesh.tscn @@ -0,0 +1,21 @@ +[gd_scene load_steps=5 format=3 uid="uid://b8aytbebcsmv8"] + +[ext_resource type="Shader" path="res://addons/SphynxMotionBlurToolkit/LinearBlurToolkit/LinearMotionBlurMesh.gdshader" id="1_m7mjv"] +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/LinearBlurToolkit/linear_motion_blur_mesh.gd" id="2_glqur"] + +[sub_resource type="BoxMesh" id="BoxMesh_lylv4"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_oosyj"] +resource_local_to_scene = true +render_priority = 0 +shader = ExtResource("1_m7mjv") +shader_parameter/local_stretch_axis = Vector3(0, 1, 0) +shader_parameter/movement_speed = 0.0 +shader_parameter/sample_count = 8 +shader_parameter/debug_toggle = 0.0 +shader_parameter/debug_color = Color(0, 0, 0, 0) + +[node name="LinearMotionBlurMesh" type="MeshInstance3D"] +mesh = SubResource("BoxMesh_lylv4") +surface_material_override/0 = SubResource("ShaderMaterial_oosyj") +script = ExtResource("2_glqur") diff --git a/addons/SphynxMotionBlurToolkit/LinearBlurToolkit/linear_motion_blur_mesh.gd b/addons/SphynxMotionBlurToolkit/LinearBlurToolkit/linear_motion_blur_mesh.gd new file mode 100644 index 0000000..886d345 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/LinearBlurToolkit/linear_motion_blur_mesh.gd @@ -0,0 +1,63 @@ +extends MeshInstance3D +class_name LinearMotionBlurMesh + +@export var target_node : Node3D + +## the rotation vector the current mesh blur's around +## locally +@export_enum("x", "y", "z") var local_stretch_axis : int + +@export var negate_local_stretch_axis : bool = false + +@onready var local_stretch_vector : Vector3 = Vector3(1 if local_stretch_axis == 0 else 0, 1 if local_stretch_axis == 1 else 0, 1 if local_stretch_axis == 2 else 0) * (1 if !negate_local_stretch_axis else -1) + +## At what speed does the mesh become visible and start blurring +@export var speed_visibility_threshold : float = 0.2 + +## make mesh visible for debugging +@export var show_debug : bool = false + +var previous_mesh_transform : Transform3D = Transform3D() + +var shape_depth : float = 0 + +func _ready(): + get_surface_override_material(0).set_shader_parameter("debug_color", Color(0, 0, 0, 0) if !show_debug else Color(1, 0, 0, 0)) + + var mesh_aabb : AABB = mesh.get_aabb() + + var extent : Vector3 = mesh_aabb.size * global_basis.get_scale() + + var center : Vector3 = mesh_aabb.get_center() * global_basis.get_scale() + + var all_axis : Array[float] = [extent.x, extent.y, extent.z] + + shape_depth = all_axis[local_stretch_axis] + + previous_mesh_transform = target_node.global_transform + + deferred_update_cylinder_data.call_deferred() + +func deferred_update_cylinder_data(): + get_surface_override_material(0).set_shader_parameter("local_stretch_axis", local_stretch_vector) + +func _process(delta: float) -> void: + var target_transform : Transform3D = target_node.global_transform + + var offset : Vector3 = target_transform.origin - previous_mesh_transform.origin + + var distance : float = (offset).length() + + visible = distance > speed_visibility_threshold + + get_surface_override_material(0).set_shader_parameter("movement_speed", distance / (distance + shape_depth)) + + global_position = target_transform.origin - offset / 2 + + previous_mesh_transform = target_transform + + var alignment_quaternion : Quaternion = Quaternion(global_basis.orthonormalized() * local_stretch_vector, offset.normalized()) + + global_basis = Basis(alignment_quaternion) * global_basis; + + scale = scale * (Vector3(1, 1, 1) - local_stretch_vector) + local_stretch_vector * (distance + shape_depth) diff --git a/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_blur.glsl b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_blur.glsl index 5ba1804..a3e9681 100644 --- a/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_blur.glsl +++ b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_blur.glsl @@ -14,9 +14,9 @@ layout(rgba16f, set = 0, binding = 6) uniform image2D past_color_image; layout(push_constant, std430) uniform Params { - float minimum_user_threshold; - float importance_bias; - float maximum_jitter_value; + float nan5; + float nan6; + float nan7; float nan8; int tile_size; int sample_count; diff --git a/addons/SphynxMotionBlurToolkit/McGuire/base_mcguire_motion_blur.gd b/addons/SphynxMotionBlurToolkit/McGuire/base_mcguire_motion_blur.gd new file mode 100644 index 0000000..a858ad8 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/base_mcguire_motion_blur.gd @@ -0,0 +1,4 @@ +extends "res://addons/SphynxMotionBlurToolkit/BaseClasses/mb_compositor_effect.gd" + +@export_group("Shader Parameters") +@export var tile_size : int = 40 diff --git a/addons/SphynxMotionBlurToolkit/McGuire/mcguire_motion_blur.gd b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_motion_blur.gd index 75b3501..49e8e2d 100644 --- a/addons/SphynxMotionBlurToolkit/McGuire/mcguire_motion_blur.gd +++ b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_motion_blur.gd @@ -1,13 +1,7 @@ -extends MotionBlurCompositorEffect +extends "res://addons/SphynxMotionBlurToolkit/McGuire/base_mcguire_motion_blur.gd" class_name McGuireMotionBlur -@export_group("Motion Blur", "motion_blur_") -# diminishing returns over 16 -@export_range(4, 64) var motion_blur_samples: int = 25 -# you really don't want this over 0.5, but you can if you want to try -@export_range(0, 0.5, 0.001, "or_greater") var motion_blur_intensity: float = 1 -@export_range(0, 1) var motion_blur_center_fade: float = 0.0 - +@export_group("Shader Stages") @export var blur_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/McGuire/mcguire_blur_stage.tres"): set(value): unsubscribe_shader_stage(blur_stage) @@ -44,16 +38,6 @@ class_name McGuireMotionBlur tile_variance_stage = value subscirbe_shader_stage(value) -@export var tile_size : int = 40 - -@export var linear_falloff_slope : float = 1 - -@export var importance_bias : float = 40 - -@export var maximum_jitter_value : float = 0.95 - -@export var minimum_user_threshold : float = 1.5 - var output_color: StringName = "output_color" var tile_max_x : StringName = "tile_max_x" @@ -145,14 +129,14 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce tile_variance_push_constants_byte_array.append_array(int_tile_variance_push_constants.to_byte_array()) var blur_push_constants: PackedFloat32Array = [ - minimum_user_threshold, - importance_bias, - maximum_jitter_value, + 0, + 0, + 0, 0, ] var int_blur_push_constants : PackedInt32Array = [ tile_size, - motion_blur_samples, + samples, Engine.get_frames_drawn() % 8, 0 ] diff --git a/addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_camera_movement_component.tres b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_camera_movement_component.tres new file mode 100644 index 0000000..3d06652 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_camera_movement_component.tres @@ -0,0 +1,9 @@ +[gd_resource type="Resource" script_class="BlurVelocityComponentResource" load_steps=2 format=3 uid="uid://cslvcweyejh3c"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/blur_velocity_component_resource.gd" id="1_856ea"] + +[resource] +script = ExtResource("1_856ea") +multiplier = 1.0 +lower_threshold = 0.0 +upper_threshold = 0.0 diff --git a/addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_camera_rotation_component.tres b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_camera_rotation_component.tres new file mode 100644 index 0000000..f2f1b05 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_camera_rotation_component.tres @@ -0,0 +1,9 @@ +[gd_resource type="Resource" script_class="BlurVelocityComponentResource" load_steps=2 format=3 uid="uid://iru8ynu04i00"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/blur_velocity_component_resource.gd" id="1_j2iku"] + +[resource] +script = ExtResource("1_j2iku") +multiplier = 1.0 +lower_threshold = 0.0 +upper_threshold = 0.0 diff --git a/addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_component.tres b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_object_movement_component.tres similarity index 100% rename from addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_component.tres rename to addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_object_movement_component.tres diff --git a/addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processor.gd b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processor.gd index 21757ee..13ba964 100644 --- a/addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processor.gd +++ b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processor.gd @@ -1,16 +1,17 @@ -extends EnhancedCompositorEffect +extends "res://addons/SphynxMotionBlurToolkit/BaseClasses/enhanced_compositor_effect.gd" class_name PreBlurProcessor - +@export_group("Shader Stages") @export var pre_blur_processor_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processing_stage.tres"): set(value): unsubscribe_shader_stage(pre_blur_processor_stage) pre_blur_processor_stage = value subscirbe_shader_stage(value) -@export var camera_rotation_component : BlurVelocityComponentResource = preload("res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_component.tres") -@export var camera_movement_component : BlurVelocityComponentResource = preload("res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_component.tres") -@export var object_movement_component : BlurVelocityComponentResource = preload("res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_component.tres") +@export_group("Blur Components") +@export var camera_rotation_component : BlurVelocityComponentResource = preload("res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_camera_rotation_component.tres") +@export var camera_movement_component : BlurVelocityComponentResource = preload("res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_camera_movement_component.tres") +@export var object_movement_component : BlurVelocityComponentResource = preload("res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_object_movement_component.tres") var custom_velocity : StringName = "custom_velocity" diff --git a/addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processor.glsl b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processor.glsl index c306d26..dc8df55 100644 --- a/addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processor.glsl +++ b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processor.glsl @@ -146,7 +146,10 @@ void main() vec3 past_uv = vec3(view_past_ndc.xy * 0.5 + 0.5, view_past_ndc.z); + vec4 view_past_ndc_cache = view_past_ndc; + vec3 camera_uv_change = past_uv - vec3(uvn, depth); + // get just rotation change world_local_position = mat4(mat3(scene_data.inv_view_matrix)) * vec4(view_position.xyz, 1.0); @@ -186,5 +189,16 @@ void main() total_velocity = base_velocity; } - imageStore(vector_output, uvi, vec4(total_velocity, 1.0)); + float total_velocity_length = max(FLT_MIN, length(total_velocity)); + total_velocity = total_velocity * clamp(total_velocity_length, 0, 1) / total_velocity_length; + + imageStore(vector_output, uvi, vec4(total_velocity * (view_past_ndc_cache.w < 0 ? -1 : 1), depth));//, depth));// + +#ifdef DEBUG + vec2 velocity = textureLod(vector_sampler, uvn, 0.0).xy; + float velocity_length = length(velocity); + velocity = velocity * clamp(velocity_length, 0, 10) / velocity_length; + imageStore(debug_6_image, uvi, vec4(velocity * (view_past_ndc_cache.w < 0 ? -1 : 1), view_past_ndc_cache.w < 0 ? 1 : 0, 1)); + imageStore(debug_7_image, uvi, vec4(camera_uv_change.xy, 0, 1)); +#endif } \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/RadialBlurToolkit/radial_blur_mesh.tscn b/addons/SphynxMotionBlurToolkit/RadialBlurToolkit/radial_blur_mesh.tscn index 6e396b9..0bf0585 100644 --- a/addons/SphynxMotionBlurToolkit/RadialBlurToolkit/radial_blur_mesh.tscn +++ b/addons/SphynxMotionBlurToolkit/RadialBlurToolkit/radial_blur_mesh.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=5 format=3 uid="uid://8p6li7o742g3"] -[ext_resource type="Shader" path="res://RadialBlurTest/radial_blur_mesh.gdshader" id="1_36vys"] -[ext_resource type="Script" path="res://RadialBlurTest/radial_blur_mesh.gd" id="2_cfhks"] +[ext_resource type="Shader" path="res://addons/SphynxMotionBlurToolkit/RadialBlurToolkit/radial_blur_mesh.gdshader" id="1_36vys"] +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/RadialBlurToolkit/radial_blur_mesh.gd" id="2_cfhks"] [sub_resource type="CylinderMesh" id="CylinderMesh_pgvyt"] resource_local_to_scene = true