diff --git a/addons/MyJumpFloodIteration/LICENSE-MotionBlurEffect b/addons/MyJumpFloodIteration/LICENSE-MotionBlurEffect deleted file mode 100644 index 2dea453..0000000 --- a/addons/MyJumpFloodIteration/LICENSE-MotionBlurEffect +++ /dev/null @@ -1,21 +0,0 @@ -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/MyJumpFloodIteration/jfp_backtracking_experimental.glsl.import b/addons/MyJumpFloodIteration/jfp_backtracking_experimental.glsl.import deleted file mode 100644 index 4eb6671..0000000 --- a/addons/MyJumpFloodIteration/jfp_backtracking_experimental.glsl.import +++ /dev/null @@ -1,14 +0,0 @@ -[remap] - -importer="glsl" -type="RDShaderFile" -uid="uid://3v1b0hrdm7nw" -path="res://.godot/imported/jfp_backtracking_experimental.glsl-d67307f6899fed647164be410a7debc8.res" - -[deps] - -source_file="res://MyJumpFloodIteration/jfp_backtracking_experimental.glsl" -dest_files=["res://.godot/imported/jfp_backtracking_experimental.glsl-d67307f6899fed647164be410a7debc8.res"] - -[params] - diff --git a/addons/MyJumpFloodIteration/jump_flood_blur.gd b/addons/MyJumpFloodIteration/jump_flood_blur.gd deleted file mode 100644 index 7948086..0000000 --- a/addons/MyJumpFloodIteration/jump_flood_blur.gd +++ /dev/null @@ -1,355 +0,0 @@ -extends CompositorEffect -class_name MotionBlurSphynxJumpFlood - -@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 var blur_shader_file : RDShaderFile = preload("res://addons/MyJumpFloodIteration/jump_flood_blur.glsl"): - set(value): - blur_shader_file = value - _init() - -@export var overlay_shader_file : RDShaderFile = preload("res://addons/MyJumpFloodIteration/jump_flood_overlay.glsl"): - set(value): - overlay_shader_file = value - _init() - -@export var construction_pass : RDShaderFile = preload("res://addons/MyJumpFloodIteration/jfp_backtracking_experimental.glsl"): - set(value): - construction_pass = value - _init() - -## 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.3 - -## 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 = 4 - -## 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 -@export var backtracking_sample_count : int = 8 - -## how sensitive the backtracking for velocities be -@export var backtracking_velocity_match_threshold : float = 0.9 - -## how sensitively the backtracking should treat velocities that are a different -## length along that velocity -@export var backtracking_velocity_match_parallel_sensitivity : float = 1 - -## how sensitively the backtracking should treat velcoities that have perpendicular -## offset to that velocity -@export var backtracking_velcoity_match_perpendicular_sensitivity : float = 0.05 - -## how closely does the depth of the backtracked sample has to match the original sample to be -## 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 - -## wether to display debug views for velocity and depth -## buffers -@export var draw_debug : bool = false - -## currently 0 - 1, flip between velocity buffers -## and depth buffers debug views -@export var debug_page : int = 0 - -var rd: RenderingDevice - -var linear_sampler: RID - -var nearest_sampler : RID - -var construct_shader : RID -var construct_pipeline : RID - -var motion_blur_shader: RID -var motion_blur_pipeline: RID - -var overlay_shader: RID -var overlay_pipeline: RID - -var context: StringName = "MotionBlur" -var texture: StringName = "texture" - -var buffer_a : StringName = "buffer_a" -var buffer_b : StringName = "buffer_b" - -var past_color : StringName = "past_color" - -var custom_velocity : StringName = "custom_velocity" - -var freeze : bool = false - -func _init(): - #effect_callback_type = EFFECT_CALLBACK_TYPE_POST_TRANSPARENT - needs_motion_vectors = true - RenderingServer.call_on_render_thread(_initialize_compute) - -func _notification(what): - if what == NOTIFICATION_PREDELETE: - if linear_sampler.is_valid(): - rd.free_rid(linear_sampler) - if motion_blur_shader.is_valid(): - rd.free_rid(motion_blur_shader) - if overlay_shader.is_valid(): - rd.free_rid(overlay_shader) - -func _initialize_compute(): - rd = RenderingServer.get_rendering_device() - if !rd: - return - - var sampler_state := RDSamplerState.new() - sampler_state.min_filter = RenderingDevice.SAMPLER_FILTER_LINEAR - sampler_state.mag_filter = RenderingDevice.SAMPLER_FILTER_LINEAR - sampler_state.repeat_u = RenderingDevice.SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE - sampler_state.repeat_v = RenderingDevice.SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE - linear_sampler = rd.sampler_create(sampler_state) - - sampler_state.min_filter = RenderingDevice.SAMPLER_FILTER_NEAREST - sampler_state.mag_filter = RenderingDevice.SAMPLER_FILTER_NEAREST - sampler_state.repeat_u = RenderingDevice.SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE - sampler_state.repeat_v = RenderingDevice.SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE - - nearest_sampler = rd.sampler_create(sampler_state) - - var construct_shader_spirv : RDShaderSPIRV = construction_pass.get_spirv() - construct_shader = rd.shader_create_from_spirv(construct_shader_spirv) - construct_pipeline = rd.compute_pipeline_create(construct_shader) - - var shader_spirv: RDShaderSPIRV = blur_shader_file.get_spirv() - motion_blur_shader = rd.shader_create_from_spirv(shader_spirv) - motion_blur_pipeline = rd.compute_pipeline_create(motion_blur_shader) - - var overlay_shader_spirv: RDShaderSPIRV = overlay_shader_file.get_spirv() - overlay_shader = rd.shader_create_from_spirv(overlay_shader_spirv) - overlay_pipeline = rd.compute_pipeline_create(overlay_shader) - -func get_image_uniform(image: RID, binding: int) -> RDUniform: - var uniform: RDUniform = RDUniform.new() - uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_IMAGE - uniform.binding = binding - uniform.add_id(image) - return uniform - -func get_sampler_uniform(image: RID, binding: int, linear : bool = true) -> RDUniform: - var uniform: RDUniform = RDUniform.new() - uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_SAMPLER_WITH_TEXTURE - uniform.binding = binding - uniform.add_id(linear_sampler if linear else nearest_sampler) - uniform.add_id(image) - return uniform - -var temp_motion_blur_intensity : float - -var previous_time : float = 0 - -func _render_callback(p_effect_callback_type, p_render_data): - var time : float = float(Time.get_ticks_msec()) / 1000 - - var delta_time : float = time - previous_time - - previous_time = time - - temp_motion_blur_intensity = motion_blur_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_motion_blur_intensity = motion_blur_intensity * capped_frame_time / delta_time - - if rd: - var render_scene_buffers: RenderSceneBuffersRD = p_render_data.get_render_scene_buffers() - var render_scene_data: RenderSceneDataRD = p_render_data.get_render_scene_data() - if render_scene_buffers and render_scene_data: - var render_size: Vector2 = render_scene_buffers.get_internal_size() - if render_size.x == 0.0 or render_size.y == 0.0: - return - - ensure_texture(texture, render_scene_buffers) - ensure_texture(buffer_a, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16_SFLOAT) - ensure_texture(buffer_b, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16_SFLOAT) - ensure_texture(past_color, render_scene_buffers) - ensure_texture(custom_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 / motion_blur_intensity; - - var push_constant: PackedFloat32Array = [ - motion_blur_samples, temp_motion_blur_intensity, - motion_blur_center_fade, 1 if draw_debug else 0, - freeze, - Engine.get_frames_drawn() % 8, - last_iteration_index, - sample_step_multiplier, - step_exponent_modifier, - max_dilation_radius, - 0, - 0 - ] - var int_push_constant : PackedInt32Array = [ - debug_page, - 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 texture_image := render_scene_buffers.get_texture_slice(context, texture, 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 past_color_image := render_scene_buffers.get_texture_slice(context, past_color, view, 0, 1, 1) - var custom_velocity_image := render_scene_buffers.get_texture_slice(context, custom_velocity, view, 0, 1, 1) - rd.draw_command_begin_label("Construct blur " + str(view), Color(1.0, 1.0, 1.0, 1.0)) - - var tex_uniform_set - var compute_list - - var x_groups := floori((render_size.x - 1) / 16 + 1) - var y_groups := floori((render_size.y - 1) / 16 + 1) - - tex_uniform_set = UniformSetCacheRD.get_cache(construct_shader, 0, [ - get_sampler_uniform(depth_image, 0, false), - get_sampler_uniform(custom_velocity_image, 1, false), - get_image_uniform(buffer_a_image, 2), - get_image_uniform(buffer_b_image, 3), - get_sampler_uniform(buffer_a_image, 4, false), - get_sampler_uniform(buffer_b_image, 5, false) - ]) - - compute_list = rd.compute_list_begin() - rd.compute_list_bind_compute_pipeline(compute_list, construct_pipeline) - rd.compute_list_bind_uniform_set(compute_list, tex_uniform_set, 0) - - for i in JFA_pass_count: - var jf_push_constants : PackedInt32Array = [ - i, - last_iteration_index, - backtracking_sample_count, - 16 - ] - - var step_size : float = round(pow(2 + step_exponent_modifier, last_iteration_index - i)) * sample_step_multiplier; - - var jf_float_push_constants_test : PackedFloat32Array = [ - perpen_error_threshold, - sample_step_multiplier, - temp_motion_blur_intensity, - backtracking_velocity_match_threshold, - backtracking_velocity_match_parallel_sensitivity, - backtracking_velcoity_match_perpendicular_sensitivity, - backtracbing_depth_match_threshold, - 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()) - - rd.compute_list_set_push_constant(compute_list, jf_byte_array, jf_byte_array.size()) - rd.compute_list_dispatch(compute_list, x_groups, y_groups, 1) - - rd.compute_list_end() - - rd.draw_command_end_label() - - rd.draw_command_begin_label("Compute blur " + str(view), Color(1.0, 1.0, 1.0, 1.0)) - - tex_uniform_set = UniformSetCacheRD.get_cache(motion_blur_shader, 0, [ - 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(buffer_b_image if last_iteration_index % 2 else buffer_a_image, 3, false), - get_image_uniform(texture_image, 4), - get_image_uniform(past_color_image, 5), - ]) - - compute_list = rd.compute_list_begin() - rd.compute_list_bind_compute_pipeline(compute_list, motion_blur_pipeline) - rd.compute_list_bind_uniform_set(compute_list, tex_uniform_set, 0) - rd.compute_list_set_push_constant(compute_list, byte_array, byte_array.size()) - rd.compute_list_dispatch(compute_list, x_groups, y_groups, 1) - rd.compute_list_end() - rd.draw_command_end_label() - - rd.draw_command_begin_label("Overlay result " + str(view), Color(1.0, 1.0, 1.0, 1.0)) - - tex_uniform_set = UniformSetCacheRD.get_cache(overlay_shader, 0, [ - get_sampler_uniform(texture_image, 0), - get_image_uniform(color_image, 1), - ]) - - compute_list = rd.compute_list_begin() - rd.compute_list_bind_compute_pipeline(compute_list, overlay_pipeline) - rd.compute_list_bind_uniform_set(compute_list, tex_uniform_set, 0) - rd.compute_list_dispatch(compute_list, x_groups, y_groups, 1) - rd.compute_list_end() - rd.draw_command_end_label() - - rd.draw_command_end_label() - - -func ensure_texture(texture_name : StringName, render_scene_buffers : RenderSceneBuffersRD, texture_format : RenderingDevice.DataFormat = RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, high_accuracy : bool = false, render_size_multiplier : Vector2 = Vector2(1, 1)): - var render_size : Vector2 = Vector2(render_scene_buffers.get_internal_size()) * render_size_multiplier - - if render_scene_buffers.has_texture(context, texture_name): - var tf: RDTextureFormat = render_scene_buffers.get_texture_format(context, texture_name) - if tf.width != render_size.x or tf.height != render_size.y: - render_scene_buffers.clear_context(context) - - if !render_scene_buffers.has_texture(context, texture_name): - var usage_bits: int = RenderingDevice.TEXTURE_USAGE_SAMPLING_BIT | RenderingDevice.TEXTURE_USAGE_STORAGE_BIT - render_scene_buffers.create_texture(context, texture_name, texture_format, usage_bits, RenderingDevice.TEXTURE_SAMPLES_1, render_size, 1, 1, true) diff --git a/addons/MyJumpFloodIteration/jump_flood_blur.glsl.import b/addons/MyJumpFloodIteration/jump_flood_blur.glsl.import deleted file mode 100644 index 153a4e6..0000000 --- a/addons/MyJumpFloodIteration/jump_flood_blur.glsl.import +++ /dev/null @@ -1,14 +0,0 @@ -[remap] - -importer="glsl" -type="RDShaderFile" -uid="uid://wfmvke70qcpa" -path="res://.godot/imported/jump_flood_blur.glsl-df0c6b7cc65d8b0520871790f9075253.res" - -[deps] - -source_file="res://MyJumpFloodIteration/jump_flood_blur.glsl" -dest_files=["res://.godot/imported/jump_flood_blur.glsl-df0c6b7cc65d8b0520871790f9075253.res"] - -[params] - diff --git a/addons/MyJumpFloodIteration/jump_flood_overlay.glsl.import b/addons/MyJumpFloodIteration/jump_flood_overlay.glsl.import deleted file mode 100644 index 3366cf8..0000000 --- a/addons/MyJumpFloodIteration/jump_flood_overlay.glsl.import +++ /dev/null @@ -1,14 +0,0 @@ -[remap] - -importer="glsl" -type="RDShaderFile" -uid="uid://bbnb4hw0aoqy1" -path="res://.godot/imported/jump_flood_overlay.glsl-764d3c488a9e9576eab825591e868325.res" - -[deps] - -source_file="res://MyJumpFloodIteration/jump_flood_overlay.glsl" -dest_files=["res://.godot/imported/jump_flood_overlay.glsl-764d3c488a9e9576eab825591e868325.res"] - -[params] - diff --git a/addons/PreBlurProcessing/pre_blur_processor.gd b/addons/PreBlurProcessing/pre_blur_processor.gd deleted file mode 100644 index 8f0c9a4..0000000 --- a/addons/PreBlurProcessing/pre_blur_processor.gd +++ /dev/null @@ -1,158 +0,0 @@ -extends CompositorEffect -class_name PreBlurProcessor - -@export var pre_blur_processor_shader_file : RDShaderFile = preload("res://addons/PreBlurProcessing/pre_blur_processor.glsl"): - set(value): - pre_blur_processor_shader_file = value - _init() - -@export var camera_rotation_component : BlurVelocityComponentResource = preload("res://addons/PreBlurProcessing/default_component.tres") -@export var camera_movement_component : BlurVelocityComponentResource = preload("res://addons/PreBlurProcessing/default_component.tres") -@export var object_movement_component : BlurVelocityComponentResource = preload("res://addons/PreBlurProcessing/default_component.tres") - -var context: StringName = "MotionBlur" - -var rd: RenderingDevice - -var linear_sampler: RID - -var nearest_sampler : RID - -var construct_shader : RID -var construct_pipeline : RID - -var pre_blur_processor_shader: RID -var pre_blur_processor_pipeline: RID - -var custom_velocity : StringName = "custom_velocity" - -func _init(): - needs_motion_vectors = true - RenderingServer.call_on_render_thread(_initialize_compute) - -func _notification(what): - if what == NOTIFICATION_PREDELETE: - if linear_sampler.is_valid(): - rd.free_rid(linear_sampler) - if pre_blur_processor_shader.is_valid(): - rd.free_rid(pre_blur_processor_shader) - -func _initialize_compute(): - rd = RenderingServer.get_rendering_device() - if !rd: - return - - var sampler_state := RDSamplerState.new() - sampler_state.min_filter = RenderingDevice.SAMPLER_FILTER_LINEAR - sampler_state.mag_filter = RenderingDevice.SAMPLER_FILTER_LINEAR - sampler_state.repeat_u = RenderingDevice.SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE - sampler_state.repeat_v = RenderingDevice.SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE - linear_sampler = rd.sampler_create(sampler_state) - - sampler_state.min_filter = RenderingDevice.SAMPLER_FILTER_NEAREST - sampler_state.mag_filter = RenderingDevice.SAMPLER_FILTER_NEAREST - sampler_state.repeat_u = RenderingDevice.SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE - sampler_state.repeat_v = RenderingDevice.SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE - nearest_sampler = rd.sampler_create(sampler_state) - - var shader_spirv: RDShaderSPIRV = pre_blur_processor_shader_file.get_spirv() - pre_blur_processor_shader = rd.shader_create_from_spirv(shader_spirv) - pre_blur_processor_pipeline = rd.compute_pipeline_create(pre_blur_processor_shader) - -func get_image_uniform(image: RID, binding: int) -> RDUniform: - var uniform: RDUniform = RDUniform.new() - uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_IMAGE - uniform.binding = binding - uniform.add_id(image) - return uniform - -func get_sampler_uniform(image: RID, binding: int, linear : bool = true) -> RDUniform: - var uniform: RDUniform = RDUniform.new() - uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_SAMPLER_WITH_TEXTURE - uniform.binding = binding - uniform.add_id(linear_sampler if linear else nearest_sampler) - uniform.add_id(image) - return uniform - -func _render_callback(p_effect_callback_type, p_render_data : RenderData): - if rd: - var render_scene_buffers: RenderSceneBuffersRD = p_render_data.get_render_scene_buffers() - var render_scene_data: RenderSceneDataRD = p_render_data.get_render_scene_data() - if render_scene_buffers and render_scene_data: - var render_size: Vector2 = render_scene_buffers.get_internal_size() - if render_size.x == 0.0 or render_size.y == 0.0: - return - - ensure_texture(custom_velocity, render_scene_buffers) - - rd.draw_command_begin_label("Pre Blur Processing", Color(1.0, 1.0, 1.0, 1.0)) - - var float_pre_blur_push_constants: PackedFloat32Array = [ - camera_rotation_component.multiplier, - camera_movement_component.multiplier, - object_movement_component.multiplier, - camera_rotation_component.lower_threshold, - camera_movement_component.lower_threshold, - object_movement_component.lower_threshold, - camera_rotation_component.upper_threshold, - camera_movement_component.upper_threshold, - object_movement_component.upper_threshold, - 1 if true else 0, - 0, - 0, - ] - - var int_pre_blur_push_constants : PackedInt32Array = [ - ] - - var byte_array = float_pre_blur_push_constants.to_byte_array() - byte_array.append_array(int_pre_blur_push_constants.to_byte_array()) - - var view_count = render_scene_buffers.get_view_count() - for view in range(view_count): - var depth_image := render_scene_buffers.get_depth_layer(view) - var velocity_image := render_scene_buffers.get_velocity_layer(view) - var custom_velocity_image := render_scene_buffers.get_texture_slice(context, custom_velocity, view, 0, 1, 1) - var scene_data_buffer : RID = render_scene_data.get_uniform_buffer() - var scene_data_buffer_uniform := RDUniform.new() - scene_data_buffer_uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_UNIFORM_BUFFER - scene_data_buffer_uniform.binding = 5 - scene_data_buffer_uniform.add_id(scene_data_buffer) - - var tex_uniform_set - var compute_list - - var x_groups := floori((render_size.x - 1) / 16 + 1) - var y_groups := floori((render_size.y - 1) / 16 + 1) - - rd.draw_command_begin_label("Process Velocity Buffer " + str(view), Color(1.0, 1.0, 1.0, 1.0)) - - tex_uniform_set = UniformSetCacheRD.get_cache(pre_blur_processor_shader, 0, [ - get_sampler_uniform(depth_image, 0, false), - get_sampler_uniform(velocity_image, 1, false), - get_image_uniform(custom_velocity_image, 2), - scene_data_buffer_uniform, - ]) - - compute_list = rd.compute_list_begin() - rd.compute_list_bind_compute_pipeline(compute_list, pre_blur_processor_pipeline) - rd.compute_list_bind_uniform_set(compute_list, tex_uniform_set, 0) - rd.compute_list_set_push_constant(compute_list, byte_array, byte_array.size()) - rd.compute_list_dispatch(compute_list, x_groups, y_groups, 1) - rd.compute_list_end() - rd.draw_command_end_label() - rd.draw_command_end_label() - - -func ensure_texture(texture_name : StringName, render_scene_buffers : RenderSceneBuffersRD, high_accuracy : bool = false, render_size_multiplier : Vector2 = Vector2(1, 1)): - var render_size : Vector2 = Vector2(render_scene_buffers.get_internal_size()) * render_size_multiplier - - if render_scene_buffers.has_texture(context, texture_name): - var tf: RDTextureFormat = render_scene_buffers.get_texture_format(context, texture_name) - if tf.width != render_size.x or tf.height != render_size.y: - render_scene_buffers.clear_context(context) - - if !render_scene_buffers.has_texture(context, texture_name): - var usage_bits: int = RenderingDevice.TEXTURE_USAGE_SAMPLING_BIT | RenderingDevice.TEXTURE_USAGE_STORAGE_BIT - var texture_format = RenderingDevice.DATA_FORMAT_R32G32B32A32_SFLOAT if high_accuracy else RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT - render_scene_buffers.create_texture(context, texture_name, texture_format, usage_bits, RenderingDevice.TEXTURE_SAMPLES_1, render_size, 1, 1, true) diff --git a/addons/PreBlurProcessing/pre_blur_processor.glsl.import b/addons/PreBlurProcessing/pre_blur_processor.glsl.import deleted file mode 100644 index f0622a6..0000000 --- a/addons/PreBlurProcessing/pre_blur_processor.glsl.import +++ /dev/null @@ -1,14 +0,0 @@ -[remap] - -importer="glsl" -type="RDShaderFile" -uid="uid://ccg27o4i1gfty" -path="res://.godot/imported/pre_blur_processor.glsl-15aad2fcd84f6b03da65e9fe7bb8e345.res" - -[deps] - -source_file="res://PreBlurProcessing/pre_blur_processor.glsl" -dest_files=["res://.godot/imported/pre_blur_processor.glsl-15aad2fcd84f6b03da65e9fe7bb8e345.res"] - -[params] - diff --git a/addons/SphynxMotionBlurToolkit/BaseClasses/enhanced_compositor_effect.gd b/addons/SphynxMotionBlurToolkit/BaseClasses/enhanced_compositor_effect.gd new file mode 100644 index 0000000..07d925d --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/BaseClasses/enhanced_compositor_effect.gd @@ -0,0 +1,144 @@ +extends CompositorEffect +class_name EnhancedCompositorEffect + +var rd: RenderingDevice + +var linear_sampler: RID + +var nearest_sampler : RID + +var context: StringName = "PostProcess" + +var all_shader_stages : Dictionary + +func _init(): + RenderingServer.call_on_render_thread(_initialize_compute) + +func _notification(what): + if what == NOTIFICATION_PREDELETE: + if !rd: + return + if linear_sampler.is_valid(): + rd.free_rid(linear_sampler) + if nearest_sampler.is_valid(): + rd.free_rid(nearest_sampler) + 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 subscirbe_shader_stage(shader_stage : ShaderStageResource): + if all_shader_stages.has(shader_stage): + return + + all_shader_stages[shader_stage] = 1 + + if rd: + generate_shader_stage(shader_stage) + +func unsubscribe_shader_stage(shader_stage : ShaderStageResource): + if all_shader_stages.has(shader_stage): + all_shader_stages.erase(shader_stage) + if !rd: + return + + if shader_stage.shader.is_valid(): + rd.free_rid(shader_stage.shader) + if shader_stage.pipeline.is_valid(): + rd.free_rid(shader_stage.pipeline) + +func _initialize_compute(): + rd = RenderingServer.get_rendering_device() + + if !rd: + return + + var sampler_state := RDSamplerState.new() + + sampler_state.min_filter = RenderingDevice.SAMPLER_FILTER_LINEAR + sampler_state.mag_filter = RenderingDevice.SAMPLER_FILTER_LINEAR + sampler_state.repeat_u = RenderingDevice.SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE + sampler_state.repeat_v = RenderingDevice.SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE + + linear_sampler = rd.sampler_create(sampler_state) + + sampler_state.min_filter = RenderingDevice.SAMPLER_FILTER_NEAREST + sampler_state.mag_filter = RenderingDevice.SAMPLER_FILTER_NEAREST + sampler_state.repeat_u = RenderingDevice.SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE + sampler_state.repeat_v = RenderingDevice.SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE + + nearest_sampler = rd.sampler_create(sampler_state) + + for shader_stage in all_shader_stages.keys(): + generate_shader_stage(shader_stage) + +func generate_shader_stage(shader_stage : ShaderStageResource): + var shader_spirv : RDShaderSPIRV = 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) + +func _render_callback(p_effect_callback_type, p_render_data): + if !rd: + return + + var render_scene_buffers: RenderSceneBuffersRD = p_render_data.get_render_scene_buffers() + var render_scene_data: RenderSceneDataRD = p_render_data.get_render_scene_data() + if !render_scene_buffers or !render_scene_data: + return + + var render_size: Vector2i = render_scene_buffers.get_internal_size() + + if render_size.x == 0 or render_size.y == 0: + return + + + _render_callback_2(render_size, render_scene_buffers, render_scene_data) + +func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSceneBuffersRD, render_scene_data : RenderSceneDataRD): + pass + +func ensure_texture(texture_name : StringName, render_scene_buffers : RenderSceneBuffersRD, texture_format : RenderingDevice.DataFormat = RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, render_size_multiplier : Vector2 = Vector2(1, 1)): + var render_size : Vector2i = Vector2(render_scene_buffers.get_internal_size()) * render_size_multiplier + + if render_scene_buffers.has_texture(context, texture_name): + var tf: RDTextureFormat = render_scene_buffers.get_texture_format(context, texture_name) + if tf.width != render_size.x or tf.height != render_size.y: + render_scene_buffers.clear_context(context) + + if !render_scene_buffers.has_texture(context, texture_name): + var usage_bits: int = RenderingDevice.TEXTURE_USAGE_SAMPLING_BIT | RenderingDevice.TEXTURE_USAGE_STORAGE_BIT + render_scene_buffers.create_texture(context, texture_name, texture_format, usage_bits, RenderingDevice.TEXTURE_SAMPLES_1, render_size, 1, 1, true) + +func get_image_uniform(image: RID, binding: int) -> RDUniform: + var uniform: RDUniform = RDUniform.new() + uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_IMAGE + uniform.binding = binding + uniform.add_id(image) + return uniform + +func get_sampler_uniform(image: RID, binding: int, linear : bool = true) -> RDUniform: + var uniform: RDUniform = RDUniform.new() + uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_SAMPLER_WITH_TEXTURE + uniform.binding = binding + uniform.add_id(linear_sampler if linear else nearest_sampler) + uniform.add_id(image) + return uniform + +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) + + var tex_uniform_set = UniformSetCacheRD.get_cache(stage.shader, 0, uniforms) + + var compute_list = rd.compute_list_begin() + rd.compute_list_bind_compute_pipeline(compute_list, stage.pipeline) + rd.compute_list_bind_uniform_set(compute_list, tex_uniform_set, 0) + + if !push_constants.is_empty(): + rd.compute_list_set_push_constant(compute_list, push_constants, push_constants.size()) + + rd.compute_list_dispatch(compute_list, dispatch_size.x, dispatch_size.y, dispatch_size.z) + + rd.compute_list_end() + + rd.draw_command_end_label() diff --git a/addons/SphynxMotionBlurToolkit/BaseClasses/mb_compositor_effect.gd b/addons/SphynxMotionBlurToolkit/BaseClasses/mb_compositor_effect.gd new file mode 100644 index 0000000..f7b9175 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/BaseClasses/mb_compositor_effect.gd @@ -0,0 +1,9 @@ +extends EnhancedCompositorEffect +class_name MotionBlurCompositorEffect + +func _init(): + set_deferred("context", "MotionBlur") + super() + +func _get_max_dilation_range() -> float: + return 0 diff --git a/addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd b/addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd new file mode 100644 index 0000000..7d86dfe --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd @@ -0,0 +1,7 @@ +extends Resource +class_name ShaderStageResource + +@export var shader_file : RDShaderFile + +var shader : RID +var pipeline : RID diff --git a/addons/SphynxMotionBlurToolkit/Debug/ShaderFiles/debug_overlay.glsl b/addons/SphynxMotionBlurToolkit/Debug/ShaderFiles/debug_overlay.glsl new file mode 100644 index 0000000..958ce73 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Debug/ShaderFiles/debug_overlay.glsl @@ -0,0 +1,93 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 +#define DBL_MAX 1.7976931348623158e+308 +#define DBL_MIN 2.2250738585072014e-308 + +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 +{ + float nan_fl_1; + float nan_fl_2; + float nan_fl_3; + float nan_fl_4; + int freeze; + int draw_debug; + int debug_page; + int nan3; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + + +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; + } + // show past image for freeze frame + if(params.freeze > 0) + { + imageStore(output_color_image, uvi, imageLoad(past_color_image, uvi)); + return; + } + // must be on pixel center for whole values (tested) + vec2 uvn = vec2(uvi + vec2(0.5)) / render_size; + + vec4 source = textureLod(color_sampler, uvn, 0.0); + + if (params.draw_debug == 0) + { + imageStore(output_color_image, uvi, source); + imageStore(past_color_image, uvi, source); + return; + } + + vec4 tl_col; + + vec4 tr_col; + + vec4 bl_col; + + vec4 br_col; + + 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); + } + 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); + } + + 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); + imageStore(output_color_image, uvi / 2 + ivec2(vec2(0.5, 0.0) * render_size), tr_col); + imageStore(past_color_image, uvi / 2, tl_col); + imageStore(past_color_image, uvi / 2 + ivec2(vec2(0.5, 0.5) * render_size), br_col); + imageStore(past_color_image, uvi / 2 + ivec2(vec2(0.0, 0.5) * render_size), bl_col); + imageStore(past_color_image, uvi / 2 + ivec2(vec2(0.5, 0.0) * render_size), tr_col); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/Debug/ShaderFiles/debug_overlay.glsl.import b/addons/SphynxMotionBlurToolkit/Debug/ShaderFiles/debug_overlay.glsl.import new file mode 100644 index 0000000..af416c2 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Debug/ShaderFiles/debug_overlay.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://dyxn6g5gvoge7" +path="res://.godot/imported/debug_overlay.glsl-5ad15477a64c7f484bc494103ad163b6.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/Debug/ShaderFiles/debug_overlay.glsl" +dest_files=["res://.godot/imported/debug_overlay.glsl-5ad15477a64c7f484bc494103ad163b6.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/Debug/debug_overlay_shader_stage.tres b/addons/SphynxMotionBlurToolkit/Debug/debug_overlay_shader_stage.tres new file mode 100644 index 0000000..58735f3 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Debug/debug_overlay_shader_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://o2bivm33b0v4"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_rqnmr"] +[ext_resource type="RDShaderFile" uid="uid://dyxn6g5gvoge7" path="res://addons/SphynxMotionBlurToolkit/Debug/ShaderFiles/debug_overlay.glsl" id="2_qgd1y"] + +[resource] +script = ExtResource("1_rqnmr") +shader_file = ExtResource("2_qgd1y") diff --git a/addons/SphynxMotionBlurToolkit/Debug/post_process_debug.gd b/addons/SphynxMotionBlurToolkit/Debug/post_process_debug.gd new file mode 100644 index 0000000..7aefdd9 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Debug/post_process_debug.gd @@ -0,0 +1,107 @@ +extends EnhancedCompositorEffect +class_name DebugCompositorEffect + +@export var overlay_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/Debug/debug_overlay_shader_stage.tres"): + set(value): + unsubscribe_shader_stage(overlay_stage) + overlay_stage = value + subscirbe_shader_stage(value) + +## wether to display debug views for velocity and depth +## buffers +@export var draw_debug : bool = false + +## currently 0 - 1, flip between velocity buffers +## 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") + super() + +func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSceneBuffersRD, render_scene_data : RenderSceneDataRD): + ensure_texture(past_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("Debug", Color(1.0, 1.0, 1.0, 1.0)) + + if Input.is_action_just_pressed("freeze"): + freeze = !freeze + + if Input.is_action_just_pressed("Z"): + draw_debug = !draw_debug + + if Input.is_action_just_pressed("C"): + debug_page = 1 if debug_page == 0 else 0 + + var push_constant: PackedFloat32Array = [ + 0, + 0, + 0, + 0, + ] + var int_push_constant : PackedInt32Array = [ + freeze, + draw_debug, + debug_page, + 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 past_color_image := render_scene_buffers.get_texture_slice(context, past_color, 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 - 1) / 16 + 1) + var y_groups := floori((render_size.y - 1) / 16 + 1) + + dispatch_stage(overlay_stage, + [ + get_image_uniform(past_color_image, 0), + get_image_uniform(color_image, 1), + get_sampler_uniform(color_image, 2), + get_sampler_uniform(debug_1_image, 3), + get_sampler_uniform(debug_2_image, 4), + get_sampler_uniform(debug_3_image, 5), + get_sampler_uniform(debug_4_image, 6), + get_sampler_uniform(debug_5_image, 7), + get_sampler_uniform(debug_6_image, 8), + get_sampler_uniform(debug_7_image, 9), + get_sampler_uniform(debug_8_image, 10), + ], + byte_array, + Vector3i(x_groups, y_groups, 1), + "Debug Overlay", + view) + + rd.draw_command_end_label() diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_blur.glsl b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_blur.glsl new file mode 100644 index 0000000..9efecd9 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_blur.glsl @@ -0,0 +1,156 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 + +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 debug_1_image; +layout(rgba16f, set = 0, binding = 7) uniform image2D debug_2_image; + +layout(push_constant, std430) uniform Params +{ + float minimum_user_threshold; + float importance_bias; + float maximum_jitter_value; + float nan8; + int tile_size; + int sample_count; + int frame; + int nan4; +} 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 - abs(T) / v, 0, 1); +} + +float cylinder(float T, float v) +{ + return 1.0 - smoothstep(0.95 * v, 1.05 * v, abs(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) +{ + return clamp(1. - (a - b) / min(a, b), 0, 1); +} +// ---------------------------------------------------------- + +// 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))); +} +// ---------------------------------------------------------- + +vec2 sample_random_offset(vec2 uv, float j) +{ + return vec2(0); +} + +void main() +{ + ivec2 render_size = ivec2(textureSize(color_sampler, 0)); + ivec2 tile_render_size = ivec2(textureSize(neighbor_max, 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); + + float j = interleaved_gradient_noise(uvi, params.frame) * 2. - 1.; + + vec2 vn = textureLod(neighbor_max, x, 0.0).xy * render_size / 2; + + float vn_length = max(0.5, length(vn)); + + vec4 base_color = textureLod(color_sampler, x, 0.0); + + if(vn_length <= 0.5) + { + imageStore(output_color, uvi, base_color); + imageStore(debug_1_image, uvi, base_color); + imageStore(debug_2_image, uvi, vec4(vn / render_size * 2, 0, 1)); + return; + } + + vec2 wn = normalize(vn); + + vec2 vx = textureLod(velocity_sampler, x, 0.0).xy * render_size / 2; + + float vx_length = max(0.5, length(vx)); + + vec2 wp = vec2(-wn.y, wn.x); + + if(dot(wp, vx) < 0) + { + wp = -wp; + } + + vec2 wc = normalize(mix(wp, normalize(vx), (vx_length - 0.5) / params.minimum_user_threshold)); + + float zx = -0.05 / textureLod(depth_sampler, x, 0.0).x; + + float weight = params.sample_count / (params.importance_bias * vx_length); + + vec4 sum = base_color * weight; + + for(int i = 0; i < params.sample_count; i++) + { + float t = mix(-1.0, 1.0, (i + j * params.maximum_jitter_value + 1.0) / (params.sample_count + 1.0)); + + vec2 d = ((i % 2) > 0) ? vx : vn; + + float T = t * vn_length; + + vec2 y = x + t * d / render_size; + + vec2 vy = textureLod(velocity_sampler, y, 0.0).xy * render_size / 2; + + float vy_length = max(0.5, length(vy)); + + float zy = -0.05 / textureLod(depth_sampler, y, 0.0).x; + + float f = z_compare(zx, zy); + float b = z_compare(zy, zx); + + float wa = dot(wc, d); + float wb = dot(normalize(vy), d); + + float ay = f * cone(T, 1. / vy_length) * max(FLT_MIN, abs(wb)) + + b * cone(T, 1. / vx_length) * max(FLT_MIN, abs(wa)) + + cylinder(T, min(vx_length, vy_length)) * 2 * max(FLT_MIN, max(abs(wa), abs(wb))); + + weight += abs(ay); + sum += ay * textureLod(color_sampler, y, 0.0); + } + + sum /= weight; + + imageStore(output_color, uvi, sum); + imageStore(debug_1_image, uvi, sum); + imageStore(debug_2_image, uvi, vec4(vn / render_size * 2, 0, 1)); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_blur.glsl.import b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_blur.glsl.import new file mode 100644 index 0000000..2b497ce --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_blur.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://cbdyfuhewqag8" +path="res://.godot/imported/guertin_blur.glsl-bc647b2d965e982b702f0e036903e801.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_blur.glsl" +dest_files=["res://.godot/imported/guertin_blur.glsl-bc647b2d965e982b702f0e036903e801.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_kino_blur.glsl b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_kino_blur.glsl new file mode 100644 index 0000000..2b877e3 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_kino_blur.glsl @@ -0,0 +1,184 @@ +#[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 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(push_constant, std430) uniform Params +{ + float minimum_user_threshold; + float importance_bias; + float maximum_jitter_value; + float nan8; + int tile_size; + int sample_count; + int frame; + int nan4; +} 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) / min(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(1 >= 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(neighbor_max, 0) / 4; +} +// ---------------------------------------------------------- + +void main() +{ + ivec2 render_size = ivec2(textureSize(color_sampler, 0)); + ivec2 tile_render_size = ivec2(textureSize(neighbor_max, 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); + + float j = interleaved_gradient_noise(uvi) * 2. - 1.; + + vec2 vn = textureLod(neighbor_max, x + jitter_tile(uvi), 0.0).xy * render_size / 2.; + + float vn_length = length(vn); + + vec4 base_color = textureLod(color_sampler, x, 0.0); + + if(vn_length < 0.5) + { + imageStore(output_color, uvi, base_color); + 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)); + return; + } + + vec2 wn = safenorm(vn); + + vec2 vx = textureLod(velocity_sampler, x, 0.0).xy * render_size / 2.; + + float vx_length = max(0.5, length(vx)); + + vec2 wx = safenorm(vx); + + vec2 wp = vec2(-wn.y, wn.x); + + if(dot(wp, vx) < 0) + { + wp = -wp; + } + + 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 total_weight = params.sample_count / (params.importance_bias * vx_length); + + vec4 sum = base_color * total_weight; + + for(int i = 0; i < params.sample_count; i++) + { + float t = mix(-1.0, 1.0, (i + j * params.maximum_jitter_value + 1.0) / (params.sample_count + 1.0)); + + vec2 d = ((i % 2) > 0) ? vx : vn; + + vec2 wd = safenorm(d); + + float T = abs(t * vn_length); + + vec2 y = x + t * d / render_size; + + float wa = dot(wc, wd); + + vec2 vy = textureLod(velocity_sampler, y, 0.0).xy * render_size / 2; + + float vy_length = max(0.5, length(vy)); + + float zy = -0.05 / max(FLT_MIN, textureLod(depth_sampler, y, 0.0).x); + + float f = z_compare(zy, zx, 15); + float b = z_compare(zx, zy, 15); + + float wb = abs(dot(vy / vy_length, wd)); + + float weight = 0.0; + weight += f * cone(T, vy_length) * wb; + weight += b * cone(T, vx_length) * wa; + weight += cylinder(T, min(vy_length, vx_length)) * 2. * max(wa, wb); + + total_weight += weight; + + sum += weight * textureLod(color_sampler, y, 0.0); + } + + sum /= total_weight; + + imageStore(output_color, uvi, sum); + 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)); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_kino_blur.glsl.import b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_kino_blur.glsl.import new file mode 100644 index 0000000..a13c0d0 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_kino_blur.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://m6rlgfu6i0b3" +path="res://.godot/imported/guertin_kino_blur.glsl-71e9932045a7522115793d60f179d67e.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_kino_blur.glsl" +dest_files=["res://.godot/imported/guertin_kino_blur.glsl-71e9932045a7522115793d60f179d67e.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_neighbor_max.glsl b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_neighbor_max.glsl new file mode 100644 index 0000000..ccd3b7f --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_neighbor_max.glsl @@ -0,0 +1,72 @@ +#[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(rgba16f, set = 0, binding = 1) 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_velocity_length = 0; + + 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; + } + + bool is_diagonal = (abs(i) + abs(j) == 2); + + vec2 current_neighbor_velocity = textureLod(tile_max, current_uv, 0.0).xy; + + bool facing_center = dot(current_neighbor_velocity, current_offset) > 0; + + if(is_diagonal && !facing_center) + { + continue; + } + + float current_neighbor_velocity_length = dot(current_neighbor_velocity, current_neighbor_velocity); + if(current_neighbor_velocity_length > max_neighbor_velocity_length) + { + max_neighbor_velocity_length = current_neighbor_velocity_length; + max_neighbor_velocity = current_neighbor_velocity; + } + } + } + + imageStore(neighbor_max, uvi, vec4(max_neighbor_velocity, 0, 1)); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_neighbor_max.glsl.import b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_neighbor_max.glsl.import new file mode 100644 index 0000000..edb48e0 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_neighbor_max.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://bn88jkvr17x4j" +path="res://.godot/imported/guertin_neighbor_max.glsl-91e836516679e0c51b67df5b480ef0af.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_neighbor_max.glsl" +dest_files=["res://.godot/imported/guertin_neighbor_max.glsl-91e836516679e0c51b67df5b480ef0af.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_overlay.glsl b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_overlay.glsl new file mode 100644 index 0000000..c85ac5b --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_overlay.glsl @@ -0,0 +1,18 @@ +#[compute] +#version 450 + +layout(set = 0, binding = 0) uniform sampler2D blur_sampler; +layout(rgba16f, set = 0, binding = 1) uniform image2D color_image; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; +void main() +{ + ivec2 render_size = ivec2(textureSize(blur_sampler, 0)); + ivec2 output_size = imageSize(color_image); + ivec2 uv = ivec2(gl_GlobalInvocationID.xy); + if ((uv.x >= output_size.x) || (uv.y >= output_size.y)) + { + return; + } + imageStore(color_image, uv, textureLod(blur_sampler, (vec2(uv) + 0.5) / output_size, 0.0)); +} diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_overlay.glsl.import b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_overlay.glsl.import new file mode 100644 index 0000000..5b57c2b --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_overlay.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://i6rnwhmss334" +path="res://.godot/imported/guertin_overlay.glsl-506c18362b63cb0a2477b4a4fbfea046.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_overlay.glsl" +dest_files=["res://.godot/imported/guertin_overlay.glsl-506c18362b63cb0a2477b4a4fbfea046.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_x.glsl b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_x.glsl new file mode 100644 index 0000000..007548d --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_x.glsl @@ -0,0 +1,55 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#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(push_constant, std430) uniform Params +{ + float nan5; + float nan6; + float nan7; + float nan8; + int tile_size; + 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(velocity_sampler, 0)); + ivec2 output_size = imageSize(tile_max_x); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + ivec2 global_uvi = uvi * ivec2(params.tile_size, 1); + if ((uvi.x >= output_size.x) || (uvi.y >= output_size.y) || (global_uvi.x >= render_size.x) || (global_uvi.y >= render_size.y)) + { + return; + } + + vec2 uvn = (vec2(global_uvi) + vec2(0.5)) / render_size; + + vec4 max_velocity = vec4(0); + + float max_velocity_length = -1; + + for(int i = 0; i < params.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; + float current_velocity_length = dot(velocity_sample.xy, velocity_sample.xy); + if(current_velocity_length > max_velocity_length) + { + max_velocity_length = current_velocity_length; + max_velocity = vec4(velocity_sample, textureLod(depth_sampler, current_uv, 0.0).x); + } + } + imageStore(tile_max_x, uvi, max_velocity); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_x.glsl.import b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_x.glsl.import new file mode 100644 index 0000000..19144a3 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_x.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://d0s5upcgm7r6l" +path="res://.godot/imported/guertin_tile_max_x.glsl-7ca561425618287b0f2821fd8c232f09.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_x.glsl" +dest_files=["res://.godot/imported/guertin_tile_max_x.glsl-7ca561425618287b0f2821fd8c232f09.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_y.glsl b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_y.glsl new file mode 100644 index 0000000..1fc1328 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_y.glsl @@ -0,0 +1,54 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 + +layout(set = 0, binding = 0) uniform sampler2D tile_max_x; +layout(rgba16f, set = 0, binding = 1) uniform writeonly image2D tile_max; + +layout(push_constant, std430) uniform Params +{ + float nan5; + float nan6; + float nan7; + float nan8; + int tile_size; + 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_x, 0)); + ivec2 output_size = imageSize(tile_max); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + ivec2 global_uvi = uvi * ivec2(1, params.tile_size); + if ((uvi.x >= output_size.x) || (uvi.y >= output_size.y) || (global_uvi.x >= render_size.x) || (global_uvi.y >= render_size.y)) + { + return; + } + + vec2 uvn = (vec2(global_uvi) + vec2(0.5)) / render_size; + + vec4 max_velocity = vec4(0); + + float max_velocity_length = -1; + + for(int i = 0; i < params.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) + { + max_velocity_length = current_velocity_length; + max_velocity = velocity_sample; + } + } + imageStore(tile_max, uvi, max_velocity); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_y.glsl.import b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_y.glsl.import new file mode 100644 index 0000000..e241248 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_y.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://ceetvitdbio4l" +path="res://.godot/imported/guertin_tile_max_y.glsl-60f045725ff6917c4bd911cf3710a444.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_y.glsl" +dest_files=["res://.godot/imported/guertin_tile_max_y.glsl-60f045725ff6917c4bd911cf3710a444.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_variance.glsl b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_variance.glsl new file mode 100644 index 0000000..24ec95c --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_variance.glsl @@ -0,0 +1,68 @@ +#[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(rgba16f, set = 0, binding = 1) uniform writeonly image2D tile_variance; + +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; + + float variance = 0; + + vec2 current_velocity = abs(normalize(textureLod(tile_max, uvn, 0.0).xy)); + + float tile_count = 0; + + 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; + } + if(i == j && i == 0) + { + continue; + } + + tile_count += 1; + + vec2 current_neighbor_velocity = abs(normalize(textureLod(tile_max, current_uv, 0.0).xy)); + + variance += dot(current_velocity, current_neighbor_velocity); + } + } + + variance /= tile_count; + + imageStore(tile_variance, uvi, vec4(1 - variance)); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_variance.glsl.import b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_variance.glsl.import new file mode 100644 index 0000000..61e2a82 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_variance.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://by6mslkv0palh" +path="res://.godot/imported/guertin_tile_variance.glsl-2fb44423dc25efae19822b8cfbe32a55.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_variance.glsl" +dest_files=["res://.godot/imported/guertin_tile_variance.glsl-2fb44423dc25efae19822b8cfbe32a55.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/Guertin/guertin_blur_stage.tres b/addons/SphynxMotionBlurToolkit/Guertin/guertin_blur_stage.tres new file mode 100644 index 0000000..32072c4 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/guertin_blur_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://dre56ajymywpr"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_loemu"] +[ext_resource type="RDShaderFile" uid="uid://m6rlgfu6i0b3" path="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_kino_blur.glsl" id="2_uo41r"] + +[resource] +script = ExtResource("1_loemu") +shader_file = ExtResource("2_uo41r") diff --git a/addons/SphynxMotionBlurToolkit/Guertin/guertin_motion_blur.gd b/addons/SphynxMotionBlurToolkit/Guertin/guertin_motion_blur.gd new file mode 100644 index 0000000..a4e879d --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/guertin_motion_blur.gd @@ -0,0 +1,262 @@ +extends MotionBlurCompositorEffect +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 var blur_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/Guertin/guertin_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/Guertin/guertin_overlay_stage.tres"): + set(value): + unsubscribe_shader_stage(overlay_stage) + overlay_stage = value + subscirbe_shader_stage(value) + +@export var tile_max_x_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/Guertin/guertin_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/Guertin/guertin_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 neighbor_max_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/Guertin/guertin_neighbor_max_stage.tres"): + set(value): + unsubscribe_shader_stage(neighbor_max_stage) + neighbor_max_stage = value + subscirbe_shader_stage(value) + +@export var tile_variance_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_variance_stage.tres"): + set(value): + unsubscribe_shader_stage(tile_variance_stage) + 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" + +var tile_max : StringName = "tile_max" + +var neighbor_max : StringName = "neighbor_max" + +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: + return tile_size; + +func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSceneBuffersRD, render_scene_data : RenderSceneDataRD): + ensure_texture(tile_max_x, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / tile_size, 1.)) + ensure_texture(tile_max, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / tile_size, 1. / tile_size)) + ensure_texture(neighbor_max, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / tile_size, 1. / tile_size)) + 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)) + + var tile_max_x_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_tile_max_x_push_constants : PackedInt32Array = [ + tile_size, + 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 = [ + tile_size, + 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 tile_variance_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_tile_variance_push_constants : PackedInt32Array = [ + 0, + 0, + 0, + 0 + ] + var tile_variance_push_constants_byte_array = tile_variance_push_constants.to_byte_array() + 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, + ] + var int_blur_push_constants : PackedInt32Array = [ + tile_size, + motion_blur_samples, + Engine.get_frames_drawn() % 8, + 0 + ] + var blur_push_constants_byte_array = blur_push_constants.to_byte_array() + blur_push_constants_byte_array.append_array(int_blur_push_constants.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 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 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) + + 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 / tile_size - 1) / 16 + 1) + y_groups = floori((render_size.y / tile_size - 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) + + dispatch_stage(neighbor_max_stage, + [ + get_sampler_uniform(tile_max_image, 0, false), + get_image_uniform(neighbor_max_image, 1) + ], + neighbor_max_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "NeighborMax", + view) + + dispatch_stage(tile_variance_stage, + [ + get_sampler_uniform(tile_max_image, 0, false), + get_image_uniform(tile_variance_image, 1) + ], + tile_variance_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "TileVariance", + 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_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) + ], + blur_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "Blur", + view) + + dispatch_stage(overlay_stage, + [ + get_sampler_uniform(output_color_image, 0, false), + 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/Guertin/guertin_neighbor_max_stage.tres b/addons/SphynxMotionBlurToolkit/Guertin/guertin_neighbor_max_stage.tres new file mode 100644 index 0000000..a742592 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/guertin_neighbor_max_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://cvb65hfs2lrxo"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_i1bu0"] +[ext_resource type="RDShaderFile" uid="uid://bn88jkvr17x4j" path="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_neighbor_max.glsl" id="2_jp4do"] + +[resource] +script = ExtResource("1_i1bu0") +shader_file = ExtResource("2_jp4do") diff --git a/addons/SphynxMotionBlurToolkit/Guertin/guertin_overlay_stage.tres b/addons/SphynxMotionBlurToolkit/Guertin/guertin_overlay_stage.tres new file mode 100644 index 0000000..fed9f06 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/guertin_overlay_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://bidsfymvdyhek"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_2uett"] +[ext_resource type="RDShaderFile" uid="uid://i6rnwhmss334" path="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_overlay.glsl" id="2_evkw4"] + +[resource] +script = ExtResource("1_2uett") +shader_file = ExtResource("2_evkw4") diff --git a/addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_max_x_stage.tres b/addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_max_x_stage.tres new file mode 100644 index 0000000..53cffa5 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_max_x_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://dipvwksvqb3dm"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_bxcqf"] +[ext_resource type="RDShaderFile" uid="uid://d0s5upcgm7r6l" path="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_x.glsl" id="2_q6kae"] + +[resource] +script = ExtResource("1_bxcqf") +shader_file = ExtResource("2_q6kae") diff --git a/addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_max_y_stage.tres b/addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_max_y_stage.tres new file mode 100644 index 0000000..6dde404 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_max_y_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://bxfg45ubc2pv7"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_gy5dj"] +[ext_resource type="RDShaderFile" uid="uid://ceetvitdbio4l" path="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_y.glsl" id="2_grpec"] + +[resource] +script = ExtResource("1_gy5dj") +shader_file = ExtResource("2_grpec") diff --git a/addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_variance_stage.tres b/addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_variance_stage.tres new file mode 100644 index 0000000..1565004 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_variance_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://bqehecsdgt70s"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_kkpwt"] +[ext_resource type="RDShaderFile" uid="uid://by6mslkv0palh" path="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_variance.glsl" id="2_r5u5d"] + +[resource] +script = ExtResource("1_kkpwt") +shader_file = ExtResource("2_r5u5d") diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_x.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_x.glsl new file mode 100644 index 0000000..84b1645 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_x.glsl @@ -0,0 +1,56 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#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(push_constant, std430) uniform Params +{ + float nan5; + float nan6; + float nan7; + float nan8; + int tile_size; + 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(velocity_sampler, 0)); + ivec2 output_size = imageSize(tile_max_x); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + int tile_size = render_size.x / output_size.x; + ivec2 global_uvi = uvi * ivec2(tile_size, 1); + if ((uvi.x >= output_size.x) || (uvi.y >= output_size.y) || (global_uvi.x >= render_size.x) || (global_uvi.y >= render_size.y)) + { + return; + } + + vec2 uvn = (vec2(global_uvi) + vec2(0.5)) / render_size; + + vec4 max_velocity = vec4(0); + + float max_velocity_length = -1; + + 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; + float current_velocity_length = dot(velocity_sample.xy, velocity_sample.xy); + if(current_velocity_length > max_velocity_length) + { + max_velocity_length = current_velocity_length; + max_velocity = vec4(velocity_sample, textureLod(depth_sampler, current_uv, 0.0).x); + } + } + imageStore(tile_max_x, uvi, max_velocity); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_x.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_x.glsl.import new file mode 100644 index 0000000..6b1a9ee --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_x.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://djp3da364fk2l" +path="res://.godot/imported/jf_guertin_tile_max_x.glsl-acb187dfb7304d498ecdfb75a54c725d.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_x.glsl" +dest_files=["res://.godot/imported/jf_guertin_tile_max_x.glsl-acb187dfb7304d498ecdfb75a54c725d.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_y.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_y.glsl new file mode 100644 index 0000000..2ea1f74 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_y.glsl @@ -0,0 +1,55 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 + +layout(set = 0, binding = 0) uniform sampler2D tile_max_x; +layout(rgba16f, set = 0, binding = 1) uniform writeonly image2D tile_max; + +layout(push_constant, std430) uniform Params +{ + float nan5; + float nan6; + float nan7; + float nan8; + int tile_size; + 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_x, 0)); + ivec2 output_size = imageSize(tile_max); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + int tile_size = render_size.y / output_size.y; + ivec2 global_uvi = uvi * ivec2(1, tile_size); + if ((uvi.x >= output_size.x) || (uvi.y >= output_size.y) || (global_uvi.x >= render_size.x) || (global_uvi.y >= render_size.y)) + { + return; + } + + vec2 uvn = (vec2(global_uvi) + vec2(0.5)) / render_size; + + vec4 max_velocity = vec4(0); + + float max_velocity_length = -1; + + 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) + { + max_velocity_length = current_velocity_length; + max_velocity = velocity_sample; + } + } + imageStore(tile_max, uvi, max_velocity); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_y.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_y.glsl.import new file mode 100644 index 0000000..c729a25 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_y.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://cqlltc8f21wre" +path="res://.godot/imported/jf_guertin_tile_max_y.glsl-8b893536de27f9161f4a8be7b8c5058f.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_y.glsl" +dest_files=["res://.godot/imported/jf_guertin_tile_max_y.glsl-8b893536de27f9161f4a8be7b8c5058f.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_neighbor_max.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_neighbor_max.glsl new file mode 100644 index 0000000..5f20780 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_neighbor_max.glsl @@ -0,0 +1,68 @@ +#[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_velocity_length = -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; + } + + bool is_diagonal = (abs(i) + abs(j) == 2); + + vec2 current_neighbor_sample = textureLod(tile_max_map, current_uv, 0.0).xy; + + 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) + { + max_neighbor_velocity_length = current_neighbor_velocity_length; + max_neighbor_velocity = current_neighbor_sample; + } + } + } + + 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_max.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_neighbor_max.glsl.import new file mode 100644 index 0000000..5debb67 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_neighbor_max.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://cfk5chwlcyay4" +path="res://.godot/imported/jf_neighbor_max.glsl-d9e677fd383d0688a8ad642473870160.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_neighbor_max.glsl" +dest_files=["res://.godot/imported/jf_neighbor_max.glsl-d9e677fd383d0688a8ad642473870160.res"] + +[params] + diff --git a/addons/MyJumpFloodIteration/jfp_backtracking_experimental.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_backtracking_experimental.glsl similarity index 66% rename from addons/MyJumpFloodIteration/jfp_backtracking_experimental.glsl rename to addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_backtracking_experimental.glsl index f695908..43ee73c 100644 --- a/addons/MyJumpFloodIteration/jfp_backtracking_experimental.glsl +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_backtracking_experimental.glsl @@ -6,8 +6,8 @@ layout(set = 0, binding = 0) uniform sampler2D depth_sampler; layout(set = 0, binding = 1) uniform sampler2D velocity_sampler; -layout(rg16f, set = 0, binding = 2) uniform writeonly image2D buffer_a; -layout(rg16f, set = 0, binding = 3) uniform writeonly image2D buffer_b; +layout(rgba16f, set = 0, binding = 2) uniform writeonly image2D buffer_a; +layout(rgba16f, set = 0, binding = 3) uniform writeonly image2D buffer_b; layout(set = 0, binding = 4) uniform sampler2D buffer_a_sampler; layout(set = 0, binding = 5) uniform sampler2D buffer_b_sampler; @@ -46,59 +46,50 @@ const vec2 check_step_kernel[kernel_size] = { vec2(-1, -1), }; -vec4 get_value(bool a, vec2 uv, ivec2 render_size) +void get_value(bool a,inout vec2 uv) { - if (any(notEqual(uv, clamp(uv, vec2(0.0), vec2(1.0))))) - { - return vec4(-1, -1, 0, 1); - } - if(a) { - return textureLod(buffer_a_sampler, uv, 0.0); + uv = textureLod(buffer_a_sampler, uv, 0.0).xy; + } + else + { + uv = textureLod(buffer_b_sampler, uv, 0.0).xy; } - - return textureLod(buffer_b_sampler, uv, 0.0); } -void set_value(bool a, ivec2 uvi, vec4 value, ivec2 render_size) +void set_value(bool a, ivec2 uvi, vec4 value) { - if (any(notEqual(uvi, clamp(uvi, ivec2(0), render_size)))) - { - return; - } if(a) { imageStore(buffer_a, uvi, value); - return; } - - imageStore(buffer_b, uvi, value); + else + { + imageStore(buffer_b, uvi, value); + } } // Motion similarity // ---------------------------------------------------------- -float get_motion_difference(vec2 V, vec2 V2, float parallel_sensitivity, float perpendicular_sensitivity) +float get_motion_difference(vec2 V, vec2 V2) { - vec2 VO = V - V2; - // parallel offset - float parallel = abs(dot(VO, V) / max(FLT_MIN, dot(V, V))); - // perpendicular offset - float perpendicular = abs(dot(VO, vec2(V.y, -V.x)) / max(FLT_MIN, dot(V, V))); - // weighted difference - float difference = parallel * parallel_sensitivity + perpendicular * perpendicular_sensitivity; - return clamp(difference, 0, 1); + 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); } // ---------------------------------------------------------- -vec4 sample_fitness(vec2 uv_offset, vec4 uv_sample, vec2 render_size) +void sample_fitness(vec2 uv_offset, vec4 uv_sample, vec2 render_size, inout vec4 curren_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) { - return vec4(FLT_MAX, FLT_MAX, FLT_MAX, 0); + curren_sample_fitness = vec4(FLT_MAX, FLT_MAX, FLT_MAX, 0); + return; } // velocity space distance (projected pixel offset onto velocity vector) @@ -114,7 +105,7 @@ vec4 sample_fitness(vec2 uv_offset, vec4 uv_sample, vec2 render_size) // 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 - return vec4(absolute_velocity_space_distance, velocity_space_distance, uv_sample.w + uv_sample.z * velocity_space_distance, within_velocity_range * within_perpen_error_range); + curren_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); } float is_sample_better(vec4 a, vec4 b) @@ -139,52 +130,64 @@ vec4 get_backtracked_sample(vec2 uvn, vec2 chosen_uv, vec3 chosen_velocity, vec4 float best_depth = best_sample_fitness.z; // set temp variable to keet track of better matches - float smallest_velocity_difference = params.velocity_match_threshold; + float smallest_velocity_difference = 0.99;//params.velocity_match_threshold; // minimum amount of valid velocities to compare before decision int initial_steps_to_compare = 2; int steps_to_compare = initial_steps_to_compare; + float velocity_multiplier; + + vec2 check_uv; + + vec3 velocity_test; + + float depth_test; + + float velocity_difference; + + float current_depth; + for(int i = -params.backtracking_sample_count; i < params.backtracking_sample_count + 1; i++) { - float velocity_multiplier = general_velocity_multiplier * (1 + float(i) / float(params.backtracking_sample_count)); + velocity_multiplier = general_velocity_multiplier * (1 + float(i) / float(params.backtracking_sample_count)); if(velocity_multiplier > params.motion_blur_intensity || velocity_multiplier < 0) { continue; } - vec2 check_uv = uvn - chosen_velocity.xy * velocity_multiplier; + check_uv = uvn - chosen_velocity.xy * velocity_multiplier; if(any(notEqual(check_uv, clamp(check_uv, vec2(0.0), vec2(1.0))))) { continue; } // get potential velocity and depth matches - vec3 velocity_test = textureLod(velocity_sampler, check_uv, 0.0).xyz; + velocity_test = textureLod(velocity_sampler, check_uv, 0.0).xyz; - float depth_test = textureLod(depth_sampler, check_uv, 0.0).x; + depth_test = textureLod(depth_sampler, check_uv, 0.0).x; - float velocity_difference = get_motion_difference(chosen_velocity.xy, velocity_test.xy, params.parallel_sensitivity, params.perpendicular_sensitivity); + velocity_difference = get_motion_difference(chosen_velocity.xy, velocity_test.xy); - float current_depth = depth_test + chosen_velocity.z * velocity_multiplier; + current_depth = depth_test + chosen_velocity.z * velocity_multiplier; // if checked sample matches depth and velocity, it is valid for backtracking - if((abs(current_depth - best_sample_fitness.z) < params.depth_match_threshold) && (velocity_difference <= smallest_velocity_difference)) + if((abs(current_depth - best_sample_fitness.z) < 0.002) && (velocity_difference <= smallest_velocity_difference)) { best_uv = check_uv; best_multiplier = velocity_multiplier; best_depth = current_depth; if(steps_to_compare == 0) { - return vec4(best_uv, best_depth, best_multiplier); + return vec4(best_uv, best_depth, 0); } steps_to_compare--; } // if a sample was found and we lost footing after, go with that found sample right away else if(initial_steps_to_compare > steps_to_compare) { - return vec4(best_uv, best_depth, best_multiplier); + return vec4(best_uv, best_depth, 0); } } @@ -205,38 +208,44 @@ void main() 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(FLT_MAX, FLT_MAX, FLT_MAX, 0.); vec2 chosen_uv = uvn; - vec3 chosen_velocity = vec3(0); + vec3 chosen_velocity = vec3(0.); bool set_a = !bool(step(0.5, float(params.iteration_index % 2))); + vec2 step_offset; + + vec2 check_uv; + + vec4 uv_sample; + + vec4 current_sample_fitness; + for(int i = 0; i < kernel_size; i++) { - vec2 step_offset = check_step_kernel[i] * uv_step; - vec2 check_uv = uvn + step_offset; + step_offset = check_step_kernel[i] * uv_step; + check_uv = uvn + step_offset; if(any(notEqual(check_uv, clamp(check_uv, vec2(0.0), vec2(1.0))))) { continue; } - if(params.iteration_index > 0) + if(params.iteration_index > 0.) { - vec4 buffer_load = get_value(!set_a, check_uv, render_size); - - check_uv = buffer_load.xy; + get_value(!set_a, check_uv); step_offset = check_uv - uvn; } - vec4 uv_sample = vec4(textureLod(velocity_sampler, check_uv, 0.0).xyz, textureLod(depth_sampler, check_uv, 0.0).x); + uv_sample = vec4(textureLod(velocity_sampler, check_uv, 0.0).xyz, textureLod(depth_sampler, check_uv, 0.0).x); - vec4 current_sample_fitness = sample_fitness(step_offset, uv_sample, render_size); + sample_fitness(step_offset, uv_sample, render_size, current_sample_fitness); - if (is_sample_better(current_sample_fitness, best_sample_fitness) > 0.5) + if (mix(1. - step(best_sample_fitness.x * current_sample_fitness.w, current_sample_fitness.x * best_sample_fitness.w), step(best_sample_fitness.z, current_sample_fitness.z), step(0.5, best_sample_fitness.w) * step(0.5, current_sample_fitness.w)) > 0.5)//is_sample_better(current_sample_fitness, best_sample_fitness) > 0.5) { best_sample_fitness = current_sample_fitness; chosen_uv = check_uv; @@ -246,7 +255,7 @@ void main() if(params.iteration_index < params.last_iteration_index) { - set_value(set_a, uvi, vec4(chosen_uv, 0, 0), render_size); + set_value(set_a, uvi, vec4(chosen_uv, 0, 0)); return; } @@ -257,11 +266,11 @@ void main() if(best_sample_fitness.w == 0 || depth > backtracked_sample.z) { - set_value(set_a, uvi, vec4(uvn, 0, 0), render_size); + set_value(set_a, uvi, vec4(uvn, 0, 0)); return; } - set_value(set_a, uvi, backtracked_sample, render_size); + set_value(set_a, uvi, backtracked_sample); return; } diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_backtracking_experimental.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_backtracking_experimental.glsl.import new file mode 100644 index 0000000..73c03a5 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_backtracking_experimental.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://rkkajixdjosk" +path="res://.godot/imported/jfp_backtracking_experimental.glsl-a7a47621c3999d6edb8c655271f824d5.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_backtracking_experimental.glsl" +dest_files=["res://.godot/imported/jfp_backtracking_experimental.glsl-a7a47621c3999d6edb8c655271f824d5.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_simple.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_simple.glsl new file mode 100644 index 0000000..02338eb --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_simple.glsl @@ -0,0 +1,192 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 + +layout(set = 0, binding = 0) uniform sampler2D tile_max_sampler; +layout(rgba16f, set = 0, binding = 1) uniform writeonly image2D buffer_a; +layout(rgba16f, set = 0, binding = 2) uniform writeonly image2D buffer_b; +layout(set = 0, binding = 3) uniform sampler2D buffer_a_sampler; +layout(set = 0, binding = 4) uniform sampler2D buffer_b_sampler; + +layout(push_constant, std430) uniform Params +{ + int iteration_index; + int last_iteration_index; + int nan1; + int nan2; + float perpen_error_thresh; + float sample_step_multiplier; + float motion_blur_intensity; + float nan_fl_5; + float nan_fl_4; + float nan_fl_3; + float nan_fl_6; + float step_exponent_modifier; + float step_size; + float max_dilation_radius; + float nan_fl_1; + float nan_fl_2; +} params; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + +const int kernel_size = 8; + +const vec2 check_step_kernel[kernel_size] = { + vec2(-1, 0), + vec2(1, 0), + vec2(0, -1), + vec2(0, 1), + vec2(-1, 1), + vec2(1, -1), + vec2(1, 1), + vec2(-1, -1), +}; + +vec2 get_value(bool a, vec2 uv) +{ + if(a) + { + return textureLod(buffer_a_sampler, uv, 0.0).xy; + } + else + { + return textureLod(buffer_b_sampler, uv, 0.0).xy; + } +} + +//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) + { + imageStore(buffer_a, uvi, value); + } + else + { + imageStore(buffer_b, uvi, 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); + 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 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); +} + +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);// +} + +void main() +{ + ivec2 render_size = ivec2(textureSize(tile_max_sampler, 0)); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y)) + { + 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); + + vec2 chosen_uv = uvn; + + bool set_a = !bool(step(0.5, float(params.iteration_index % 2))); + + vec2 step_offset; + + vec2 check_uv; + + vec4 uv_sample; + + vec4 current_sample_fitness; + + for(int i = 0; i < kernel_size; i++) + { + step_offset = check_step_kernel[i] * uv_step; + check_uv = uvn + step_offset; + + if(any(notEqual(check_uv, clamp(check_uv, vec2(0.0), vec2(1.0))))) + { + continue; + } + + if(params.iteration_index > 0) + { + check_uv = get_value(!set_a, check_uv).xy; + + step_offset = check_uv - uvn; + } + + uv_sample = textureLod(tile_max_sampler, check_uv, 0.0); + + 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; + } + } + + set_value(set_a, uvi, vec4(chosen_uv, 0, 0)); +} +// +// if((a.w == b.w) && (a.w == 1)) +// { +// return a.z < b.z ? 0. : 1.; +// } +// +// return a.x * b.w < b.x * a.w ? 1. : 0.; \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_simple.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_simple.glsl.import new file mode 100644 index 0000000..632a2c5 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_simple.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://c4dywnp7k8rph" +path="res://.godot/imported/jfp_simple.glsl-96987ba8c42947c7e648d28f42a73f7a.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_simple.glsl" +dest_files=["res://.godot/imported/jfp_simple.glsl-96987ba8c42947c7e648d28f42a73f7a.res"] + +[params] + diff --git a/addons/MyJumpFloodIteration/jump_flood_blur.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_blur.glsl similarity index 59% rename from addons/MyJumpFloodIteration/jump_flood_blur.glsl rename to addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_blur.glsl index fa3c665..469b14e 100644 --- a/addons/MyJumpFloodIteration/jump_flood_blur.glsl +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_blur.glsl @@ -11,23 +11,26 @@ 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 image2D past_color_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 { float motion_blur_samples; float motion_blur_intensity; float motion_blur_center_fade; - float debug; - float freeze; float frame; float last_iteration_index; float sample_step_multiplier; float step_exponent_modifier; float max_dilation_radius; - float nan_fl_3; - float nan_fl_4; - int debug_page; + int nan0; int nan1; int nan2; int nan3; @@ -72,12 +75,7 @@ void main() { return; } - // show past image for freeze frame - if(params.freeze > 0) - { - imageStore(output_image, uvi, imageLoad(past_color_image, uvi)); - return; - } + // must be on pixel center for whole values (tested) vec2 uvn = vec2(uvi + vec2(0.5)) / render_size; @@ -89,10 +87,9 @@ void main() vec3 naive_velocity = -textureLod(vector_sampler, uvn, 0.0).xyz; // if velocity is 0 and we dont show debug, return right away. - if ((dot(dominant_velocity, dominant_velocity) == 0 || params.motion_blur_intensity == 0) && params.debug == 0) + if ((dot(dominant_velocity, dominant_velocity) == 0 || params.motion_blur_intensity == 0)) { imageStore(output_image, uvi, base_color); - imageStore(past_color_image, uvi, base_color); return; } // offset along velocity to blend between sample steps @@ -115,40 +112,82 @@ void main() vec3 naive_offset = naive_step_sample * noise_offset; + vec3 dominant_back_offset = -step_sample * (1. - noise_offset); + vec4 col = base_color * total_weight; float naive_depth = textureLod(depth_sampler, uvn, 0.0).x; + float backstepping_coef = clamp(length(dominant_velocity) / 0.05, 0, 1); + + vec2 dominant_uvo; + + vec2 naive_uvo; + + vec3 current_dominant_offset; + + float current_naive_depth; + + float foreground; + + vec3 current_dominant_velocity; + + float motion_difference; + + float sample_weight; + + float dominant_naive_mix; + + vec2 sample_uv; + for (int i = 1; i < params.motion_blur_samples; i++) { dominant_offset += step_sample; naive_offset += naive_step_sample; - vec2 dominant_uvo = uvn + dominant_offset.xy; + dominant_uvo = uvn + dominant_offset.xy; - vec2 naive_uvo = uvn + naive_offset.xy; + naive_uvo = uvn + naive_offset.xy; + + current_dominant_offset = dominant_offset; - if (any(notEqual(dominant_uvo, clamp(dominant_uvo, vec2(0.0), vec2(1.0))))) + current_naive_depth = textureLod(depth_sampler, dominant_uvo, 0.0).x; + // is current depth closer than origin of dilation (stepped into a foreground object) + foreground = step(naive_depth + current_dominant_offset.z, current_naive_depth - 0.0001); + + velocity_map_step_sample = textureLod(velocity_map, dominant_uvo, 0.0); + + current_dominant_velocity = -textureLod(vector_sampler, velocity_map_step_sample.xy, 0.0).xyz; + + motion_difference = get_motion_difference(dominant_velocity.xy, current_dominant_velocity.xy, 0.1); + + sample_weight = 1; + + if (any(notEqual(dominant_uvo, clamp(dominant_uvo, vec2(0.0), vec2(1.0)))) || foreground * motion_difference > 0.5) { - break; + dominant_uvo = uvn + dominant_back_offset.xy; + current_dominant_offset = dominant_back_offset; + dominant_back_offset -= step_sample; + sample_weight = 0.5;//backstepping_coef; } velocity_map_step_sample = textureLod(velocity_map, dominant_uvo, 0.0); - vec3 current_dominant_velocity = -textureLod(vector_sampler, velocity_map_step_sample.xy, 0.0).xyz; - - float current_naive_depth = textureLod(depth_sampler, dominant_uvo, 0.0).x; - // is current velocity different than dilated velocity - float motion_difference = get_motion_difference(dominant_velocity.xy, current_dominant_velocity.xy, 0.1); - // is current depth closer than origin of dilation (object in the foreground) - float foreground = step(naive_depth + dominant_offset.z, current_naive_depth - 0.0001); + current_dominant_velocity = -textureLod(vector_sampler, velocity_map_step_sample.xy, 0.0).xyz; + // is current velocity different than dilated velocity + + current_naive_depth = textureLod(depth_sampler, dominant_uvo, 0.0).x; + // is current depth closer than origin of dilation (stepped into a foreground object) + foreground = step(naive_depth + current_dominant_offset.z, current_naive_depth - 0.002); + + motion_difference = get_motion_difference(dominant_velocity.xy, current_dominant_velocity.xy, 0.1); // if we are sampling a foreground object and its velocity is different, discard this sample (prevent ghosting) - float sample_weight = 1 - (foreground * motion_difference); + sample_weight *= 1 - (foreground * motion_difference); - float dominant_naive_mix = 1. - step(0.9, motion_difference); + dominant_naive_mix = 1. - step(0.9, motion_difference); - vec2 sample_uv = mix(naive_uvo, dominant_uvo, dominant_naive_mix); + sample_uv = mix(naive_uvo, dominant_uvo, dominant_naive_mix); total_weight += sample_weight; @@ -157,42 +196,5 @@ void main() col /= total_weight; - if (params.debug == 0) - { - imageStore(output_image, uvi, col); - imageStore(past_color_image, uvi, col); - return; - } - - vec4 tl_col; - - vec4 tr_col; - - vec4 bl_col; - - vec4 br_col; - - if(params.debug_page == 0) - { - tl_col = vec4((textureLod(vector_sampler, uvn, 0.0).xyz) * vec3(10, 10, 10000), 1); - tr_col = vec4(abs(dominant_velocity.xy) * 10, 0, 1); - bl_col = vec4(abs(velocity_map_sample.xyw - vec3(uvn, 0)) * vec3(10, 10, 1), 1); - br_col = col; - } - if(params.debug_page == 1) - { - tl_col = vec4(naive_depth * 10); - tr_col = textureLod(color_sampler, velocity_map_sample.xy, 0.0);// - //bl_col = vec4(dominant_depth * 10); - br_col = col; - } - - imageStore(output_image, uvi / 2, tl_col); - imageStore(output_image, uvi / 2 + ivec2(vec2(0.5, 0.5) * render_size), br_col); - imageStore(output_image, uvi / 2 + ivec2(vec2(0.0, 0.5) * render_size), bl_col); - imageStore(output_image, uvi / 2 + ivec2(vec2(0.5, 0.0) * render_size), tr_col); - imageStore(past_color_image, uvi / 2, tl_col); - imageStore(past_color_image, uvi / 2 + ivec2(vec2(0.5, 0.5) * render_size), br_col); - imageStore(past_color_image, uvi / 2 + ivec2(vec2(0.0, 0.5) * render_size), bl_col); - imageStore(past_color_image, uvi / 2 + ivec2(vec2(0.5, 0.0) * render_size), tr_col); + imageStore(output_image, uvi, col); } \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_blur.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_blur.glsl.import new file mode 100644 index 0000000..97b9fad --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_blur.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://c57nhlyxb4m1t" +path="res://.godot/imported/jump_flood_blur.glsl-11f088c8cddfb4c62f32dfa84c694ded.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_blur.glsl" +dest_files=["res://.godot/imported/jump_flood_blur.glsl-11f088c8cddfb4c62f32dfa84c694ded.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_mcguire_blur.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_mcguire_blur.glsl new file mode 100644 index 0000000..af39e6a --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_mcguire_blur.glsl @@ -0,0 +1,235 @@ +#[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 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(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) / min(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(1 >= 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; +} +// ---------------------------------------------------------- + +float get_motion_difference(vec2 V, vec2 V2, float power) +{ + vec2 VO = V - V2; + float difference = dot(VO, V) / max(FLT_MIN, dot(V, V)); + return pow(clamp(difference, 0, 1), power); +} + +vec2 sample_random_offset(vec2 uv, float j) +{ + return vec2(0); +} + +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);// * 2; + + vec2 vn = vnz.xy; + + float vn_length = max(0.5, length(vn)); + + vec2 wn = safenorm(vn); + + vec4 col_x = textureLod(color_sampler, x, 0.0); + + vec3 vxz = textureLod(vector_sampler, x, 0.0).xyz * vec3(render_size, 1);// * 2; + + vec2 vx = vxz.xy; + + if(vn_length <= 0.5) + { + imageStore(output_image, uvi, col_x); + 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)); + return; + } + + float zx = -0.05 / max(FLT_MIN, textureLod(depth_sampler, x, 0.0).x); + + float vx_length = max(0.5, length(vx)); + + vec2 wx = safenorm(vx); + + vec2 wp = vec2(-wn.y, wn.x); + + if(dot(wp, vx) < 0) + { + wp = -wp; + } + + vec2 wc = safenorm(mix(wp, wx, clamp((vx_length - 0.5) / 1.5, 0, 1))); + + float weight = 1;//params.motion_blur_samples / (100 * vx_length); + + vec4 sum = col_x * weight; + + float j = interleaved_gradient_noise(uvi) - 0.5; + + int vnvx = 2;//int(vn_length / (10 + vx_length)) + 2; + + for(int i = 0; i < params.motion_blur_samples; i++) + { + if(i == (params.motion_blur_samples - 1) / 2) + { + continue; + } + float t = mix(-1., 0.0, (i + j + 1.0) / (params.motion_blur_samples + 1.0)); + + float T = abs(t * vn_length); + + float Tx = abs((t + 0.5) * vn_length); + + bool sample_main_v = !(((i - 1) % vnvx) == 0); + + vec2 d = vn;//sample_main_v ? vn : vx; + + float dz = vnz.z;//sample_main_v ? vnz.z : vxz.z; + + vec2 wd = safenorm(d); + + vec2 y = x + (d / render_size) * t; + + vec2 vy = textureLod(vector_sampler, y, 0.0).xy * render_size;// * 2; + + float vy_length = max(0.5, length(vy)); + + float zy = -0.05 / max(FLT_MIN, textureLod(depth_sampler, y, 0.0).x - dz * t); + + float f = z_compare(zy, zx, 15); + float b = z_compare(zx, zy, 15); + + float wa = abs(max(0, dot(vy / vy_length, wd))); + + float wb = abs((dot(wc, wd))); + + float cone_x = cone(T, vx_length); // how much of the velocity reaches the current position + + float cone_y = cone(T, vy_length); // how much of the velocity reaches the current position + + float ay = clamp(max(step(FLT_MIN, f * wa * cone_y), step(FLT_MIN, b * wb * cone_x)), 0, 1);// * wb;// + cylinder(T, vy_length) * cylinder(T, vx_length) * 2;//cylinder(T, min(vy_length, vx_length)) * 2. * max(wa, wb);// + + vec4 col_y = textureLod(color_sampler, y, 0.0); + + vec4 final_color = mix(col_x, col_y, ay); + + float final_weight = mix(1, 1, ay); + + weight += final_weight;//ay; + sum += final_color * final_weight;// * ay; + } + + sum /= weight; + + imageStore(output_image, uvi, sum); + + imageStore(debug_1_image, uvi, 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)); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_mcguire_blur.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_mcguire_blur.glsl.import new file mode 100644 index 0000000..1e20159 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_mcguire_blur.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://dc6r26wwdjceq" +path="res://.godot/imported/jump_flood_mcguire_blur.glsl-01a8aea5f4a3ebff22641db3a49ace6c.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_mcguire_blur.glsl" +dest_files=["res://.godot/imported/jump_flood_mcguire_blur.glsl-01a8aea5f4a3ebff22641db3a49ace6c.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_new_blur.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_new_blur.glsl new file mode 100644 index 0000000..81112f6 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_new_blur.glsl @@ -0,0 +1,274 @@ +#[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 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(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) / min(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(1 >= 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; +} +// ---------------------------------------------------------- + +float get_motion_difference(vec2 V, vec2 V2, float power) +{ + vec2 VO = V - V2; + float difference = dot(VO, V) / max(FLT_MIN, dot(V, V)); + return pow(clamp(difference, 0, 1), power); +} + +vec2 sample_random_offset(vec2 uv, float j) +{ + return vec2(0); +} + +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);// * 2; + + vec2 vn = vnz.xy; + + float vn_length = max(0.5, length(vn)); + + vec2 wn = safenorm(vn); + + vec4 col_x = textureLod(color_sampler, x, 0.0); + + vec3 vxz = textureLod(vector_sampler, x, 0.0).xyz * vec3(render_size, 1);// * 2; + + vec2 vx = vxz.xy; + + if(vn_length <= 0.5) + { + imageStore(output_image, uvi, col_x); + 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)); + return; + } + + float zx = -0.05 / max(FLT_MIN, textureLod(depth_sampler, x, 0.0).x); + + float vx_length = max(0.5, length(vx)); + + vec2 wx = safenorm(vx); + + vec2 wp = vec2(-wn.y, wn.x); + + if(dot(wp, vx) < 0) + { + wp = -wp; + } + + vec2 wc = safenorm(mix(wp, wx, clamp((vx_length - 0.5) / 1.5, 0, 1))); + + float weight = 0;// params.motion_blur_samples / (40 * vx_length); + + vec4 sum = col_x * weight; + + float j = interleaved_gradient_noise(uvi) - 0.5; + + int vnvx = 2;//int(vn_length / (10 + vx_length)) + 2; + + float total_back_weight = 1e-10; + + vec4 back_sum = col_x * total_back_weight; + + for(int i = 0; i < params.motion_blur_samples; i++) + { + float t = mix(-1., 0.0, (i + j + 1.0) / (params.motion_blur_samples + 1.0)); + + float T = abs(t * vn_length); + + float Tx = abs((t + 0.5) * vn_length); + + bool sample_main_v = !(((i - 1) % vnvx) == 0); + + vec2 d = vn;//sample_main_v ? vn : vx; + + vec2 nai_d = vx; + + vec2 nai_wd = safenorm(nai_d); + + float nai_dz = vxz.z; + + float dz = vnz.z;//sample_main_v ? vnz.z : vxz.z; + + vec2 wd = safenorm(d); + + vec2 y = x + (d / render_size) * t; + + vec2 nai_y = x + (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; + + float vy_length = max(0.5, length(vy)); + + vec2 nai_vy = textureLod(vector_sampler, nai_y, 0.0).xy * render_size; + + float nai_vy_length = max(0.5, length(nai_vy)); + + float zy = -0.05 / max(FLT_MIN, textureLod(depth_sampler, y, 0.0).x - dz * t); + + float nai_zy = -0.05 / max(FLT_MIN, textureLod(depth_sampler, nai_y, 0.0).x - nai_dz * t); + + float f = z_compare(zy, zx, 15); + float b = z_compare(zx, zy, 15); + + float wa = abs(max(0, dot(vy / vy_length, wd))); + + float wb = abs((dot(wc, wd))); + + float cone_x = cone(T, vx_length); + + float cone_y = cone(T, vy_length); + + float nai_f = z_compare(nai_zy, zx, 15); + + float nai_b = z_compare(zx, nai_zy, 15); + + float nai_wa = abs(max(0, dot(nai_vy / nai_vy_length, nai_wd))); + + float nai_wb = abs((dot(wc, nai_wd))); + + float nai_cone_y = cone(T, nai_vy_length); + + float ay = max(f * wa * step(FLT_MIN, cone_y), b * wb * cone_x); + + float nai_ay = nai_b; + + vec4 col_y = textureLod(color_sampler, 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 += back_weight; + + back_sum += col_back * back_weight; + + weight += ay; + + sum += col_y * ay; + } + + 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); + + 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)); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_new_blur.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_new_blur.glsl.import new file mode 100644 index 0000000..effe9a4 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_new_blur.glsl.import @@ -0,0 +1,14 @@ +[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/MyJumpFloodIteration/jump_flood_overlay.glsl b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_overlay.glsl similarity index 100% rename from addons/MyJumpFloodIteration/jump_flood_overlay.glsl rename to addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_overlay.glsl diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_overlay.glsl.import b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_overlay.glsl.import new file mode 100644 index 0000000..be6ca36 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_overlay.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://dig08kpnfakuf" +path="res://.godot/imported/jump_flood_overlay.glsl-fc28b3ae9a688e5da04536a5cdb7b76e.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_overlay.glsl" +dest_files=["res://.godot/imported/jump_flood_overlay.glsl-fc28b3ae9a688e5da04536a5cdb7b76e.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/jf_simple_stage.tres b/addons/SphynxMotionBlurToolkit/JumpFlood/jf_simple_stage.tres new file mode 100644 index 0000000..af7fc15 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/jf_simple_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://bj3exhmsfcx4w"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_v4e3u"] +[ext_resource type="RDShaderFile" uid="uid://c4dywnp7k8rph" path="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_simple.glsl" id="2_msxel"] + +[resource] +script = ExtResource("1_v4e3u") +shader_file = ExtResource("2_msxel") diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_blur_stage.tres b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_blur_stage.tres new file mode 100644 index 0000000..684a55a --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_blur_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://nhb123qs0ja8"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_fyqxe"] +[ext_resource type="RDShaderFile" uid="uid://c57nhlyxb4m1t" path="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_blur.glsl" id="2_c1vs2"] + +[resource] +script = ExtResource("1_fyqxe") +shader_file = ExtResource("2_c1vs2") diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_construction_stage.tres b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_construction_stage.tres new file mode 100644 index 0000000..8631f8c --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_construction_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://clwi2fnp1nm3r"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_eeyf1"] +[ext_resource type="RDShaderFile" uid="uid://rkkajixdjosk" path="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jfp_backtracking_experimental.glsl" id="2_o6bvw"] + +[resource] +script = ExtResource("1_eeyf1") +shader_file = ExtResource("2_o6bvw") diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_motion_blur.gd b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_motion_blur.gd new file mode 100644 index 0000000..f5a1f2b --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_motion_blur.gd @@ -0,0 +1,270 @@ +extends MotionBlurCompositorEffect +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 var blur_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_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) + +@export var construct_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_construction_stage.tres"): + set(value): + unsubscribe_shader_stage(construct_stage) + 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 +@export var backtracking_sample_count : int = 8 + +## how sensitive the backtracking for velocities be +@export var backtracking_velocity_match_threshold : float = 0.9 + +## how sensitively the backtracking should treat velocities that are a different +## length along that velocity +@export var backtracking_velocity_match_parallel_sensitivity : float = 1 + +## how sensitively the backtracking should treat velcoities that have perpendicular +## offset to that velocity +@export var backtracking_velcoity_match_perpendicular_sensitivity : float = 0.05 + +## how closely does the depth of the backtracked sample has to match the original sample to be +## 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" +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 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_motion_blur_intensity = motion_blur_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_motion_blur_intensity = motion_blur_intensity * capped_frame_time / delta_time + + + ensure_texture(texture, render_scene_buffers) + ensure_texture(buffer_a, render_scene_buffers)#, RenderingDevice.DATA_FORMAT_R16G16_SFLOAT) + 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 push_constant: PackedFloat32Array = [ + motion_blur_samples, + temp_motion_blur_intensity, + motion_blur_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 texture_image := render_scene_buffers.get_texture_slice(context, texture, 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 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)) + + var tex_uniform_set + var compute_list + + var x_groups := floori((render_size.x - 1) / 16 + 1) + var y_groups := floori((render_size.y - 1) / 16 + 1) + + tex_uniform_set = UniformSetCacheRD.get_cache(construct_stage.shader, 0, [ + get_sampler_uniform(depth_image, 0, false), + get_sampler_uniform(custom_velocity_image, 1, false), + get_image_uniform(buffer_a_image, 2), + get_image_uniform(buffer_b_image, 3), + get_sampler_uniform(buffer_a_image, 4, false), + get_sampler_uniform(buffer_b_image, 5, false) + ]) + + compute_list = rd.compute_list_begin() + rd.compute_list_bind_compute_pipeline(compute_list, construct_stage.pipeline) + rd.compute_list_bind_uniform_set(compute_list, tex_uniform_set, 0) + + for i in JFA_pass_count: + var jf_push_constants : PackedInt32Array = [ + i, + last_iteration_index, + backtracking_sample_count, + 16 + ] + + var step_size : float = round(pow(2 + step_exponent_modifier, last_iteration_index - i)) * sample_step_multiplier; + + var jf_float_push_constants_test : PackedFloat32Array = [ + perpen_error_threshold, + sample_step_multiplier, + temp_motion_blur_intensity, + backtracking_velocity_match_threshold, + backtracking_velocity_match_parallel_sensitivity, + backtracking_velcoity_match_perpendicular_sensitivity, + backtracbing_depth_match_threshold, + 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()) + + rd.compute_list_set_push_constant(compute_list, jf_byte_array, jf_byte_array.size()) + rd.compute_list_dispatch(compute_list, x_groups, y_groups, 1) + + rd.compute_list_end() + + rd.draw_command_end_label() + + 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(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), + "Compute Blur", + view) + + dispatch_stage(overlay_stage, + [ + get_sampler_uniform(texture_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/jump_flood_neighbor_max_stage.tres b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_neighbor_max_stage.tres new file mode 100644 index 0000000..532788e --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_neighbor_max_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://co5k7plgmxepi"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_8et3l"] +[ext_resource type="RDShaderFile" uid="uid://cfk5chwlcyay4" path="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_neighbor_max.glsl" id="2_fub7x"] + +[resource] +script = ExtResource("1_8et3l") +shader_file = ExtResource("2_fub7x") diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_overlay_stage.tres b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_overlay_stage.tres new file mode 100644 index 0000000..1016abe --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_overlay_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://dc5fr84ue3dn5"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_6wgo2"] +[ext_resource type="RDShaderFile" uid="uid://dig08kpnfakuf" path="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_overlay.glsl" id="2_ljukb"] + +[resource] +script = ExtResource("1_6wgo2") +shader_file = ExtResource("2_ljukb") diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_tile_max_x_stage.tres b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_tile_max_x_stage.tres new file mode 100644 index 0000000..bd10947 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_tile_max_x_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://c10aboaly701b"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_5367c"] +[ext_resource type="RDShaderFile" uid="uid://djp3da364fk2l" path="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_x.glsl" id="2_1b71e"] + +[resource] +script = ExtResource("1_5367c") +shader_file = ExtResource("2_1b71e") diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_tile_max_y_stage.tres b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_tile_max_y_stage.tres new file mode 100644 index 0000000..17ed1c7 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_tile_max_y_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://cymk87e4nyxva"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_5vg08"] +[ext_resource type="RDShaderFile" uid="uid://cqlltc8f21wre" path="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_guertin_tile_max_y.glsl" id="2_iusae"] + +[resource] +script = ExtResource("1_5vg08") +shader_file = ExtResource("2_iusae") diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/simple_jf_blur_stage.tres b/addons/SphynxMotionBlurToolkit/JumpFlood/simple_jf_blur_stage.tres new file mode 100644 index 0000000..7ac34ee --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/simple_jf_blur_stage.tres @@ -0,0 +1,8 @@ +[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"] + +[resource] +script = ExtResource("1_ljx3c") +shader_file = ExtResource("2_ase62") diff --git a/addons/SphynxMotionBlurToolkit/JumpFlood/simple_jf_motion_blur.gd b/addons/SphynxMotionBlurToolkit/JumpFlood/simple_jf_motion_blur.gd new file mode 100644 index 0000000..6c98583 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/JumpFlood/simple_jf_motion_blur.gd @@ -0,0 +1,353 @@ +extends MotionBlurCompositorEffect +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 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/simple_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) + +## 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" + +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 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 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_motion_blur_intensity = motion_blur_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_motion_blur_intensity = motion_blur_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(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 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 = [ + motion_blur_samples, + temp_motion_blur_intensity, + motion_blur_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 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) + + 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_motion_blur_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) + + + + rd.draw_command_end_label() + + 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_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) + ], + 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/McGuire/ShaderFiles/mcguire_blur.glsl b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_blur.glsl new file mode 100644 index 0000000..5ba1804 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_blur.glsl @@ -0,0 +1,137 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 + +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(push_constant, std430) uniform Params +{ + float minimum_user_threshold; + float importance_bias; + float maximum_jitter_value; + float nan8; + int tile_size; + int sample_count; + int frame; + int nan4; +} 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 - abs(T) / v, 0, 1); +} + +float cylinder(float T, float v) +{ + return 1.0 - smoothstep(0.95 * v, 1.05 * v, abs(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 multiplier) +{ + return clamp(1. + (a - b) * multiplier, 0, 1); +} +// ---------------------------------------------------------- + +// 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))); +} +// ---------------------------------------------------------- + +vec2 sample_random_offset(vec2 uv, float j) +{ + return vec2(0); +} + +void main() +{ + ivec2 render_size = ivec2(textureSize(color_sampler, 0)); + ivec2 tile_render_size = ivec2(textureSize(neighbor_max, 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 vn = textureLod(neighbor_max, x, 0.0).xy * render_size / 2; + + float vn_length = max(0.5, length(vn)); + + vec4 base_color = textureLod(color_sampler, x, 0.0); + + if(vn_length <= 0.5) + { + imageStore(output_color, uvi, base_color); + return; + } + + vec2 vx = textureLod(velocity_sampler, x, 0.0).xy * render_size / 2; + + float zx = -0.05 / textureLod(depth_sampler, x, 0.0).x; + + float vx_length = max(0.5, length(vx)); + + float weight = 1. / vx_length; + + vec4 sum = base_color * weight; + + float j = interleaved_gradient_noise(uvi, params.frame) - 0.5; + + for(int i = 0; i < params.sample_count; i++) + { + if(i == (params.sample_count - 1) / 2) + { + continue; + } + float t = mix(-1, 1, (i + j + 1.0) / (params.sample_count + 1.0)); + + float T = t * vn_length; + + vec2 y = x + (vn / render_size) * t; + + vec2 vy = textureLod(velocity_sampler, y, 0.0).xy * render_size / 2; + + float vy_length = max(0.5, length(vy)); + + float zy = -0.05 / textureLod(depth_sampler, y, 0.0).x; + + float f = soft_depth_compare(zx, zy, 0.01); + float b = soft_depth_compare(zy, zx, 0.01); + + float ay = f * cone(T, vy_length) + b * cone(T, vx_length) + cylinder(T, vy_length) * cylinder(T, vx_length) * 2; + + weight += ay; + sum += ay * textureLod(color_sampler, y, 0.0); + } + + sum /= weight; + + imageStore(output_color, uvi, sum); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_blur.glsl.import b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_blur.glsl.import new file mode 100644 index 0000000..06fe5dd --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_blur.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://7fjex8wuiejk" +path="res://.godot/imported/mcguire_blur.glsl-0cc0e90626b85e4aae8d4b21c9368b86.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_blur.glsl" +dest_files=["res://.godot/imported/mcguire_blur.glsl-0cc0e90626b85e4aae8d4b21c9368b86.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_neighbor_max.glsl b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_neighbor_max.glsl new file mode 100644 index 0000000..ccd3b7f --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_neighbor_max.glsl @@ -0,0 +1,72 @@ +#[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(rgba16f, set = 0, binding = 1) 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_velocity_length = 0; + + 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; + } + + bool is_diagonal = (abs(i) + abs(j) == 2); + + vec2 current_neighbor_velocity = textureLod(tile_max, current_uv, 0.0).xy; + + bool facing_center = dot(current_neighbor_velocity, current_offset) > 0; + + if(is_diagonal && !facing_center) + { + continue; + } + + float current_neighbor_velocity_length = dot(current_neighbor_velocity, current_neighbor_velocity); + if(current_neighbor_velocity_length > max_neighbor_velocity_length) + { + max_neighbor_velocity_length = current_neighbor_velocity_length; + max_neighbor_velocity = current_neighbor_velocity; + } + } + } + + imageStore(neighbor_max, uvi, vec4(max_neighbor_velocity, 0, 1)); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_neighbor_max.glsl.import b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_neighbor_max.glsl.import new file mode 100644 index 0000000..a1d726c --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_neighbor_max.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://byfogr1qtbafi" +path="res://.godot/imported/mcguire_neighbor_max.glsl-aa40cc8d534a08ad7aaf84bf0615cc3a.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_neighbor_max.glsl" +dest_files=["res://.godot/imported/mcguire_neighbor_max.glsl-aa40cc8d534a08ad7aaf84bf0615cc3a.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_overlay.glsl b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_overlay.glsl new file mode 100644 index 0000000..c85ac5b --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_overlay.glsl @@ -0,0 +1,18 @@ +#[compute] +#version 450 + +layout(set = 0, binding = 0) uniform sampler2D blur_sampler; +layout(rgba16f, set = 0, binding = 1) uniform image2D color_image; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; +void main() +{ + ivec2 render_size = ivec2(textureSize(blur_sampler, 0)); + ivec2 output_size = imageSize(color_image); + ivec2 uv = ivec2(gl_GlobalInvocationID.xy); + if ((uv.x >= output_size.x) || (uv.y >= output_size.y)) + { + return; + } + imageStore(color_image, uv, textureLod(blur_sampler, (vec2(uv) + 0.5) / output_size, 0.0)); +} diff --git a/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_overlay.glsl.import b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_overlay.glsl.import new file mode 100644 index 0000000..96ed706 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_overlay.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://ylkrbqh7unvl" +path="res://.godot/imported/mcguire_overlay.glsl-a331e470c95eacb608a05976de7b2202.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_overlay.glsl" +dest_files=["res://.godot/imported/mcguire_overlay.glsl-a331e470c95eacb608a05976de7b2202.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_x.glsl b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_x.glsl new file mode 100644 index 0000000..4106f70 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_x.glsl @@ -0,0 +1,54 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 + +layout(set = 0, binding = 0) uniform sampler2D velocity_sampler; +layout(rgba16f, set = 0, binding = 1) uniform writeonly image2D tile_max_x; + +layout(push_constant, std430) uniform Params +{ + float nan5; + float nan6; + float nan7; + float nan8; + int tile_size; + 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(velocity_sampler, 0)); + ivec2 output_size = imageSize(tile_max_x); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + ivec2 global_uvi = uvi * ivec2(params.tile_size, 1); + if ((uvi.x >= output_size.x) || (uvi.y >= output_size.y)) + { + return; + } + + vec2 uvn = (vec2(global_uvi) + vec2(0.5)) / render_size; + + vec2 max_velocity = vec2(0); + + float max_velocity_length = 0; + + for(int i = 0; i < params.tile_size; i++) + { + vec2 current_uv = uvn + vec2(float(i) / render_size.x, 0); + vec2 velocity_sample = textureLod(velocity_sampler, current_uv, 0.0).xy; + float current_velocity_length = dot(velocity_sample, velocity_sample); + if(current_velocity_length > max_velocity_length) + { + max_velocity_length = current_velocity_length; + max_velocity = velocity_sample; + } + } + imageStore(tile_max_x, uvi, vec4(max_velocity, 0, 1)); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_x.glsl.import b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_x.glsl.import new file mode 100644 index 0000000..e0e6e03 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_x.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://bp5jl5351ph2d" +path="res://.godot/imported/mcguire_tile_max_x.glsl-9c459b3d537ec225893d39ee91be1c1e.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_x.glsl" +dest_files=["res://.godot/imported/mcguire_tile_max_x.glsl-9c459b3d537ec225893d39ee91be1c1e.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_y.glsl b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_y.glsl new file mode 100644 index 0000000..ecd2c84 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_y.glsl @@ -0,0 +1,54 @@ +#[compute] +#version 450 + +#define FLT_MAX 3.402823466e+38 +#define FLT_MIN 1.175494351e-38 + +layout(set = 0, binding = 0) uniform sampler2D tile_max_x; +layout(rgba16f, set = 0, binding = 1) uniform writeonly image2D tile_max; + +layout(push_constant, std430) uniform Params +{ + float nan5; + float nan6; + float nan7; + float nan8; + int tile_size; + 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_x, 0)); + ivec2 output_size = imageSize(tile_max); + ivec2 uvi = ivec2(gl_GlobalInvocationID.xy); + ivec2 global_uvi = uvi * ivec2(1, params.tile_size); + if ((uvi.x >= output_size.x) || (uvi.y >= output_size.y)) + { + return; + } + + vec2 uvn = (vec2(global_uvi) + vec2(0.5)) / render_size; + + vec2 max_velocity = vec2(0); + + float max_velocity_length = 0; + + for(int i = 0; i < params.tile_size; i++) + { + vec2 current_uv = uvn + vec2(0, float(i) / render_size.y); + vec2 velocity_sample = textureLod(tile_max_x, current_uv, 0.0).xy; + float current_velocity_length = dot(velocity_sample, velocity_sample); + if(current_velocity_length > max_velocity_length) + { + max_velocity_length = current_velocity_length; + max_velocity = velocity_sample; + } + } + imageStore(tile_max, uvi, vec4(max_velocity, 0, 1)); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_y.glsl.import b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_y.glsl.import new file mode 100644 index 0000000..1fa0c65 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_y.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://deow8m5u2ji84" +path="res://.godot/imported/mcguire_tile_max_y.glsl-d6c42f715f0dbdbc13190532231a64e9.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_y.glsl" +dest_files=["res://.godot/imported/mcguire_tile_max_y.glsl-d6c42f715f0dbdbc13190532231a64e9.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_variance.glsl b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_variance.glsl new file mode 100644 index 0000000..24ec95c --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_variance.glsl @@ -0,0 +1,68 @@ +#[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(rgba16f, set = 0, binding = 1) uniform writeonly image2D tile_variance; + +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; + + float variance = 0; + + vec2 current_velocity = abs(normalize(textureLod(tile_max, uvn, 0.0).xy)); + + float tile_count = 0; + + 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; + } + if(i == j && i == 0) + { + continue; + } + + tile_count += 1; + + vec2 current_neighbor_velocity = abs(normalize(textureLod(tile_max, current_uv, 0.0).xy)); + + variance += dot(current_velocity, current_neighbor_velocity); + } + } + + variance /= tile_count; + + imageStore(tile_variance, uvi, vec4(1 - variance)); +} \ No newline at end of file diff --git a/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_variance.glsl.import b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_variance.glsl.import new file mode 100644 index 0000000..f2f84e2 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_variance.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://ddo60n85uqwbk" +path="res://.godot/imported/mcguire_tile_variance.glsl-2a5a77e5f43c4a3d379a9c7c55e12bf6.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_variance.glsl" +dest_files=["res://.godot/imported/mcguire_tile_variance.glsl-2a5a77e5f43c4a3d379a9c7c55e12bf6.res"] + +[params] + diff --git a/addons/SphynxMotionBlurToolkit/McGuire/mcguire_blur_stage.tres b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_blur_stage.tres new file mode 100644 index 0000000..4bae310 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_blur_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://cp5pmuoa15e5g"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_16plp"] +[ext_resource type="RDShaderFile" uid="uid://7fjex8wuiejk" path="res://addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_blur.glsl" id="2_nk2ao"] + +[resource] +script = ExtResource("1_16plp") +shader_file = ExtResource("2_nk2ao") diff --git a/addons/SphynxMotionBlurToolkit/McGuire/mcguire_motion_blur.gd b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_motion_blur.gd new file mode 100644 index 0000000..75b3501 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_motion_blur.gd @@ -0,0 +1,249 @@ +extends MotionBlurCompositorEffect +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 var blur_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/McGuire/mcguire_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/McGuire/mcguire_overlay_stage.tres"): + set(value): + unsubscribe_shader_stage(overlay_stage) + overlay_stage = value + subscirbe_shader_stage(value) + +@export var tile_max_x_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/McGuire/mcguire_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/McGuire/mcguire_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 neighbor_max_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/McGuire/mcguire_neighbor_max_stage.tres"): + set(value): + unsubscribe_shader_stage(neighbor_max_stage) + neighbor_max_stage = value + subscirbe_shader_stage(value) + +@export var tile_variance_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/McGuire/mcguire_tile_variance_stage.tres"): + set(value): + unsubscribe_shader_stage(tile_variance_stage) + 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" + +var tile_max : StringName = "tile_max" + +var neighbor_max : StringName = "neighbor_max" + +var tile_variance : StringName = "tile_variance" + +var past_color : StringName = "past_color" + +var custom_velocity : StringName = "custom_velocity" + +var freeze : bool = false + +func _get_max_dilation_range() -> float: + return tile_size; + +func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSceneBuffersRD, render_scene_data : RenderSceneDataRD): + ensure_texture(tile_max_x, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / tile_size, 1.)) + ensure_texture(tile_max, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / tile_size, 1. / tile_size)) + ensure_texture(neighbor_max, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / tile_size, 1. / tile_size)) + ensure_texture(tile_variance, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / tile_size, 1. / tile_size)) + ensure_texture(past_color, render_scene_buffers) + ensure_texture(custom_velocity, render_scene_buffers) + ensure_texture(output_color, render_scene_buffers) + + rd.draw_command_begin_label("Motion Blur", Color(1.0, 1.0, 1.0, 1.0)) + + var tile_max_x_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_tile_max_x_push_constants : PackedInt32Array = [ + tile_size, + 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 = [ + tile_size, + 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 tile_variance_push_constants: PackedFloat32Array = [ + 0, + 0, + 0, + 0 + ] + var int_tile_variance_push_constants : PackedInt32Array = [ + 0, + 0, + 0, + 0 + ] + var tile_variance_push_constants_byte_array = tile_variance_push_constants.to_byte_array() + 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, + ] + var int_blur_push_constants : PackedInt32Array = [ + tile_size, + motion_blur_samples, + Engine.get_frames_drawn() % 8, + 0 + ] + var blur_push_constants_byte_array = blur_push_constants.to_byte_array() + blur_push_constants_byte_array.append_array(int_blur_push_constants.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 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 tile_variance_image := render_scene_buffers.get_texture_slice(context, tile_variance, view, 0, 1, 1) + var past_color_image := render_scene_buffers.get_texture_slice(context, past_color, view, 0, 1, 1) + var custom_velocity_image := render_scene_buffers.get_texture_slice(context, custom_velocity, 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) + + 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 / tile_size - 1) / 16 + 1) + y_groups = floori((render_size.y / tile_size - 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) + + dispatch_stage(neighbor_max_stage, + [ + get_sampler_uniform(tile_max_image, 0, false), + get_image_uniform(neighbor_max_image, 1) + ], + neighbor_max_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "NeighborMax", + view) + + dispatch_stage(tile_variance_stage, + [ + get_sampler_uniform(tile_max_image, 0, false), + get_image_uniform(tile_variance_image, 1) + ], + tile_variance_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "TileVariance", + 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_sampler_uniform(tile_variance_image, 4, true), + get_image_uniform(output_color_image, 5), + get_image_uniform(past_color_image, 6) + ], + blur_push_constants_byte_array, + Vector3i(x_groups, y_groups, 1), + "Blur", + view) + + dispatch_stage(overlay_stage, + [ + get_sampler_uniform(output_color_image, 0, false), + 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/McGuire/mcguire_neighbor_max_stage.tres b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_neighbor_max_stage.tres new file mode 100644 index 0000000..126d347 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_neighbor_max_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://bk8tn7n5k0b1r"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_6n3p7"] +[ext_resource type="RDShaderFile" uid="uid://byfogr1qtbafi" path="res://addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_neighbor_max.glsl" id="2_ig0yf"] + +[resource] +script = ExtResource("1_6n3p7") +shader_file = ExtResource("2_ig0yf") diff --git a/addons/SphynxMotionBlurToolkit/McGuire/mcguire_overlay_stage.tres b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_overlay_stage.tres new file mode 100644 index 0000000..681c723 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_overlay_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://chg1vh0sap86j"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_rpgp3"] +[ext_resource type="RDShaderFile" uid="uid://ylkrbqh7unvl" path="res://addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_overlay.glsl" id="2_sx8p0"] + +[resource] +script = ExtResource("1_rpgp3") +shader_file = ExtResource("2_sx8p0") diff --git a/addons/SphynxMotionBlurToolkit/McGuire/mcguire_tile_max_x_stage.tres b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_tile_max_x_stage.tres new file mode 100644 index 0000000..a93d0ef --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_tile_max_x_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://kgrk5sdoor7t"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_50cqr"] +[ext_resource type="RDShaderFile" uid="uid://bp5jl5351ph2d" path="res://addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_x.glsl" id="2_m4c7y"] + +[resource] +script = ExtResource("1_50cqr") +shader_file = ExtResource("2_m4c7y") diff --git a/addons/SphynxMotionBlurToolkit/McGuire/mcguire_tile_max_y_stage.tres b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_tile_max_y_stage.tres new file mode 100644 index 0000000..14bea9e --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_tile_max_y_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://d2rdmkpi41wf1"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_4imrj"] +[ext_resource type="RDShaderFile" uid="uid://deow8m5u2ji84" path="res://addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_max_y.glsl" id="2_8ewid"] + +[resource] +script = ExtResource("1_4imrj") +shader_file = ExtResource("2_8ewid") diff --git a/addons/SphynxMotionBlurToolkit/McGuire/mcguire_tile_variance_stage.tres b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_tile_variance_stage.tres new file mode 100644 index 0000000..d578417 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/McGuire/mcguire_tile_variance_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://d1ckx52l74p0"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_bipj1"] +[ext_resource type="RDShaderFile" uid="uid://ddo60n85uqwbk" path="res://addons/SphynxMotionBlurToolkit/McGuire/ShaderFiles/mcguire_tile_variance.glsl" id="2_5lusy"] + +[resource] +script = ExtResource("1_bipj1") +shader_file = ExtResource("2_5lusy") diff --git a/addons/PreBlurProcessing/blur_velocity_component_resource.gd b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/blur_velocity_component_resource.gd similarity index 100% rename from addons/PreBlurProcessing/blur_velocity_component_resource.gd rename to addons/SphynxMotionBlurToolkit/PreBlurProcessing/blur_velocity_component_resource.gd diff --git a/addons/PreBlurProcessing/default_component.tres b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_component.tres similarity index 61% rename from addons/PreBlurProcessing/default_component.tres rename to addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_component.tres index 52d60d2..25bcaa1 100644 --- a/addons/PreBlurProcessing/default_component.tres +++ b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_component.tres @@ -1,6 +1,6 @@ [gd_resource type="Resource" script_class="BlurVelocityComponentResource" load_steps=2 format=3 uid="uid://rp3mpjmisoyh"] -[ext_resource type="Script" path="res://addons/PreBlurProcessing/blur_velocity_component_resource.gd" id="1_ijikr"] +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/blur_velocity_component_resource.gd" id="1_ijikr"] [resource] script = ExtResource("1_ijikr") diff --git a/addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processing_stage.tres b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processing_stage.tres new file mode 100644 index 0000000..31ceb1a --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processing_stage.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://c8ulad7utgrg7"] + +[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_8hijg"] +[ext_resource type="RDShaderFile" uid="uid://ojudxyx6f4rx" path="res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processor.glsl" id="2_w54vd"] + +[resource] +script = ExtResource("1_8hijg") +shader_file = ExtResource("2_w54vd") diff --git a/addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processor.gd b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processor.gd new file mode 100644 index 0000000..21757ee --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processor.gd @@ -0,0 +1,75 @@ +extends EnhancedCompositorEffect +class_name PreBlurProcessor + + +@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") + +var custom_velocity : StringName = "custom_velocity" + +func _init(): + needs_motion_vectors = true + set_deferred("context", "MotionBlur") + super() + +func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSceneBuffersRD, render_scene_data : RenderSceneDataRD): + ensure_texture(custom_velocity, render_scene_buffers) + + rd.draw_command_begin_label("Pre Blur Processing", Color(1.0, 1.0, 1.0, 1.0)) + + var float_pre_blur_push_constants: PackedFloat32Array = [ + camera_rotation_component.multiplier, + camera_movement_component.multiplier, + object_movement_component.multiplier, + camera_rotation_component.lower_threshold, + camera_movement_component.lower_threshold, + object_movement_component.lower_threshold, + camera_rotation_component.upper_threshold, + camera_movement_component.upper_threshold, + object_movement_component.upper_threshold, + 1 if true else 0, + 0, + 0, + ] + + var int_pre_blur_push_constants : PackedInt32Array = [ + ] + + var byte_array = float_pre_blur_push_constants.to_byte_array() + byte_array.append_array(int_pre_blur_push_constants.to_byte_array()) + + var view_count = render_scene_buffers.get_view_count() + + for view in range(view_count): + var depth_image := render_scene_buffers.get_depth_layer(view) + var velocity_image := render_scene_buffers.get_velocity_layer(view) + var custom_velocity_image := render_scene_buffers.get_texture_slice(context, custom_velocity, view, 0, 1, 1) + var scene_data_buffer : RID = render_scene_data.get_uniform_buffer() + var scene_data_buffer_uniform := RDUniform.new() + scene_data_buffer_uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_UNIFORM_BUFFER + scene_data_buffer_uniform.binding = 5 + scene_data_buffer_uniform.add_id(scene_data_buffer) + + var x_groups := floori((render_size.x - 1) / 16 + 1) + var y_groups := floori((render_size.y - 1) / 16 + 1) + + dispatch_stage(pre_blur_processor_stage, + [ + get_sampler_uniform(depth_image, 0, false), + get_sampler_uniform(velocity_image, 1, false), + get_image_uniform(custom_velocity_image, 2), + scene_data_buffer_uniform + ], + byte_array, + Vector3i(x_groups, y_groups, 1), + "Process Velocity Buffer", + view) + + rd.draw_command_end_label() diff --git a/addons/PreBlurProcessing/pre_blur_processor.glsl b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processor.glsl similarity index 99% rename from addons/PreBlurProcessing/pre_blur_processor.glsl rename to addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processor.glsl index d4917f3..c306d26 100644 --- a/addons/PreBlurProcessing/pre_blur_processor.glsl +++ b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processor.glsl @@ -175,7 +175,7 @@ void main() + camera_movement_uv_change * params.movement_velocity_multiplier * sharp_step(params.movement_velocity_lower_threshold, params.movement_velocity_upper_threshold, length(camera_movement_uv_change)) + object_uv_change * params.object_velocity_multilpier * sharp_step(params.object_velocity_lower_threshold, params.object_velocity_upper_threshold, length(object_uv_change)); // if objects move, clear z direction, (z only correct for static environment) - if(dot(object_uv_change, object_uv_change) > 0.000001) + if(dot(object_uv_change.xy, object_uv_change.xy) > 0.000001) { total_velocity.z = 0; base_velocity.z = 0; diff --git a/addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processor.glsl.import b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processor.glsl.import new file mode 100644 index 0000000..eff1188 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processor.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://ojudxyx6f4rx" +path="res://.godot/imported/pre_blur_processor.glsl-1e488552a0780ca6b7db6c45f5370f53.res" + +[deps] + +source_file="res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processor.glsl" +dest_files=["res://.godot/imported/pre_blur_processor.glsl-1e488552a0780ca6b7db6c45f5370f53.res"] + +[params] + diff --git a/addons/RadialBlurTest/radial_blur_mesh.gd b/addons/SphynxMotionBlurToolkit/RadialBlurToolkit/radial_blur_mesh.gd similarity index 100% rename from addons/RadialBlurTest/radial_blur_mesh.gd rename to addons/SphynxMotionBlurToolkit/RadialBlurToolkit/radial_blur_mesh.gd diff --git a/addons/RadialBlurTest/radial_blur_mesh.gdshader b/addons/SphynxMotionBlurToolkit/RadialBlurToolkit/radial_blur_mesh.gdshader similarity index 100% rename from addons/RadialBlurTest/radial_blur_mesh.gdshader rename to addons/SphynxMotionBlurToolkit/RadialBlurToolkit/radial_blur_mesh.gdshader diff --git a/addons/RadialBlurTest/radial_blur_mesh.tscn b/addons/SphynxMotionBlurToolkit/RadialBlurToolkit/radial_blur_mesh.tscn similarity index 79% rename from addons/RadialBlurTest/radial_blur_mesh.tscn rename to addons/SphynxMotionBlurToolkit/RadialBlurToolkit/radial_blur_mesh.tscn index a75bffe..6e396b9 100644 --- a/addons/RadialBlurTest/radial_blur_mesh.tscn +++ b/addons/SphynxMotionBlurToolkit/RadialBlurToolkit/radial_blur_mesh.tscn @@ -1,15 +1,16 @@ -[gd_scene load_steps=5 format=3 uid="uid://b0shum42bqq0y"] +[gd_scene load_steps=5 format=3 uid="uid://8p6li7o742g3"] -[ext_resource type="Shader" path="res://RadialBlurTest/radial_blur_mesh.gdshader" id="1_20eg7"] -[ext_resource type="Script" path="res://RadialBlurTest/radial_blur_mesh.gd" id="2_wbael"] +[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"] [sub_resource type="CylinderMesh" id="CylinderMesh_pgvyt"] +resource_local_to_scene = true height = 0.25 [sub_resource type="ShaderMaterial" id="ShaderMaterial_stapv"] resource_local_to_scene = true render_priority = 0 -shader = ExtResource("1_20eg7") +shader = ExtResource("1_36vys") shader_parameter/local_rotation_axis = Vector3(0, 1, 0) shader_parameter/rotation_speed = 0.0 shader_parameter/sample_count = 8 @@ -23,4 +24,4 @@ shader_parameter/debug_color = Color(1, 0, 0, 0) process_priority = 1 mesh = SubResource("CylinderMesh_pgvyt") surface_material_override/0 = SubResource("ShaderMaterial_stapv") -script = ExtResource("2_wbael") +script = ExtResource("2_cfhks") diff --git a/addons/SphynxMotionBlurToolkit/SphynxMotionBlurToolkit.gd b/addons/SphynxMotionBlurToolkit/SphynxMotionBlurToolkit.gd new file mode 100644 index 0000000..aa1b8e0 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/SphynxMotionBlurToolkit.gd @@ -0,0 +1,12 @@ +@tool +extends EditorPlugin + + +func _enter_tree() -> void: + # Initialization of the plugin goes here. + pass + + +func _exit_tree() -> void: + # Clean-up of the plugin goes here. + pass diff --git a/addons/SphynxMotionBlurToolkit/plugin.cfg b/addons/SphynxMotionBlurToolkit/plugin.cfg new file mode 100644 index 0000000..bf53cf0 --- /dev/null +++ b/addons/SphynxMotionBlurToolkit/plugin.cfg @@ -0,0 +1,7 @@ +[plugin] + +name="SphynxMotionBlurToolkit" +description="A toolkit containinp multiple motion blur implementations, as well as debug stages, and radial blur toolkit for propellers and wheels" +author="Sphynx" +version="4.3" +script="SphynxMotionBlurToolkit.gd"