Multiple fixes, Higher blur Quality

- better blending
- handle velocity buffer projection edge case
- handle blur edge cases
This commit is contained in:
sphynx-owner
2024-08-14 23:10:32 +03:00
parent d1c3b2e4c0
commit 260e5ec88a
45 changed files with 1954 additions and 434 deletions

View File

@ -1,5 +1,4 @@
extends CompositorEffect
class_name EnhancedCompositorEffect
var rd: RenderingDevice
@ -11,6 +10,26 @@ var context: StringName = "PostProcess"
var all_shader_stages : Dictionary
@export var debug : bool = false:
set(value):
if(debug == value):
return
debug = value
free_shaders.call_deferred()
generate_shaders.call_deferred()
var debug_1 : String = "debug_1"
var debug_2 : String = "debug_2"
var debug_3 : String = "debug_3"
var debug_4 : String = "debug_4"
var debug_5 : String = "debug_5"
var debug_6 : String = "debug_6"
var debug_7 : String = "debug_7"
var debug_8 : String = "debug_8"
var all_debug_images : Array[RID]
func _init():
RenderingServer.call_on_render_thread(_initialize_compute)
@ -28,6 +47,18 @@ func _notification(what):
if shader_stage.shader.is_valid():
rd.free_rid(shader_stage.shader)
func free_shaders():
for shader_stage in all_shader_stages.keys():
if shader_stage.pipeline.is_valid():
rd.free_rid(shader_stage.pipeline)
if shader_stage.shader.is_valid():
rd.free_rid(shader_stage.shader)
func generate_shaders():
for shader_stage in all_shader_stages.keys():
generate_shader_stage(shader_stage)
func subscirbe_shader_stage(shader_stage : ShaderStageResource):
if all_shader_stages.has(shader_stage):
return
@ -70,11 +101,35 @@ func _initialize_compute():
nearest_sampler = rd.sampler_create(sampler_state)
for shader_stage in all_shader_stages.keys():
generate_shader_stage(shader_stage)
generate_shaders()
func generate_shader_stage(shader_stage : ShaderStageResource):
var shader_spirv : RDShaderSPIRV = shader_stage.shader_file.get_spirv()
var shader_spirv : RDShaderSPIRV
if debug:
var file = FileAccess.open(shader_stage.shader_file.resource_path, FileAccess.READ)
var split_shader : PackedStringArray = file.get_as_text().split("#[compute]", true, 1)
var content : String = split_shader[min(1, split_shader.size() - 1)]
var all_split_parts : PackedStringArray = content.split("#version 450", true, 1)
content = str(all_split_parts[0],
"#version 450
#define DEBUG
layout(rgba16f, set = 0, binding = 10) uniform image2D debug_1_image;
layout(rgba16f, set = 0, binding = 11) uniform image2D debug_2_image;
layout(rgba16f, set = 0, binding = 12) uniform image2D debug_3_image;
layout(rgba16f, set = 0, binding = 13) uniform image2D debug_4_image;
layout(rgba16f, set = 0, binding = 14) uniform image2D debug_5_image;
layout(rgba16f, set = 0, binding = 15) uniform image2D debug_6_image;
layout(rgba16f, set = 0, binding = 16) uniform image2D debug_7_image;
layout(rgba16f, set = 0, binding = 17) uniform image2D debug_8_image;",
all_split_parts[1])
var shader_source : RDShaderSource = RDShaderSource.new()
shader_source.set_stage_source(RenderingDevice.SHADER_STAGE_COMPUTE, content)
shader_spirv = rd.shader_compile_spirv_from_source(shader_source, false)
print(content)
else:
shader_spirv = shader_stage.shader_file.get_spirv()
shader_stage.shader = rd.shader_create_from_spirv(shader_spirv)
shader_stage.pipeline = rd.compute_pipeline_create(shader_stage.shader)
@ -91,9 +146,32 @@ func _render_callback(p_effect_callback_type, p_render_data):
if render_size.x == 0 or render_size.y == 0:
return
if debug:
ensure_texture(debug_1, render_scene_buffers)
ensure_texture(debug_2, render_scene_buffers)
ensure_texture(debug_3, render_scene_buffers)
ensure_texture(debug_4, render_scene_buffers)
ensure_texture(debug_5, render_scene_buffers)
ensure_texture(debug_6, render_scene_buffers)
ensure_texture(debug_7, render_scene_buffers)
ensure_texture(debug_8, render_scene_buffers)
var view_count = render_scene_buffers.get_view_count()
for view in range(view_count):
all_debug_images.append(render_scene_buffers.get_texture_slice(context, debug_1, view, 0, 1, 1))
all_debug_images.append(render_scene_buffers.get_texture_slice(context, debug_2, view, 0, 1, 1))
all_debug_images.append(render_scene_buffers.get_texture_slice(context, debug_3, view, 0, 1, 1))
all_debug_images.append(render_scene_buffers.get_texture_slice(context, debug_4, view, 0, 1, 1))
all_debug_images.append(render_scene_buffers.get_texture_slice(context, debug_5, view, 0, 1, 1))
all_debug_images.append(render_scene_buffers.get_texture_slice(context, debug_6, view, 0, 1, 1))
all_debug_images.append(render_scene_buffers.get_texture_slice(context, debug_7, view, 0, 1, 1))
all_debug_images.append(render_scene_buffers.get_texture_slice(context, debug_8, view, 0, 1, 1))
_render_callback_2(render_size, render_scene_buffers, render_scene_data)
all_debug_images.clear()
func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSceneBuffersRD, render_scene_data : RenderSceneDataRD):
pass
@ -128,6 +206,11 @@ func get_sampler_uniform(image: RID, binding: int, linear : bool = true) -> RDUn
func dispatch_stage(stage : ShaderStageResource, uniforms : Array[RDUniform], push_constants : PackedByteArray, dispatch_size : Vector3i, label : String = "DefaultLabel", view : int = 0, color : Color = Color(1, 1, 1, 1)):
rd.draw_command_begin_label(label + " " + str(view), color)
if debug:
for i in 8:
var debug_image_index = i + view * 8;
uniforms.append(get_image_uniform(all_debug_images[debug_image_index], 10 + i))
var tex_uniform_set = UniformSetCacheRD.get_cache(stage.shader, 0, uniforms)
var compute_list = rd.compute_list_begin()

View File

@ -1,5 +1,27 @@
extends EnhancedCompositorEffect
class_name MotionBlurCompositorEffect
extends "res://addons/SphynxMotionBlurToolkit/BaseClasses/enhanced_compositor_effect.gd"
@export_group("Motion Blur")
# diminishing returns over 16
@export_range(4, 64) var samples: int = 16
# you really don't want this over 0.5, but you can if you want to try
@export_range(0, 0.5, 0.001, "or_greater") var intensity: float = 1
@export_range(0, 1) var center_fade: float = 0.0
## wether this motion blur stays the same intensity below
## target_constant_framerate
@export var framerate_independent : bool = true
## Description: Removes clamping on motion blur scale to allow framerate independent motion
## blur to scale longer than realistically possible when render framerate is higher
## than target framerate.[br][br]
## [color=yellow]Warning:[/color] Turning this on would allow over-blurring of pixels, which
## produces inaccurate results, and would likely cause nausea in players over
## long exposure durations, use with caution and out of artistic intent
@export var uncapped_independence : bool = false
## if framerate_independent is enabled, the blur would simulate
## sutter speeds at that framerate, and up.
@export var target_constant_framerate : float = 30
func _init():
set_deferred("context", "MotionBlur")

View File

@ -9,14 +9,6 @@
layout(rgba16f, set = 0, binding = 0) uniform image2D past_color_image;
layout(rgba16f, set = 0, binding = 1) uniform image2D output_color_image;
layout(set = 0, binding = 2) uniform sampler2D color_sampler;
layout(set = 0, binding = 3) uniform sampler2D debug_sampler_1;
layout(set = 0, binding = 4) uniform sampler2D debug_sampler_2;
layout(set = 0, binding = 5) uniform sampler2D debug_sampler_3;
layout(set = 0, binding = 6) uniform sampler2D debug_sampler_4;
layout(set = 0, binding = 7) uniform sampler2D debug_sampler_5;
layout(set = 0, binding = 8) uniform sampler2D debug_sampler_6;
layout(set = 0, binding = 9) uniform sampler2D debug_sampler_7;
layout(set = 0, binding = 10) uniform sampler2D debug_sampler_8;
layout(push_constant, std430) uniform Params
{
@ -66,22 +58,24 @@ void main()
vec4 bl_col;
vec4 br_col;
#ifdef DEBUG
if(params.debug_page == 0)
{
tl_col = textureLod(debug_sampler_1, uvn, 0.0);
tr_col = textureLod(debug_sampler_2, uvn, 0.0);
bl_col = textureLod(debug_sampler_3, uvn, 0.0);
br_col = textureLod(debug_sampler_4, uvn, 0.0);
tl_col = imageLoad(debug_1_image, uvi);
tr_col = imageLoad(debug_2_image, uvi);
bl_col = imageLoad(debug_3_image, uvi);
br_col = imageLoad(debug_4_image, uvi);
}
if(params.debug_page == 1)
{
tl_col = textureLod(debug_sampler_5, uvn, 0.0);
tr_col = textureLod(debug_sampler_6, uvn, 0.0);
bl_col = textureLod(debug_sampler_7, uvn, 0.0);
br_col = textureLod(debug_sampler_8, uvn, 0.0);
tl_col = imageLoad(debug_5_image, uvi);
tr_col = imageLoad(debug_6_image, uvi);
bl_col = imageLoad(debug_7_image, uvi);
br_col = imageLoad(debug_8_image, uvi);
}
#endif
imageStore(output_color_image, uvi / 2, tl_col);
imageStore(output_color_image, uvi / 2 + ivec2(vec2(0.5, 0.5) * render_size), br_col);
imageStore(output_color_image, uvi / 2 + ivec2(vec2(0.0, 0.5) * render_size), bl_col);

View File

@ -1,4 +1,4 @@
extends EnhancedCompositorEffect
extends "res://addons/SphynxMotionBlurToolkit/BaseClasses/enhanced_compositor_effect.gd"
class_name DebugCompositorEffect
@export var overlay_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/Debug/debug_overlay_shader_stage.tres"):
@ -15,21 +15,13 @@ class_name DebugCompositorEffect
## and depth buffers debug views
@export var debug_page : int = 0
@export var debug_1 : String = "debug_1"
@export var debug_2 : String = "debug_2"
@export var debug_3 : String = "debug_3"
@export var debug_4 : String = "debug_4"
@export var debug_5 : String = "debug_5"
@export var debug_6 : String = "debug_6"
@export var debug_7 : String = "debug_7"
@export var debug_8 : String = "debug_8"
var past_color : StringName = "past_color"
var freeze : bool = false
func _init():
set_deferred("context", "MotionBlur")
set_deferred("debug", true)
super()
func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSceneBuffersRD, render_scene_data : RenderSceneDataRD):

View File

@ -6,16 +6,11 @@
#define M_PI 3.1415926535897932384626433832795
layout(set = 0, binding = 0) uniform sampler2D color_sampler;
layout(set = 0, binding = 1) uniform sampler2D depth_sampler;
layout(set = 0, binding = 2) uniform sampler2D velocity_sampler;
layout(set = 0, binding = 3) uniform sampler2D neighbor_max;
layout(set = 0, binding = 4) uniform sampler2D tile_variance;
layout(rgba16f, set = 0, binding = 5) uniform writeonly image2D output_color;
layout(rgba16f, set = 0, binding = 6) uniform image2D past_color_image;
layout(rgba16f, set = 0, binding = 6) uniform image2D debug_1_image;
layout(rgba16f, set = 0, binding = 7) uniform image2D debug_2_image;
layout(rgba16f, set = 0, binding = 8) uniform image2D debug_3_image;
layout(rgba16f, set = 0, binding = 9) uniform image2D debug_4_image;
layout(set = 0, binding = 1) uniform sampler2D velocity_sampler;
layout(set = 0, binding = 2) uniform sampler2D neighbor_max;
layout(set = 0, binding = 3) uniform sampler2D tile_variance;
layout(rgba16f, set = 0, binding = 4) uniform writeonly image2D output_color;
layout(push_constant, std430) uniform Params
{
@ -53,7 +48,7 @@ float cylinder(float T, float v)
// ----------------------------------------------------------
float z_compare(float a, float b, float sze)
{
return clamp(1. - sze * (a - b) / min(a, b), 0, 1);
return clamp(1. - sze * (a - b), 0, 1);
}
// ----------------------------------------------------------
@ -73,7 +68,7 @@ float interleaved_gradient_noise(vec2 uv){
vec2 safenorm(vec2 v)
{
float l = max(length(v), 1e-6);
return v / l * int(1 >= 0.5);
return v / l * int(l >= 0.5);
}
vec2 jitter_tile(vec2 uvi)
@ -100,7 +95,9 @@ void main()
float j = interleaved_gradient_noise(uvi) * 2. - 1.;
vec2 vn = textureLod(neighbor_max, x + jitter_tile(uvi), 0.0).xy * render_size / 2.;
vec4 vnzw = textureLod(neighbor_max, x + jitter_tile(uvi), 0.0) * vec4(render_size / 2., 1, 1);
vec2 vn = vnzw.xy;
float vn_length = length(vn);
@ -109,16 +106,20 @@ void main()
if(vn_length < 0.5)
{
imageStore(output_color, uvi, base_color);
#ifdef DEBUG
imageStore(debug_1_image, uvi, base_color);
imageStore(debug_2_image, uvi, vec4(vn / render_size * 2, 0, 1));
imageStore(debug_3_image, uvi, vec4(0));
imageStore(debug_4_image, uvi, vec4(0));
#endif
return;
}
vec2 wn = safenorm(vn);
vec2 vx = textureLod(velocity_sampler, x, 0.0).xy * render_size / 2.;
vec4 vxzw = textureLod(velocity_sampler, x, 0.0) * vec4(render_size / 2., 1, 1);
vec2 vx = vxzw.xy;
float vx_length = max(0.5, length(vx));
@ -133,7 +134,7 @@ void main()
vec2 wc = safenorm(mix(wp, wx, clamp((vx_length - 0.5) / params.minimum_user_threshold, 0, 1)));
float zx = -0.05 / max(FLT_MIN, textureLod(depth_sampler, x, 0.0).x);
float zx = vxzw.w;
float total_weight = params.sample_count / (params.importance_bias * vx_length);
@ -145,6 +146,8 @@ void main()
vec2 d = ((i % 2) > 0) ? vx : vn;
float dz = ((i % 2) > 0) ? vxzw.z : vnzw.z;
vec2 wd = safenorm(d);
float T = abs(t * vn_length);
@ -153,14 +156,16 @@ void main()
float wa = dot(wc, wd);
vec2 vy = textureLod(velocity_sampler, y, 0.0).xy * render_size / 2;
vec4 vyzw = textureLod(velocity_sampler, y, 0.0) * vec4(render_size / 2, 1, 1);
vec2 vy = vyzw.xy - dz * t;
float vy_length = max(0.5, length(vy));
float zy = -0.05 / max(FLT_MIN, textureLod(depth_sampler, y, 0.0).x);
float zy = vyzw.w;
float f = z_compare(zy, zx, 15);
float b = z_compare(zx, zy, 15);
float f = z_compare(-zy, -zx, 20000);
float b = z_compare(-zx, -zy, 20000);
float wb = abs(dot(vy / vy_length, wd));
@ -177,8 +182,10 @@ void main()
sum /= total_weight;
imageStore(output_color, uvi, sum);
#ifdef DEBUG
imageStore(debug_1_image, uvi, sum);
imageStore(debug_2_image, uvi, vec4(vn / render_size * 2, 0, 1));
imageStore(debug_3_image, uvi, vec4(0));
imageStore(debug_4_image, uvi, vec4(0));
imageStore(debug_3_image, uvi, vnzw);
imageStore(debug_4_image, uvi, vxzw);
#endif
}

View File

@ -0,0 +1,12 @@
extends "res://addons/SphynxMotionBlurToolkit/BaseClasses/mb_compositor_effect.gd"
@export_group("Shader Parameters")
@export var tile_size : int = 40
@export var linear_falloff_slope : float = 1
@export var importance_bias : float = 40
@export var maximum_jitter_value : float = 0.95
@export var minimum_user_threshold : float = 1.5

View File

@ -1,13 +1,7 @@
extends MotionBlurCompositorEffect
extends "res://addons/SphynxMotionBlurToolkit/Guertin/base_guertin_motion_blur.gd"
class_name GuertinMotionBlur
@export_group("Motion Blur", "motion_blur_")
# diminishing returns over 16
@export_range(4, 64) var motion_blur_samples: int = 25
# you really don't want this over 0.5, but you can if you want to try
@export_range(0, 0.5, 0.001, "or_greater") var motion_blur_intensity: float = 1
@export_range(0, 1) var motion_blur_center_fade: float = 0.0
@export_group("Shader Stages")
@export var blur_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/Guertin/guertin_blur_stage.tres"):
set(value):
unsubscribe_shader_stage(blur_stage)
@ -44,16 +38,6 @@ class_name GuertinMotionBlur
tile_variance_stage = value
subscirbe_shader_stage(value)
@export var tile_size : int = 40
@export var linear_falloff_slope : float = 1
@export var importance_bias : float = 40
@export var maximum_jitter_value : float = 0.95
@export var minimum_user_threshold : float = 1.5
var output_color: StringName = "output_color"
var tile_max_x : StringName = "tile_max_x"
@ -66,11 +50,6 @@ var tile_variance : StringName = "tile_variance"
var custom_velocity : StringName = "custom_velocity"
var debug_1 : StringName = "debug_1"
var debug_2 : StringName = "debug_2"
var debug_3 : StringName = "debug_3"
var debug_4 : StringName = "debug_4"
var freeze : bool = false
func _get_max_dilation_range() -> float:
@ -83,10 +62,6 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce
ensure_texture(tile_variance, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / tile_size, 1. / tile_size))
ensure_texture(custom_velocity, render_scene_buffers)
ensure_texture(output_color, render_scene_buffers)
ensure_texture(debug_1, render_scene_buffers)
ensure_texture(debug_2, render_scene_buffers)
ensure_texture(debug_3, render_scene_buffers)
ensure_texture(debug_4, render_scene_buffers)
rd.draw_command_begin_label("Motion Blur", Color(1.0, 1.0, 1.0, 1.0))
@ -158,7 +133,7 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce
]
var int_blur_push_constants : PackedInt32Array = [
tile_size,
motion_blur_samples,
samples,
Engine.get_frames_drawn() % 8,
0
]
@ -176,10 +151,6 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce
var neighbor_max_image := render_scene_buffers.get_texture_slice(context, neighbor_max, view, 0, 1, 1)
var tile_variance_image := render_scene_buffers.get_texture_slice(context, tile_variance, view, 0, 1, 1)
var custom_velocity_image := render_scene_buffers.get_texture_slice(context, custom_velocity, view, 0, 1, 1)
var debug_1_image := render_scene_buffers.get_texture_slice(context, debug_1, view, 0, 1, 1)
var debug_2_image := render_scene_buffers.get_texture_slice(context, debug_2, view, 0, 1, 1)
var debug_3_image := render_scene_buffers.get_texture_slice(context, debug_3, view, 0, 1, 1)
var debug_4_image := render_scene_buffers.get_texture_slice(context, debug_4, view, 0, 1, 1)
var x_groups := floori((render_size.x / tile_size - 1) / 16 + 1)
var y_groups := floori((render_size.y - 1) / 16 + 1)
@ -234,15 +205,10 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce
dispatch_stage(blur_stage,
[
get_sampler_uniform(color_image, 0, false),
get_sampler_uniform(depth_image, 1, false),
get_sampler_uniform(custom_velocity_image, 2, false),
get_sampler_uniform(neighbor_max_image, 3, false),
get_sampler_uniform(tile_variance_image, 4, true),
get_image_uniform(output_color_image, 5),
get_image_uniform(debug_1_image, 6),
get_image_uniform(debug_2_image, 7),
get_image_uniform(debug_3_image, 8),
get_image_uniform(debug_4_image, 9)
get_sampler_uniform(custom_velocity_image, 1, false),
get_sampler_uniform(neighbor_max_image, 2, false),
get_sampler_uniform(tile_variance_image, 3, true),
get_image_uniform(output_color_image, 4),
],
blur_push_constants_byte_array,
Vector3i(x_groups, y_groups, 1),

View File

@ -5,8 +5,7 @@
#define FLT_MIN 1.175494351e-38
layout(set = 0, binding = 0) uniform sampler2D velocity_sampler;
layout(set = 0, binding = 1) uniform sampler2D depth_sampler;
layout(rgba16f, set = 0, binding = 2) uniform writeonly image2D tile_max_x;
layout(rgba16f, set = 0, binding = 1) uniform writeonly image2D tile_max_x;
layout(push_constant, std430) uniform Params
{
@ -40,16 +39,22 @@ void main()
vec4 max_velocity = vec4(0);
float max_velocity_length = -1;
//bool foreground = false;
for(int i = 0; i < tile_size; i++)
{
vec2 current_uv = uvn + vec2(float(i) / render_size.x, 0);
vec3 velocity_sample = textureLod(velocity_sampler, current_uv, 0.0).xyz;
vec4 velocity_sample = textureLod(velocity_sampler, current_uv, 0.0);
float current_velocity_length = dot(velocity_sample.xy, velocity_sample.xy);
if(current_velocity_length > max_velocity_length)
if(current_velocity_length > max_velocity_length)// || (velocity_sample.w > 0 && !foreground))
{
max_velocity_length = current_velocity_length;
max_velocity = vec4(velocity_sample, textureLod(depth_sampler, current_uv, 0.0).x);
max_velocity = vec4(velocity_sample);
// if(velocity_sample.w > 0)
// {
// foreground = true;
// }
}
}
imageStore(tile_max_x, uvi, max_velocity);

View File

@ -40,15 +40,21 @@ void main()
float max_velocity_length = -1;
//bool foreground = false;
for(int i = 0; i < tile_size; i++)
{
vec2 current_uv = uvn + vec2(0, float(i) / render_size.y);
vec4 velocity_sample = textureLod(tile_max_x, current_uv, 0.0);
float current_velocity_length = dot(velocity_sample.xy, velocity_sample.xy);
if(current_velocity_length > max_velocity_length)
if(current_velocity_length > max_velocity_length)// || (velocity_sample.w > 0 && !foreground))
{
max_velocity_length = current_velocity_length;
max_velocity = velocity_sample;
max_velocity = vec4(velocity_sample);
// if(velocity_sample.w > 0)
// {
// foreground = true;
// }
}
}
imageStore(tile_max, uvi, max_velocity);

View File

@ -0,0 +1,63 @@
#[compute]
#version 450
#define FLT_MAX 3.402823466e+38
#define FLT_MIN 1.175494351e-38
layout(set = 0, binding = 0) uniform sampler2D tile_max;
layout(set = 0, binding = 1) uniform sampler2D tile_max_map;
layout(rgba16f, set = 0, binding = 2) uniform writeonly image2D neighbor_max;
layout(push_constant, std430) uniform Params
{
float nan5;
float nan6;
float nan7;
float nan8;
int nan1;
int nan2;
int nan3;
int nan4;
} params;
layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
void main()
{
ivec2 render_size = ivec2(textureSize(tile_max, 0));
ivec2 uvi = ivec2(gl_GlobalInvocationID.xy);
if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y))
{
return;
}
vec2 uvn = (vec2(uvi) + vec2(0.5)) / render_size;
vec2 max_neighbor_velocity = vec2(0);
float max_neighbor_depth = -1;
for(int i = -1; i < 2; i++)
{
for(int j = -1; j < 2; j++)
{
vec2 current_offset = vec2(1) / vec2(render_size) * vec2(i, j);
vec2 current_uv = uvn + current_offset;
if(current_uv.x < 0 || current_uv.x > 1 || current_uv.y < 0 || current_uv.y > 1)
{
continue;
}
vec3 current_neighbor_sample = textureLod(tile_max_map, current_uv, 0.0).xyz;
if(current_neighbor_sample.z > max_neighbor_depth)
{
max_neighbor_depth = current_neighbor_sample.z;
max_neighbor_velocity = current_neighbor_sample.xy;
}
}
}
imageStore(neighbor_max, uvi, vec4(max_neighbor_velocity, 0, 1));
}

View File

@ -0,0 +1,14 @@
[remap]
importer="glsl"
type="RDShaderFile"
uid="uid://bcivntgn7ipwo"
path="res://.godot/imported/jf_neighbor_depth_max.glsl-412337591574185d763ac95625cd98ac.res"
[deps]
source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jf_neighbor_depth_max.glsl"
dest_files=["res://.godot/imported/jf_neighbor_depth_max.glsl-412337591574185d763ac95625cd98ac.res"]
[params]

View File

@ -34,7 +34,7 @@ void main()
vec2 uvn = (vec2(uvi) + vec2(0.5)) / render_size;
vec2 max_neighbor_velocity = vec2(0);
vec2 best_sample_uv = vec2(uvn);
float max_neighbor_velocity_length = -1;
@ -49,20 +49,19 @@ void main()
continue;
}
bool is_diagonal = (abs(i) + abs(j) == 2);
vec2 velocity_map_sample = textureLod(tile_max_map, current_uv, 0.0).xy;
vec2 current_neighbor_sample = textureLod(tile_max_map, current_uv, 0.0).xy;
vec4 velocity_sample = textureLod(tile_max, velocity_map_sample, 0.0);
vec2 current_neighbor_velocity = textureLod(tile_max, current_neighbor_sample, 0.0).xy;
float current_neighbor_velocity_length = dot(current_neighbor_velocity, current_neighbor_velocity);
if(current_neighbor_velocity_length > max_neighbor_velocity_length)
float current_velocity_length = dot(velocity_sample.xy, velocity_sample.xy);
if(current_velocity_length > max_neighbor_velocity_length)
{
max_neighbor_velocity_length = current_neighbor_velocity_length;
max_neighbor_velocity = current_neighbor_sample;
max_neighbor_velocity_length = current_velocity_length;
best_sample_uv = velocity_map_sample;
}
}
}
imageStore(neighbor_max, uvi, vec4(max_neighbor_velocity, 0, 1));
imageStore(neighbor_max, uvi, vec4(best_sample_uv, 0, 1));
}

View File

@ -57,18 +57,6 @@ vec2 get_value(bool a, vec2 uv)
}
}
//vec4 get_value(bool a, ivec2 uvi)
//{
// if(a)
// {
// return imageLoad(buffer_a, uvi);
// }
// else
// {
// return imageLoad(buffer_b, uvi);
// }
//}
void set_value(bool a, ivec2 uvi, vec4 value)
{
if(a)
@ -81,48 +69,52 @@ void set_value(bool a, ivec2 uvi, vec4 value)
}
}
// Motion similarity
// ----------------------------------------------------------
float get_motion_difference(vec2 V, vec2 V2)
{
return clamp(dot(V - V2, V) / dot(V, V), 0, 1);
// vec2 VO = V - V2;
// float parallel = dot(VO, V) / dot(V, V);
// return clamp(parallel, 0, 1);
}
// ----------------------------------------------------------
void sample_fitness(vec2 uv_offset, vec4 uv_sample, vec2 render_size, inout vec4 current_sample_fitness)
{
vec2 sample_velocity = -uv_sample.xy;
// if velocity is 0, we never reach it (steps never smaller than 1)
if (dot(sample_velocity, sample_velocity) <= FLT_MIN || uv_sample.w == 0)
{
current_sample_fitness = vec4(FLT_MAX, FLT_MAX, FLT_MAX, -1);
current_sample_fitness = vec4(10, 10, 0, 0);
return;
}
// velocity space distance (projected pixel offset onto velocity vector)
float velocity_space_distance = dot(sample_velocity, uv_offset) / dot(sample_velocity, sample_velocity);
// the velcity space distance to gravitate the JFA to (found more relieable than doing a 0 - 1 range)
float mid_point = params.motion_blur_intensity / 2;
// centralize the velocity space distance around that mid point
float mid_point = params.motion_blur_intensity / 2 + 1e-5;
float absolute_velocity_space_distance = abs(velocity_space_distance - mid_point);
// if that distance is half the original, its within range (we centered around a mid point)
float within_velocity_range = step(absolute_velocity_space_distance, mid_point);
// perpendicular offset
float side_offset = abs(dot(vec2(uv_offset.y, -uv_offset.x), sample_velocity)) / dot(sample_velocity, sample_velocity);
// arbitrary perpendicular limit (lower means tighter dilation, but less reliable)
float within_perpen_error_range = step(side_offset, params.perpen_error_thresh * params.motion_blur_intensity);
// store relevant data for use in conditions
current_sample_fitness = vec4(absolute_velocity_space_distance, velocity_space_distance, uv_sample.w + uv_sample.z * velocity_space_distance, within_velocity_range * within_perpen_error_range);
current_sample_fitness = vec4(/*max(absolute_velocity_space_distance, side_offset)*/absolute_velocity_space_distance, velocity_space_distance, uv_sample.w + uv_sample.z * velocity_space_distance, within_velocity_range * within_perpen_error_range);
}
float is_sample_better(vec4 a, vec4 b)
{
// see explanation at end of code
return mix(1. - step(b.x * a.w, a.x * b.w), step(b.z, a.z), step(0.5, b.w) * step(0.5, a.w));//1. - step(a.x * a.w, b.x * b.w);//(a.x > b.x) ? 1 : 0;//1. - step(b.x * a.w, a.x * b.w);//
return 1. - step(b.x * a.w, a.x * b.w);//mix(1. - step(b.x * a.w, a.x * b.w), step(b.z, a.z), step(0.5, b.w) * step(0.5, a.w));
}
vec4 backtrack_sample(vec2 chosen_uv, vec4 best_sample_fitness)
{
vec4 velocity = textureLod(tile_max_sampler, chosen_uv, 0.0);
vec2 uv_candidate = chosen_uv + velocity.xy;
vec4 velocity_candidate = textureLod(tile_max_sampler, uv_candidate, 0.0);
if((dot(velocity, velocity_candidate) / dot(velocity, velocity)) > 0.5 && velocity_candidate.w > 0)
{
return vec4(uv_candidate, 0, 0);
}
else
{
return vec4(chosen_uv, 0, 0);
}
}
void main()
@ -134,12 +126,11 @@ void main()
return;
}
// must be on pixel center for whole values
vec2 uvn = (vec2(uvi) + vec2(0.5)) / render_size;
vec2 uv_step = vec2(round(params.step_size)) / render_size;
vec4 best_sample_fitness = vec4(FLT_MAX, FLT_MAX, FLT_MAX, 0);
vec4 best_sample_fitness = vec4(10, 10, 0, 0);
vec2 chosen_uv = uvn;
@ -174,19 +165,29 @@ void main()
sample_fitness(step_offset, uv_sample, render_size, current_sample_fitness);
if (is_sample_better(current_sample_fitness, best_sample_fitness) > 0.5)
{
best_sample_fitness = current_sample_fitness;
chosen_uv = check_uv;
}
float sample_better = 1. - step(best_sample_fitness.x * current_sample_fitness.w, current_sample_fitness.x * best_sample_fitness.w);
best_sample_fitness = mix(best_sample_fitness, current_sample_fitness, sample_better);
chosen_uv = mix(chosen_uv, check_uv, sample_better);
}
set_value(set_a, uvi, vec4(chosen_uv, 0, 0));
}
//
// if((a.w == b.w) && (a.w == 1))
// if(params.iteration_index < params.last_iteration_index)
// {
// return a.z < b.z ? 0. : 1.;
// set_value(set_a, uvi, vec4(chosen_uv, 0, 0));
// return;
// }
//
// float depth = textureLod(tile_max_sampler, uvn, 0.0).w;
//
// return a.x * b.w < b.x * a.w ? 1. : 0.;
// if(params.iteration_index == params.last_iteration_index && (best_sample_fitness.w < 0.5 || depth > best_sample_fitness.z))
// {
// set_value(set_a, uvi, vec4(uvn, 0, 0));
// return;
// }
set_value(set_a, uvi, vec4(chosen_uv, 0, 0));
// vec4 backtracked_sample = backtrack_sample(chosen_uv, best_sample_fitness);
//
// set_value(set_a, uvi, backtracked_sample);
}

View File

@ -11,14 +11,6 @@ layout(set = 0, binding = 1) uniform sampler2D depth_sampler;
layout(set = 0, binding = 2) uniform sampler2D vector_sampler;
layout(set = 0, binding = 3) uniform sampler2D velocity_map;
layout(rgba16f, set = 0, binding = 4) uniform writeonly image2D output_image;
layout(rgba16f, set = 0, binding = 5) uniform writeonly image2D debug_1_image;
layout(rgba16f, set = 0, binding = 6) uniform writeonly image2D debug_2_image;
layout(rgba16f, set = 0, binding = 7) uniform writeonly image2D debug_3_image;
layout(rgba16f, set = 0, binding = 8) uniform writeonly image2D debug_4_image;
layout(rgba16f, set = 0, binding = 9) uniform writeonly image2D debug_5_image;
layout(rgba16f, set = 0, binding = 10) uniform writeonly image2D debug_6_image;
layout(rgba16f, set = 0, binding = 11) uniform writeonly image2D debug_7_image;
layout(rgba16f, set = 0, binding = 12) uniform writeonly image2D debug_8_image;
layout(push_constant, std430) uniform Params
{

View File

@ -0,0 +1,45 @@
#[compute]
#version 450
layout(set = 0, binding = 0) uniform sampler2D velocity_sampler;
layout(set = 0, binding = 1) uniform sampler2D color_sampler;
layout(rgba16f, set = 0, binding = 2) uniform image2D past_velocity;
layout(rgba16f, set = 0, binding = 3) uniform image2D past_color;
// Guertin's functions https://research.nvidia.com/sites/default/files/pubs/2013-11_A-Fast-and/Guertin2013MotionBlur-small.pdf
// ----------------------------------------------------------
float z_compare(float a, float b, float sze)
{
return clamp(1. - sze * (a - b) / min(a, b), 0, 1);
}
// ----------------------------------------------------------
layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
void main()
{
ivec2 render_size = ivec2(textureSize(velocity_sampler, 0));
ivec2 uv = ivec2(gl_GlobalInvocationID.xy);
if ((uv.x >= render_size.x) || (uv.y >= render_size.y))
{
return;
}
vec2 x = (vec2(uv) + 0.5) / render_size;
vec4 past_vx = textureLod(velocity_sampler, x, 0.0);
vec4 past_vx_vx = textureLod(velocity_sampler, x + past_vx.xy, 0.0);
vec4 past_col_vx = textureLod(color_sampler, x + past_vx.xy, 0.0);
vec4 past_col_x = textureLod(color_sampler, x, 0.0);
float alpha = 1 - z_compare(past_vx_vx.w, past_vx.w, 15);
vec4 final_past_col = mix(past_col_vx, past_col_x, alpha);
vec4 final_past_vx = mix(past_vx_vx, past_vx, alpha);
imageStore(past_color, uv, final_past_col);
imageStore(past_velocity, uv, final_past_vx);
}

View File

@ -0,0 +1,14 @@
[remap]
importer="glsl"
type="RDShaderFile"
uid="uid://quuyr2q5w5kx"
path="res://.godot/imported/jump_flood_cache.glsl-f4eae7ab471d126e0587a3e727d847f6.res"
[deps]
source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_cache.glsl"
dest_files=["res://.godot/imported/jump_flood_cache.glsl-f4eae7ab471d126e0587a3e727d847f6.res"]
[params]

View File

@ -10,15 +10,9 @@ layout(set = 0, binding = 1) uniform sampler2D depth_sampler;
layout(set = 0, binding = 2) uniform sampler2D vector_sampler;
layout(set = 0, binding = 3) uniform sampler2D velocity_map;
layout(rgba16f, set = 0, binding = 4) uniform writeonly image2D output_image;
layout(rgba16f, set = 0, binding = 5) uniform writeonly image2D debug_1_image;
layout(rgba16f, set = 0, binding = 6) uniform writeonly image2D debug_2_image;
layout(rgba16f, set = 0, binding = 7) uniform writeonly image2D debug_3_image;
layout(rgba16f, set = 0, binding = 8) uniform writeonly image2D debug_4_image;
layout(rgba16f, set = 0, binding = 9) uniform writeonly image2D debug_5_image;
layout(rgba16f, set = 0, binding = 10) uniform writeonly image2D debug_6_image;
layout(rgba16f, set = 0, binding = 11) uniform writeonly image2D debug_7_image;
layout(rgba16f, set = 0, binding = 12) uniform writeonly image2D debug_8_image;
layout(set = 0, binding = 13) uniform sampler2D tile_max;
layout(set = 0, binding = 5) uniform sampler2D tile_max;
layout(set = 0, binding = 6) uniform sampler2D past_color_sampler;
layout(set = 0, binding = 7) uniform sampler2D past_velocity_sampler;
layout(push_constant, std430) uniform Params
{
@ -131,18 +125,33 @@ void main()
vec3 vxz = textureLod(vector_sampler, x, 0.0).xyz * vec3(render_size, 1);// * 2;
vec2 vx = vxz.xy;
vec3 past_vxz = textureLod(past_velocity_sampler, x, 0.0).xyz * vec3(render_size, 1);
vec2 past_vx = past_vxz.xy;
float velocity_match = pow(clamp(dot(vx, vn) / dot(vn, vn), 0, 1), 0.5);
vn = mix(vn, vx, velocity_match);
vnz = mix(vnz, vxz, velocity_match);
vec4 past_col_x = textureLod(past_color_sampler, x, 0.0);
if(vn_length <= 0.5)
{
imageStore(output_image, uvi, col_x);
#ifdef DEBUG
imageStore(debug_1_image, uvi, col_x);
imageStore(debug_2_image, uvi, abs(vec4(vn / render_size * 10, vnz.z * 100, 1)));
imageStore(debug_3_image, uvi, abs(vec4(velocity_map_sample - x, 0, 1)));
imageStore(debug_4_image, uvi, abs(vec4(vx / render_size * 10, vxz.z * 100, 1)));
imageStore(debug_5_image, uvi, 10 * abs(textureLod(tile_max, x, 0.0)));
imageStore(debug_6_image, uvi, 10 * abs(textureLod(tile_max, textureLod(velocity_map, x, 0.0).xy, 0.0)));
imageStore(debug_7_image, uvi, 10 * abs(textureLod(velocity_map, x, 0.0)));
imageStore(debug_8_image, uvi, abs(textureLod(velocity_map, x, 0.0) / 10));
imageStore(debug_5_image, uvi, col_x);
imageStore(debug_6_image, uvi, past_col_x);
imageStore(debug_7_image, uvi, past_col_x);
imageStore(debug_8_image, uvi, abs(vec4(past_vx / render_size * 10, past_vxz.z * 100, 1)));
#endif
return;
}
@ -191,6 +200,8 @@ void main()
float nai_dz = vxz.z;
vec2 past_nai_d = past_vx;
float dz = vnz.z;//sample_main_v ? vnz.z : vxz.z;
vec2 wd = safenorm(d);
@ -199,6 +210,8 @@ void main()
vec2 nai_y = x + (nai_d / render_size) * t;
vec2 past_nai_y = x + (past_nai_d / render_size) * t;
float nai_y_length = max(0.5, length(nai_y));
vec2 vy = textureLod(vector_sampler, y, 0.0).xy * render_size;// * 2;
@ -234,25 +247,27 @@ void main()
float nai_cone_y = cone(T, nai_vy_length);
float ay = max(f * wa * step(FLT_MIN, cone_y), b * wb * cone_x);
float ay_trail = f * wa * step(FLT_MIN, cone_y);
float ay_lead = (1 - f) * wb * step(FLT_MIN, cone_x);
float nai_ay = nai_b;
float nai_ay = nai_b;//max(nai_b, nai_f * nai_wa * step(FLT_MIN, nai_cone_y));
vec4 col_y = textureLod(color_sampler, y, 0.0);
vec4 past_col_y = textureLod(past_color_sampler, past_nai_y, 0.0);
vec4 nai_col_y = textureLod(color_sampler, nai_y, 0.0);
vec4 col_back = nai_col_y;
float back_weight = mix(0, 1, nai_ay);
total_back_weight += nai_ay;
total_back_weight += back_weight;
back_sum += col_back * nai_ay;
back_sum += col_back * back_weight;
weight += ay_trail + ay_lead;
weight += ay;
sum += col_y * ay;
sum += col_y * ay_trail + past_col_y * ay_lead;
}
back_sum *= (params.motion_blur_samples - weight) / total_back_weight;
@ -262,13 +277,15 @@ void main()
back_sum /= params.motion_blur_samples;
imageStore(output_image, uvi, sum + back_sum);
#ifdef DEBUG
imageStore(debug_1_image, uvi, sum + back_sum);
imageStore(debug_2_image, uvi, abs(vec4(vn / render_size * 10, vnz.z * 100, 1)));
imageStore(debug_3_image, uvi, abs(vec4(velocity_map_sample - x, 0, 1)));
imageStore(debug_4_image, uvi, abs(vec4(vx / render_size * 10, vxz.z * 100, 1)));
imageStore(debug_5_image, uvi, 10 * abs(textureLod(tile_max, x, 0.0)));
imageStore(debug_6_image, uvi, 10 * abs(textureLod(tile_max, textureLod(velocity_map, x, 0.0).xy, 0.0)));
imageStore(debug_7_image, uvi, 10 * abs(textureLod(velocity_map, x, 0.0)));
imageStore(debug_8_image, uvi, abs(textureLod(velocity_map, x, 0.0) / 10));
imageStore(debug_5_image, uvi, col_x);//sum + back_sum);
imageStore(debug_6_image, uvi, past_col_x);
imageStore(debug_7_image, uvi, past_col_x);
imageStore(debug_8_image, uvi, abs(vec4(past_vx / render_size * 10, past_vxz.z * 100, 1)));
#endif
}

View File

@ -0,0 +1,14 @@
[remap]
importer="glsl"
type="RDShaderFile"
uid="uid://bud4a7eh5sqr8"
path="res://.godot/imported/jump_flood_experimental_blur.glsl-27880bed814a937f2189c48828ca161e.res"
[deps]
source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_experimental_blur.glsl"
dest_files=["res://.godot/imported/jump_flood_experimental_blur.glsl-27880bed814a937f2189c48828ca161e.res"]
[params]

View File

@ -1,14 +0,0 @@
[remap]
importer="glsl"
type="RDShaderFile"
uid="uid://bdm5t4l1y3ts7"
path="res://.godot/imported/jump_flood_new_blur.glsl-ebfb8c41097767aad8ea133e2ff78878.res"
[deps]
source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_new_blur.glsl"
dest_files=["res://.godot/imported/jump_flood_new_blur.glsl-ebfb8c41097767aad8ea133e2ff78878.res"]
[params]

View File

@ -0,0 +1,292 @@
#[compute]
#version 450
#define FLT_MAX 3.402823466e+38
#define FLT_MIN 1.175494351e-38
#define M_PI 3.1415926535897932384626433832795
layout(set = 0, binding = 0) uniform sampler2D color_sampler;
layout(set = 0, binding = 1) uniform sampler2D depth_sampler;
layout(set = 0, binding = 2) uniform sampler2D velocity_sampler;
layout(set = 0, binding = 3) uniform sampler2D velocity_map;
layout(rgba16f, set = 0, binding = 4) uniform writeonly image2D output_image;
layout(set = 0, binding = 5) uniform sampler2D tile_max;
layout(push_constant, std430) uniform Params
{
float motion_blur_samples;
float motion_blur_intensity;
float motion_blur_center_fade;
float frame;
float last_iteration_index;
float sample_step_multiplier;
float step_exponent_modifier;
float max_dilation_radius;
int nan0;
int nan1;
int nan2;
int nan3;
} params;
layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
// McGuire's functions https://docs.google.com/document/d/1IIlAKTj-O01hcXEdGxTErQbCHO9iBmRx6oFUy_Jm0fI/edit
// ----------------------------------------------------------
float soft_depth_compare(float depth_X, float depth_Y, float sze)
{
return clamp(1 - (depth_X - depth_Y) / sze, 0, 1);
}
float cone(float T, float v)
{
return clamp(1 - T / v, 0, 1);
}
float cylinder(float T, float v)
{
return 1.0 - smoothstep(0.95 * v, 1.05 * v, T);
}
// ----------------------------------------------------------
// Guertin's functions https://research.nvidia.com/sites/default/files/pubs/2013-11_A-Fast-and/Guertin2013MotionBlur-small.pdf
// ----------------------------------------------------------
float z_compare(float a, float b, float sze)
{
return clamp(1. - sze * (a - b), 0, 1);
}
// ----------------------------------------------------------
// from https://www.shadertoy.com/view/ftKfzc
// ----------------------------------------------------------
float interleaved_gradient_noise(vec2 uv){
uv += float(params.frame) * (vec2(47, 17) * 0.695);
vec3 magic = vec3( 0.06711056, 0.00583715, 52.9829189 );
return fract(magic.z * fract(dot(uv, magic.xy)));
}
// ----------------------------------------------------------
// from https://github.com/bradparks/KinoMotion__unity_motion_blur/tree/master
// ----------------------------------------------------------
vec2 safenorm(vec2 v)
{
float l = max(length(v), 1e-6);
return v / l * int(l >= 0.5);
}
vec2 jitter_tile(vec2 uvi)
{
float rx, ry;
float angle = interleaved_gradient_noise(uvi + vec2(2, 0)) * M_PI * 2;
rx = cos(angle);
ry = sin(angle);
return vec2(rx, ry) / textureSize(tile_max, 0) / 4;
}
// ----------------------------------------------------------
void main()
{
ivec2 render_size = ivec2(textureSize(color_sampler, 0));
ivec2 uvi = ivec2(gl_GlobalInvocationID.xy);
if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y))
{
return;
}
vec2 x = (vec2(uvi) + vec2(0.5)) / vec2(render_size);
vec2 velocity_map_sample = textureLod(velocity_map, x + jitter_tile(uvi), 0.0).xy;
vec3 vnz = textureLod(tile_max, velocity_map_sample, 0.0).xyz * vec3(render_size, 1);
float vn_length = max(0.5, length(vnz.xy));
float multiplier = clamp(vn_length, 0, min(params.max_dilation_radius, vn_length * params.motion_blur_intensity)) / max(FLT_MIN, vn_length);
vnz.xyz *= multiplier;
vn_length *= multiplier;
vec2 vn = vnz.xy;
vec4 col_x = textureLod(color_sampler, x, 0.0);
vec2 wn = safenorm(vn);
vec4 vxz = textureLod(velocity_sampler, x, 0.0) * vec4(render_size, 1, 1);
float vx_length = max(0.5, length(vxz.xy));
multiplier = clamp(vx_length, 0, min(params.max_dilation_radius, vn_length * params.motion_blur_intensity)) / max(FLT_MIN, vx_length);
vxz.xyz *= multiplier;
vx_length *= multiplier;
vec2 vx = vxz.xy;
if(vn_length <= 0.5)
{
imageStore(output_image, uvi, col_x);
#ifdef DEBUG
imageStore(debug_1_image, uvi, col_x);
imageStore(debug_2_image, uvi, abs(vec4(vn / render_size * 10, vnz.z * 100, 1)));
imageStore(debug_3_image, uvi, abs(vec4(velocity_map_sample - x, 0, 1)));
imageStore(debug_4_image, uvi, abs(vec4(vx / render_size * 10, vxz.z * 100, 1)));
imageStore(debug_5_image, uvi, col_x);
#endif
return;
}
float velocity_match = pow(clamp(dot(vx, vn) / dot(vn, vn), 0, 1), 0.25);
vn = mix(vn, vx, velocity_match);
vnz = mix(vnz, vxz.xyz, velocity_match);
float zx = vxz.w;
vec2 wx = safenorm(vx);
float weight = 0;
vec4 sum = col_x * weight;
float total_back_weight = 1e-10;
vec4 back_sum = col_x * total_back_weight;
float j = interleaved_gradient_noise(uvi) - 0.5;
int back_amount = 0;
int nai_back_i = 1;
for(int i = 0; i < params.motion_blur_samples; i++)
{
float nai_t = mix(0., -1., (i + j + 1.0) / (params.motion_blur_samples + 1.0));
float nai_T = abs(nai_t * vx_length);
vec2 nai_y = x + (vx / render_size) * nai_t;
float nai_zy = textureLod(depth_sampler, nai_y, 0.0).x - vxz.z * nai_t;
float nai_b = z_compare(-zx, -nai_zy, 20000);
float nai_f = z_compare(-nai_zy, -zx, 20000);
vec4 nai_vy = textureLod(velocity_sampler, nai_y, 0.0) * vec4(render_size, 1, 1);
float nai_vy_length = max(0.5, length(nai_vy.xy));
float nai_ay = nai_b;
float nai_wb = abs(max(0, dot(nai_vy.xy / nai_vy_length, wx)));
float nai_ay_f = nai_f * step(nai_T, nai_vy_length * nai_wb);
if(nai_y.x < 0 || nai_y.x > 1 || nai_y.y < 0 || nai_y.y > 1 || nai_ay + nai_ay_f <= 1e-5)
{
nai_t = mix(0., 1., (nai_back_i + j + 1.0) / (params.motion_blur_samples + 1.0));
nai_T = abs(nai_t * vx_length);
nai_y = x + (vx / render_size) * nai_t;
nai_zy = textureLod(depth_sampler, nai_y, 0.0).x - vxz.z * nai_t;
nai_b = z_compare(-zx, -nai_zy, 20000);
nai_f = z_compare(-nai_zy, -zx, 20000);
nai_vy = textureLod(velocity_sampler, nai_y, 0.0) * vec4(render_size, 1, 1);
nai_vy_length = max(0.5, length(nai_vy.xy));
nai_ay = nai_b;
nai_wb = abs(max(0, dot(nai_vy.xy / nai_vy_length, wx)));
nai_ay_f = nai_f * step(nai_T, nai_vy_length * nai_wb);
nai_back_i++;
}
vec4 nai_col_y = textureLod(color_sampler, nai_y, 0.0);
total_back_weight += nai_ay;
back_sum += nai_col_y * nai_ay;
float t = mix(0., -1., (i - back_amount + j + 1.0) / (params.motion_blur_samples + 1.0));
float T = abs(t * vn_length);
vec2 y = x + (vn / render_size) * t;
if(y.x < 0 || y.x > 1 || y.y < 0 || y.y > 1)
{
continue;
// vn = -vn;
// vnz = -vnz;
// wn = -wn;
// back_amount = i;
}
vec4 vy = textureLod(velocity_sampler, y, 0.0) * vec4(render_size, 1, 1);
float vy_length = max(0.5, length(vy.xy));
float zy = vy.w - vnz.z * t;
float f = z_compare(-zy, -zx, 20000);
float wa = abs(max(0, dot(vy.xy / vy_length, wn)));
float ay_trail = f * step(T, vy_length * wa);
vec4 col_y = textureLod(color_sampler, y, 0.0);
vec2 back_y = x + (vn / render_size) * -t;
vec4 back_vy = textureLod(velocity_sampler, back_y, 0.0) * vec4(render_size, 1, 1);
float back_vy_length = max(0.5, length(back_vy.xy));
float back_zy = back_vy.w - vnz.z * -t;
float back_wa = abs(max(0, dot(back_vy.xy / back_vy_length, -wn)));
float back_f = z_compare(-back_zy, -zx, 20000);
float back_ay_trail = back_f * step(T, back_vy_length * back_wa);
vec4 back_col_y = textureLod(color_sampler, back_y, 0.0);
weight += back_ay_trail + (back_ay_trail > 0 ? 0 : ay_trail);
sum += back_col_y * back_ay_trail + (back_ay_trail > 0 ? vec4(0) : col_y * ay_trail);
}
back_sum *= (params.motion_blur_samples - weight) / total_back_weight;
sum /= params.motion_blur_samples;
back_sum /= params.motion_blur_samples;
imageStore(output_image, uvi, sum + back_sum);
#ifdef DEBUG
imageStore(debug_1_image, uvi, sum + back_sum);
imageStore(debug_2_image, uvi, abs(vec4(vn / render_size * 10, vnz.z * 100, 1)));
imageStore(debug_3_image, uvi, abs(vec4(velocity_map_sample - x, 0, 1)));
imageStore(debug_4_image, uvi, abs(vec4(vx / render_size * 10, vxz.z * 100, 1)));
imageStore(debug_5_image, uvi, col_x);
#endif
}

View File

@ -0,0 +1,14 @@
[remap]
importer="glsl"
type="RDShaderFile"
uid="uid://b1fr5qhhrbpst"
path="res://.godot/imported/jump_flood_realistic_blur.glsl-c7d6d91d942d788c7b2fc3bc2c1c8e38.res"
[deps]
source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_realistic_blur.glsl"
dest_files=["res://.godot/imported/jump_flood_realistic_blur.glsl-c7d6d91d942d788c7b2fc3bc2c1c8e38.res"]
[params]

View File

@ -0,0 +1,240 @@
#[compute]
#version 450
#define FLT_MAX 3.402823466e+38
#define FLT_MIN 1.175494351e-38
#define M_PI 3.1415926535897932384626433832795
layout(set = 0, binding = 0) uniform sampler2D color_sampler;
layout(set = 0, binding = 1) uniform sampler2D depth_sampler;
layout(set = 0, binding = 2) uniform sampler2D velocity_sampler;
layout(set = 0, binding = 3) uniform sampler2D velocity_map;
layout(rgba16f, set = 0, binding = 4) uniform writeonly image2D output_image;
layout(set = 0, binding = 5) uniform sampler2D tile_max;
layout(push_constant, std430) uniform Params
{
float motion_blur_samples;
float motion_blur_intensity;
float motion_blur_center_fade;
float frame;
float last_iteration_index;
float sample_step_multiplier;
float step_exponent_modifier;
float max_dilation_radius;
int nan0;
int nan1;
int nan2;
int nan3;
} params;
layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
// McGuire's functions https://docs.google.com/document/d/1IIlAKTj-O01hcXEdGxTErQbCHO9iBmRx6oFUy_Jm0fI/edit
// ----------------------------------------------------------
float soft_depth_compare(float depth_X, float depth_Y, float sze)
{
return clamp(1 - (depth_X - depth_Y) / sze, 0, 1);
}
float cone(float T, float v)
{
return clamp(1 - T / v, 0, 1);
}
float cylinder(float T, float v)
{
return 1.0 - smoothstep(0.95 * v, 1.05 * v, T);
}
// ----------------------------------------------------------
// Guertin's functions https://research.nvidia.com/sites/default/files/pubs/2013-11_A-Fast-and/Guertin2013MotionBlur-small.pdf
// ----------------------------------------------------------
float z_compare(float a, float b, float sze)
{
return clamp(1. - sze * (a - b), 0, 1);
}
// ----------------------------------------------------------
// from https://www.shadertoy.com/view/ftKfzc
// ----------------------------------------------------------
float interleaved_gradient_noise(vec2 uv){
uv += float(params.frame) * (vec2(47, 17) * 0.695);
vec3 magic = vec3( 0.06711056, 0.00583715, 52.9829189 );
return fract(magic.z * fract(dot(uv, magic.xy)));
}
// ----------------------------------------------------------
// from https://github.com/bradparks/KinoMotion__unity_motion_blur/tree/master
// ----------------------------------------------------------
vec2 safenorm(vec2 v)
{
float l = max(length(v), 1e-6);
return v / l * int(l >= 0.5);
}
vec2 jitter_tile(vec2 uvi)
{
float rx, ry;
float angle = interleaved_gradient_noise(uvi + vec2(2, 0)) * M_PI * 2;
rx = cos(angle);
ry = sin(angle);
return vec2(rx, ry) / textureSize(tile_max, 0) / 4;
}
// ----------------------------------------------------------
void main()
{
ivec2 render_size = ivec2(textureSize(color_sampler, 0));
ivec2 uvi = ivec2(gl_GlobalInvocationID.xy);
if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y))
{
return;
}
vec2 x = (vec2(uvi) + vec2(0.5)) / vec2(render_size);
vec2 velocity_map_sample = textureLod(velocity_map, x + jitter_tile(uvi), 0.0).xy;
vec3 vnz = textureLod(tile_max, velocity_map_sample, 0.0).xyz * vec3(render_size, 1);
float vn_length = max(0.5, length(vnz.xy));
float multiplier = clamp(vn_length, 0, min(params.max_dilation_radius, vn_length * params.motion_blur_intensity)) / max(FLT_MIN, vn_length);
vnz.xyz *= multiplier;
vn_length *= multiplier;
vec2 vn = vnz.xy;
vec4 col_x = textureLod(color_sampler, x, 0.0);
vec2 wn = safenorm(vn);
vec4 vxz = textureLod(velocity_sampler, x, 0.0) * vec4(render_size, 1, 1);
float vx_length = max(0.5, length(vxz.xy));
multiplier = clamp(vx_length, 0, min(params.max_dilation_radius, vn_length * params.motion_blur_intensity)) / max(FLT_MIN, vx_length);
vxz.xyz *= multiplier;
vx_length *= multiplier;
vec2 vx = vxz.xy;
if(vn_length <= 0.5)
{
imageStore(output_image, uvi, col_x);
#ifdef DEBUG
imageStore(debug_1_image, uvi, col_x);
imageStore(debug_2_image, uvi, abs(vec4(vn / render_size * 10, vnz.z * 100, 1)));
imageStore(debug_3_image, uvi, abs(vec4(velocity_map_sample - x, 0, 1)));
imageStore(debug_4_image, uvi, abs(vec4(vx / render_size * 10, vxz.z * 100, 1)));
imageStore(debug_5_image, uvi, col_x);
#endif
return;
}
float velocity_match = pow(clamp(dot(vx, vn) / dot(vn, vn), 0, 1), 0.25);
vn = mix(vn, vx, velocity_match);
vnz = mix(vnz, vxz.xyz, velocity_match);
float zx = vxz.w;
vec2 wx = safenorm(vx);
float weight = 0;
vec4 sum = col_x * weight;
float total_back_weight = 1e-10;
vec4 back_sum = col_x * total_back_weight;
float j = interleaved_gradient_noise(uvi) - 0.5;
int back_amount = 0;
int nai_back_i = 1;
for(int i = 0; i < params.motion_blur_samples; i++)
{
float nai_t = mix(0., -1., (i + j + 1.0) / (params.motion_blur_samples + 1.0));
float nai_T = abs(nai_t * vx_length);
vec2 nai_y = x + (vx / render_size) * nai_t;
if(nai_y.x < 0 || nai_y.x > 1 || nai_y.y < 0 || nai_y.y > 1)
{
continue;
}
float nai_zy = textureLod(depth_sampler, nai_y, 0.0).x - vxz.z * nai_t;
float nai_b = z_compare(-zx, -nai_zy, 20000);
vec4 nai_vy = textureLod(velocity_sampler, nai_y, 0.0) * vec4(render_size, 1, 1);
float nai_ay = nai_b;
vec4 nai_col_y = textureLod(color_sampler, nai_y, 0.0);
total_back_weight += nai_ay;
back_sum += nai_col_y * nai_ay;
float t = mix(0., -1., (i - back_amount + j + 1.0) / (params.motion_blur_samples + 1.0));
float T = abs(t * vn_length);
vec2 y = x + (vn / render_size) * t;
if(y.x < 0 || y.x > 1 || y.y < 0 || y.y > 1)
{
continue;
}
vec4 vy = textureLod(velocity_sampler, y, 0.0) * vec4(render_size, 1, 1);
float vy_length = max(0.5, length(vy.xy));
float zy = vy.w - vnz.z * t;
float f = z_compare(-zy, -zx, 20000);
float wa = abs(max(0, dot(vy.xy / vy_length, wn)));
float ay_trail = f * step(T, vy_length * wa);
vec4 col_y = textureLod(color_sampler, y, 0.0);
weight += ay_trail;
sum += col_y * ay_trail;
}
back_sum *= (params.motion_blur_samples - weight) / total_back_weight;
sum /= params.motion_blur_samples;
back_sum /= params.motion_blur_samples;
imageStore(output_image, uvi, sum + back_sum);
#ifdef DEBUG
imageStore(debug_1_image, uvi, sum + back_sum);
imageStore(debug_2_image, uvi, abs(vec4(vn / render_size * 10, vnz.z * 100, 1)));
imageStore(debug_3_image, uvi, abs(vec4(velocity_map_sample - x, 0, 1)));
imageStore(debug_4_image, uvi, abs(vec4(vx / render_size * 10, vxz.z * 100, 1)));
imageStore(debug_5_image, uvi, col_x);
#endif
}

View File

@ -0,0 +1,14 @@
[remap]
importer="glsl"
type="RDShaderFile"
uid="uid://bdm5t4l1y3ts7"
path="res://.godot/imported/jump_flood_simple_blur.glsl-cf442320d0e724df4bd151fec5d94fae.res"
[deps]
source_file="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_simple_blur.glsl"
dest_files=["res://.godot/imported/jump_flood_simple_blur.glsl-cf442320d0e724df4bd151fec5d94fae.res"]
[params]

View File

@ -0,0 +1,26 @@
extends "res://addons/SphynxMotionBlurToolkit/BaseClasses/mb_compositor_effect.gd"
@export_group("Shader Parameters")
## the portion of speed that is allowed for side bleed of velocities
## during the jfa dilation passes and before backtracking. Getting this a higher value
## would make it so that meshes at movement blur more reliably, but also bleed
## further perpendicularly to their velocity, thus wash elemets behind them out.
@export var perpen_error_threshold : float = 0.5
## an initial step size that can increase the dilation radius proportionally, at the
## sacrifice of some quality in the final resolution of the dilation.[br][br]
## the formula for the maximum radius of the dilation (in pixels) is: pow(2 + step_exponent_modifier, JFA_pass_count) * sample_step_multiplier
@export var sample_step_multiplier : int = 16
## by default, the jump flood makes samples along distances that start
## at 2 to the power of the pass count you want to perform, which is also
## the dilation radius you desire. You can change it to values higher than
## 2 with this variable, and reach higher dilation radius at the sacrifice of
## some accuracy in the dilation.
## the formula for the maximum radius of the dilation (in pixels) is: pow(2 + step_exponent_modifier, JFA_pass_count) * sample_step_multiplier
@export var step_exponent_modifier : float = 1
## the number of passes performed by the jump flood algorithm based dilation,
## each pass added doubles the maximum radius of dilation available.[br][br]
## the formula for the maximum radius of the dilation (in pixels) is: pow(2 + step_exponent_modifier, JFA_pass_count) * sample_step_multiplier
@export var JFA_pass_count : int = 3

View File

@ -0,0 +1,298 @@
extends "res://addons/SphynxMotionBlurToolkit/JumpFlood/base_jump_flood_motion_blur.gd"
class_name ExperimentalJumpFloodMotionBlur
@export_group("Shader Stages")
@export var tile_max_x_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_tile_max_x_stage.tres"):
set(value):
unsubscribe_shader_stage(tile_max_x_stage)
tile_max_x_stage = value
subscirbe_shader_stage(value)
@export var tile_max_y_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_tile_max_y_stage.tres"):
set(value):
unsubscribe_shader_stage(tile_max_y_stage)
tile_max_y_stage = value
subscirbe_shader_stage(value)
@export var construct_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jf_simple_stage.tres"):
set(value):
unsubscribe_shader_stage(construct_stage)
construct_stage = value
subscirbe_shader_stage(value)
@export var neighbor_max_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_neighbor_max_stage.tres"):
set(value):
unsubscribe_shader_stage(neighbor_max_stage)
neighbor_max_stage = value
subscirbe_shader_stage(value)
@export var blur_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/experimental_jump_flood_blur_stage.tres"):
set(value):
unsubscribe_shader_stage(blur_stage)
blur_stage = value
subscirbe_shader_stage(value)
@export var cache_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_cache_stage.tres"):
set(value):
unsubscribe_shader_stage(cache_stage)
cache_stage = value
subscirbe_shader_stage(value)
@export var overlay_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_overlay_stage.tres"):
set(value):
unsubscribe_shader_stage(overlay_stage)
overlay_stage = value
subscirbe_shader_stage(value)
var tile_max_x : StringName = "tile_max_x"
var tile_max : StringName = "tile_max"
var neighbor_max : StringName = "neighbor_max"
var output_color : StringName = "output_color"
var past_color : StringName = "past_color_cache"
var past_velocity : StringName = "past_velocity_cache"
var buffer_a : StringName = "buffer_a"
var buffer_b : StringName = "buffer_b"
var custom_velocity : StringName = "custom_velocity"
var temp_intensity : float
var previous_time : float = 0
func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSceneBuffersRD, render_scene_data : RenderSceneDataRD):
var time : float = float(Time.get_ticks_msec()) / 1000
var delta_time : float = time - previous_time
previous_time = time
temp_intensity = intensity
if framerate_independent:
var capped_frame_time : float = 1 / target_constant_framerate
if !uncapped_independence:
capped_frame_time = min(capped_frame_time, delta_time)
temp_intensity = intensity * capped_frame_time / delta_time
ensure_texture(custom_velocity, render_scene_buffers)
ensure_texture(tile_max_x, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1.))
ensure_texture(tile_max, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier))
ensure_texture(buffer_a, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier))
ensure_texture(buffer_b, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier))
ensure_texture(neighbor_max, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier))
ensure_texture(output_color, render_scene_buffers)
ensure_texture(past_color, render_scene_buffers)
ensure_texture(past_velocity, render_scene_buffers)
rd.draw_command_begin_label("Motion Blur", Color(1.0, 1.0, 1.0, 1.0))
var last_iteration_index : int = JFA_pass_count - 1;
var max_dilation_radius : float = pow(2 + step_exponent_modifier, last_iteration_index) * sample_step_multiplier / intensity;
var tile_max_x_push_constants: PackedFloat32Array = [
0,
0,
0,
0
]
var int_tile_max_x_push_constants : PackedInt32Array = [
sample_step_multiplier,
0,
0,
0
]
var tile_max_x_push_constants_byte_array = tile_max_x_push_constants.to_byte_array()
tile_max_x_push_constants_byte_array.append_array(int_tile_max_x_push_constants.to_byte_array())
var tile_max_y_push_constants: PackedFloat32Array = [
0,
0,
0,
0
]
var int_tile_max_y_push_constants : PackedInt32Array = [
sample_step_multiplier,
0,
0,
0
]
var tile_max_y_push_constants_byte_array = tile_max_y_push_constants.to_byte_array()
tile_max_y_push_constants_byte_array.append_array(int_tile_max_y_push_constants.to_byte_array())
var neighbor_max_push_constants: PackedFloat32Array = [
0,
0,
0,
0
]
var int_neighbor_max_push_constants : PackedInt32Array = [
0,
0,
0,
0
]
var neighbor_max_push_constants_byte_array = neighbor_max_push_constants.to_byte_array()
neighbor_max_push_constants_byte_array.append_array(int_neighbor_max_push_constants.to_byte_array())
var push_constant: PackedFloat32Array = [
samples,
temp_intensity,
center_fade,
Engine.get_frames_drawn() % 8,
last_iteration_index,
sample_step_multiplier,
step_exponent_modifier,
max_dilation_radius,
]
var int_push_constant : PackedInt32Array = [
0,
0,
0,
0
]
var byte_array = push_constant.to_byte_array()
byte_array.append_array(int_push_constant.to_byte_array())
var view_count = render_scene_buffers.get_view_count()
for view in range(view_count):
var color_image := render_scene_buffers.get_color_layer(view)
var depth_image := render_scene_buffers.get_depth_layer(view)
var output_color_image := render_scene_buffers.get_texture_slice(context, output_color, view, 0, 1, 1)
var past_color_image := render_scene_buffers.get_texture_slice(context, past_color, view, 0, 1, 1)
var past_velocity_image := render_scene_buffers.get_texture_slice(context, past_velocity, view, 0, 1, 1)
var buffer_a_image := render_scene_buffers.get_texture_slice(context, buffer_a, view, 0, 1, 1)
var buffer_b_image := render_scene_buffers.get_texture_slice(context, buffer_b, view, 0, 1, 1)
var custom_velocity_image := render_scene_buffers.get_texture_slice(context, custom_velocity, view, 0, 1, 1)
var tile_max_x_image := render_scene_buffers.get_texture_slice(context, tile_max_x, view, 0, 1, 1)
var tile_max_image := render_scene_buffers.get_texture_slice(context, tile_max, view, 0, 1, 1)
var neighbor_max_image := render_scene_buffers.get_texture_slice(context, neighbor_max, view, 0, 1, 1)
var x_groups := floori((render_size.x / sample_step_multiplier - 1) / 16 + 1)
var y_groups := floori((render_size.y - 1) / 16 + 1)
dispatch_stage(tile_max_x_stage,
[
get_sampler_uniform(custom_velocity_image, 0, false),
get_sampler_uniform(depth_image, 1, false),
get_image_uniform(tile_max_x_image, 2)
],
tile_max_x_push_constants_byte_array,
Vector3i(x_groups, y_groups, 1),
"TileMaxX",
view)
x_groups = floori((render_size.x / sample_step_multiplier - 1) / 16 + 1)
y_groups = floori((render_size.y / sample_step_multiplier - 1) / 16 + 1)
dispatch_stage(tile_max_y_stage,
[
get_sampler_uniform(tile_max_x_image, 0, false),
get_image_uniform(tile_max_image, 1)
],
tile_max_y_push_constants_byte_array,
Vector3i(x_groups, y_groups, 1),
"TileMaxY",
view)
for i in JFA_pass_count:
var jf_push_constants : PackedInt32Array = [
i,
last_iteration_index,
0,
16
]
var step_size : float = round(pow(2 + step_exponent_modifier, last_iteration_index - i));
var jf_float_push_constants_test : PackedFloat32Array = [
perpen_error_threshold,
sample_step_multiplier,
temp_intensity,
0,
0,
0,
0,
step_exponent_modifier,
step_size,
max_dilation_radius,
0,
0
]
var jf_byte_array = jf_push_constants.to_byte_array()
jf_byte_array.append_array(jf_float_push_constants_test.to_byte_array())
dispatch_stage(construct_stage,
[
get_sampler_uniform(tile_max_image, 0, false),
get_image_uniform(buffer_a_image, 1),
get_image_uniform(buffer_b_image, 2),
get_sampler_uniform(buffer_a_image, 3, false),
get_sampler_uniform(buffer_b_image, 4, false)
],
jf_byte_array,
Vector3i(x_groups, y_groups, 1),
"Construct Blur",
view)
dispatch_stage(neighbor_max_stage,
[
get_sampler_uniform(tile_max_image, 0, false),
get_sampler_uniform(buffer_b_image if last_iteration_index % 2 else buffer_a_image, 1, false),
get_image_uniform(neighbor_max_image, 2)
],
neighbor_max_push_constants_byte_array,
Vector3i(x_groups, y_groups, 1),
"NeighborMax",
view)
x_groups = floori((render_size.x - 1) / 16 + 1)
y_groups = floori((render_size.y - 1) / 16 + 1)
dispatch_stage(blur_stage,
[
get_sampler_uniform(color_image, 0, false),
get_sampler_uniform(depth_image, 1, false),
get_sampler_uniform(custom_velocity_image, 2, false),
get_sampler_uniform(neighbor_max_image, 3, false),
get_image_uniform(output_color_image, 4),
get_sampler_uniform(tile_max_image, 5, false),
get_sampler_uniform(past_color_image, 6, false),
get_sampler_uniform(past_velocity_image, 7, false)
],
byte_array,
Vector3i(x_groups, y_groups, 1),
"Compute Blur",
view)
dispatch_stage(cache_stage,
[
get_sampler_uniform(custom_velocity_image, 0),
get_sampler_uniform(color_image, 1),
get_image_uniform(past_velocity_image, 2),
get_image_uniform(past_color_image, 3),
],
[],
Vector3i(x_groups, y_groups, 1),
"Past Color Copy",
view)
dispatch_stage(overlay_stage,
[
get_sampler_uniform(output_color_image, 0),
get_image_uniform(color_image, 1),
],
[],
Vector3i(x_groups, y_groups, 1),
"Overlay Result",
view)
rd.draw_command_end_label()

View File

@ -0,0 +1,8 @@
[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://cvavvqqstnm1j"]
[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_3q423"]
[ext_resource type="RDShaderFile" uid="uid://bud4a7eh5sqr8" path="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_experimental_blur.glsl" id="2_8flx6"]
[resource]
script = ExtResource("1_3q423")
shader_file = ExtResource("2_8flx6")

View File

@ -0,0 +1,8 @@
[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://bq18dhoelcexm"]
[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_3clo0"]
[ext_resource type="RDShaderFile" uid="uid://quuyr2q5w5kx" path="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_cache.glsl" id="2_val47"]
[resource]
script = ExtResource("1_3clo0")
shader_file = ExtResource("2_val47")

View File

@ -1,13 +1,7 @@
extends MotionBlurCompositorEffect
extends "res://addons/SphynxMotionBlurToolkit/JumpFlood/base_jump_flood_motion_blur.gd"
class_name SphynxOldJumpFloodMotionBlur
@export_group("Motion Blur", "motion_blur_")
# diminishing returns over 16
@export_range(4, 64) var motion_blur_samples: int = 8
# you really don't want this over 0.5, but you can if you want to try
@export_range(0, 0.5, 0.001, "or_greater") var motion_blur_intensity: float = 1
@export_range(0, 1) var motion_blur_center_fade: float = 0.0
@export_group("Shader Stages")
@export var blur_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_blur_stage.tres"):
set(value):
unsubscribe_shader_stage(blur_stage)
@ -26,25 +20,6 @@ class_name SphynxOldJumpFloodMotionBlur
construct_stage = value
subscirbe_shader_stage(value)
## the portion of speed that is allowed for side bleed of velocities
## during the jfa dilation passes and before backtracking. Getting this a higher value
## would make it so that meshes at movement blur more reliably, but also bleed
## further perpendicularly to their velocity, thus wash elemets behind them out.
@export var perpen_error_threshold : float = 0.5
## an initial step size that can increase the dilation radius proportionally, at the
## sacrifice of some quality in the final resolution of the dilation.[br][br]
## the formula for the maximum radius of the dilation (in pixels) is: pow(2 + step_exponent_modifier, JFA_pass_count) * sample_step_multiplier
@export var sample_step_multiplier : float = 16
## by default, the jump flood makes samples along distances that start
## at 2 to the power of the pass count you want to perform, which is also
## the dilation radius you desire. You can change it to values higher than
## 2 with this variable, and reach higher dilation radius at the sacrifice of
## some accuracy in the dilation.
## the formula for the maximum radius of the dilation (in pixels) is: pow(2 + step_exponent_modifier, JFA_pass_count) * sample_step_multiplier
@export var step_exponent_modifier : float = 1
## how many steps along a range of 2 velocities from the
## dilation target velocity space do we go along to find a better fitting velocity sample
## higher samples meaning higher detail getting captured and blurred
@ -65,27 +40,6 @@ class_name SphynxOldJumpFloodMotionBlur
## considered (in NDC space)
@export var backtracbing_depth_match_threshold : float = 0.001
## the number of passes performed by the jump flood algorithm based dilation,
## each pass added doubles the maximum radius of dilation available.[br][br]
## the formula for the maximum radius of the dilation (in pixels) is: pow(2 + step_exponent_modifier, JFA_pass_count) * sample_step_multiplier
@export var JFA_pass_count : int = 3
## wether this motion blur stays the same intensity below
## target_constant_framerate
@export var framerate_independent : bool = true
## Description: Removes clamping on motion blur scale to allow framerate independent motion
## blur to scale longer than realistically possible when render framerate is higher
## than target framerate.[br][br]
## [color=yellow]Warning:[/color] Turning this on would allow over-blurring of pixels, which
## produces inaccurate results, and would likely cause nausea in players over
## long exposure durations, use with caution and out of artistic intent
@export var uncapped_independence : bool = false
## if framerate_independent is enabled, the blur would simulate
## sutter speeds at that framerate, and up.
@export var target_constant_framerate : float = 30
var texture: StringName = "texture"
var buffer_a : StringName = "buffer_a"
@ -93,16 +47,7 @@ var buffer_b : StringName = "buffer_b"
var custom_velocity : StringName = "custom_velocity"
@export var debug_1 : String = "debug_1"
@export var debug_2 : String = "debug_2"
@export var debug_3 : String = "debug_3"
@export var debug_4 : String = "debug_4"
@export var debug_5 : String = "debug_5"
@export var debug_6 : String = "debug_6"
@export var debug_7 : String = "debug_7"
@export var debug_8 : String = "debug_8"
var temp_motion_blur_intensity : float
var temp_intensity : float
var previous_time : float = 0
@ -113,7 +58,7 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce
previous_time = time
temp_motion_blur_intensity = motion_blur_intensity
temp_intensity = intensity
if framerate_independent:
var capped_frame_time : float = 1 / target_constant_framerate
@ -121,7 +66,7 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce
if !uncapped_independence:
capped_frame_time = min(capped_frame_time, delta_time)
temp_motion_blur_intensity = motion_blur_intensity * capped_frame_time / delta_time
temp_intensity = intensity * capped_frame_time / delta_time
ensure_texture(texture, render_scene_buffers)
@ -129,25 +74,16 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce
ensure_texture(buffer_b, render_scene_buffers)#, RenderingDevice.DATA_FORMAT_R16G16_SFLOAT)
ensure_texture(custom_velocity, render_scene_buffers)
ensure_texture(debug_1, render_scene_buffers)
ensure_texture(debug_2, render_scene_buffers)
ensure_texture(debug_3, render_scene_buffers)
ensure_texture(debug_4, render_scene_buffers)
ensure_texture(debug_5, render_scene_buffers)
ensure_texture(debug_6, render_scene_buffers)
ensure_texture(debug_7, render_scene_buffers)
ensure_texture(debug_8, render_scene_buffers)
rd.draw_command_begin_label("Motion Blur", Color(1.0, 1.0, 1.0, 1.0))
var last_iteration_index : int = JFA_pass_count - 1;
var max_dilation_radius : float = pow(2 + step_exponent_modifier, last_iteration_index) * sample_step_multiplier / motion_blur_intensity;
var max_dilation_radius : float = pow(2 + step_exponent_modifier, last_iteration_index) * sample_step_multiplier / intensity;
var push_constant: PackedFloat32Array = [
motion_blur_samples,
temp_motion_blur_intensity,
motion_blur_center_fade,
samples,
temp_intensity,
center_fade,
Engine.get_frames_drawn() % 8,
last_iteration_index,
sample_step_multiplier,
@ -171,14 +107,6 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce
var buffer_a_image := render_scene_buffers.get_texture_slice(context, buffer_a, view, 0, 1, 1)
var buffer_b_image := render_scene_buffers.get_texture_slice(context, buffer_b, view, 0, 1, 1)
var custom_velocity_image := render_scene_buffers.get_texture_slice(context, custom_velocity, view, 0, 1, 1)
var debug_1_image := render_scene_buffers.get_texture_slice(context, debug_1, view, 0, 1, 1)
var debug_2_image := render_scene_buffers.get_texture_slice(context, debug_2, view, 0, 1, 1)
var debug_3_image := render_scene_buffers.get_texture_slice(context, debug_3, view, 0, 1, 1)
var debug_4_image := render_scene_buffers.get_texture_slice(context, debug_4, view, 0, 1, 1)
var debug_5_image := render_scene_buffers.get_texture_slice(context, debug_5, view, 0, 1, 1)
var debug_6_image := render_scene_buffers.get_texture_slice(context, debug_6, view, 0, 1, 1)
var debug_7_image := render_scene_buffers.get_texture_slice(context, debug_7, view, 0, 1, 1)
var debug_8_image := render_scene_buffers.get_texture_slice(context, debug_8, view, 0, 1, 1)
rd.draw_command_begin_label("Construct blur " + str(view), Color(1.0, 1.0, 1.0, 1.0))
@ -214,7 +142,7 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce
var jf_float_push_constants_test : PackedFloat32Array = [
perpen_error_threshold,
sample_step_multiplier,
temp_motion_blur_intensity,
temp_intensity,
backtracking_velocity_match_threshold,
backtracking_velocity_match_parallel_sensitivity,
backtracking_velcoity_match_perpendicular_sensitivity,
@ -243,14 +171,6 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce
get_sampler_uniform(custom_velocity_image, 2, false),
get_sampler_uniform(buffer_b_image if last_iteration_index % 2 else buffer_a_image, 3, false),
get_image_uniform(texture_image, 4),
get_image_uniform(debug_1_image, 5),
get_image_uniform(debug_2_image, 6),
get_image_uniform(debug_3_image, 7),
get_image_uniform(debug_4_image, 8),
get_image_uniform(debug_5_image, 9),
get_image_uniform(debug_6_image, 10),
get_image_uniform(debug_7_image, 11),
get_image_uniform(debug_8_image, 12),
],
byte_array,
Vector3i(x_groups, y_groups, 1),

View File

@ -0,0 +1,8 @@
[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://ceav72kvj4qbw"]
[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_qdmen"]
[ext_resource type="RDShaderFile" uid="uid://b1fr5qhhrbpst" path="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_realistic_blur.glsl" id="2_bdp68"]
[resource]
script = ExtResource("1_qdmen")
shader_file = ExtResource("2_bdp68")

View File

@ -0,0 +1,268 @@
extends "res://addons/SphynxMotionBlurToolkit/JumpFlood/base_jump_flood_motion_blur.gd"
class_name SphynxRealisticJumpFloodMotionBlur
@export_group("Shader Stages")
@export var tile_max_x_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_tile_max_x_stage.tres"):
set(value):
unsubscribe_shader_stage(tile_max_x_stage)
tile_max_x_stage = value
subscirbe_shader_stage(value)
@export var tile_max_y_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_tile_max_y_stage.tres"):
set(value):
unsubscribe_shader_stage(tile_max_y_stage)
tile_max_y_stage = value
subscirbe_shader_stage(value)
@export var construct_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jf_simple_stage.tres"):
set(value):
unsubscribe_shader_stage(construct_stage)
construct_stage = value
subscirbe_shader_stage(value)
@export var neighbor_max_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_neighbor_max_stage.tres"):
set(value):
unsubscribe_shader_stage(neighbor_max_stage)
neighbor_max_stage = value
subscirbe_shader_stage(value)
@export var blur_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/realistic_jf_blur_stage.tres"):
set(value):
unsubscribe_shader_stage(blur_stage)
blur_stage = value
subscirbe_shader_stage(value)
@export var overlay_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_overlay_stage.tres"):
set(value):
unsubscribe_shader_stage(overlay_stage)
overlay_stage = value
subscirbe_shader_stage(value)
var tile_max_x : StringName = "tile_max_x"
var tile_max : StringName = "tile_max"
var neighbor_max : StringName = "neighbor_max"
var output_color : StringName = "output_color"
var buffer_a : StringName = "buffer_a"
var buffer_b : StringName = "buffer_b"
var custom_velocity : StringName = "custom_velocity"
var temp_intensity : float
var previous_time : float = 0
func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSceneBuffersRD, render_scene_data : RenderSceneDataRD):
var time : float = float(Time.get_ticks_msec()) / 1000
var delta_time : float = time - previous_time
previous_time = time
temp_intensity = intensity
if framerate_independent:
var capped_frame_time : float = 1 / target_constant_framerate
if !uncapped_independence:
capped_frame_time = min(capped_frame_time, delta_time)
temp_intensity = intensity * capped_frame_time / delta_time
ensure_texture(custom_velocity, render_scene_buffers)
ensure_texture(tile_max_x, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1.))
ensure_texture(tile_max, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier))
ensure_texture(buffer_a, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier))
ensure_texture(buffer_b, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier))
ensure_texture(neighbor_max, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier))
ensure_texture(output_color, render_scene_buffers)
rd.draw_command_begin_label("Motion Blur", Color(1.0, 1.0, 1.0, 1.0))
var last_iteration_index : int = JFA_pass_count - 1;
var max_dilation_radius : float = pow(2 + step_exponent_modifier, last_iteration_index) * sample_step_multiplier;
var tile_max_x_push_constants: PackedFloat32Array = [
0,
0,
0,
0
]
var int_tile_max_x_push_constants : PackedInt32Array = [
sample_step_multiplier,
0,
0,
0
]
var tile_max_x_push_constants_byte_array = tile_max_x_push_constants.to_byte_array()
tile_max_x_push_constants_byte_array.append_array(int_tile_max_x_push_constants.to_byte_array())
var tile_max_y_push_constants: PackedFloat32Array = [
0,
0,
0,
0
]
var int_tile_max_y_push_constants : PackedInt32Array = [
sample_step_multiplier,
0,
0,
0
]
var tile_max_y_push_constants_byte_array = tile_max_y_push_constants.to_byte_array()
tile_max_y_push_constants_byte_array.append_array(int_tile_max_y_push_constants.to_byte_array())
var neighbor_max_push_constants: PackedFloat32Array = [
0,
0,
0,
0
]
var int_neighbor_max_push_constants : PackedInt32Array = [
0,
0,
0,
0
]
var neighbor_max_push_constants_byte_array = neighbor_max_push_constants.to_byte_array()
neighbor_max_push_constants_byte_array.append_array(int_neighbor_max_push_constants.to_byte_array())
var push_constant: PackedFloat32Array = [
samples,
temp_intensity,
center_fade,
Engine.get_frames_drawn() % 8,
last_iteration_index,
sample_step_multiplier,
step_exponent_modifier,
max_dilation_radius,
]
var int_push_constant : PackedInt32Array = [
0,
0,
0,
0
]
var byte_array = push_constant.to_byte_array()
byte_array.append_array(int_push_constant.to_byte_array())
var view_count = render_scene_buffers.get_view_count()
for view in range(view_count):
var color_image := render_scene_buffers.get_color_layer(view)
var depth_image := render_scene_buffers.get_depth_layer(view)
var output_color_image := render_scene_buffers.get_texture_slice(context, output_color, view, 0, 1, 1)
var buffer_a_image := render_scene_buffers.get_texture_slice(context, buffer_a, view, 0, 1, 1)
var buffer_b_image := render_scene_buffers.get_texture_slice(context, buffer_b, view, 0, 1, 1)
var custom_velocity_image := render_scene_buffers.get_texture_slice(context, custom_velocity, view, 0, 1, 1)
var tile_max_x_image := render_scene_buffers.get_texture_slice(context, tile_max_x, view, 0, 1, 1)
var tile_max_image := render_scene_buffers.get_texture_slice(context, tile_max, view, 0, 1, 1)
var neighbor_max_image := render_scene_buffers.get_texture_slice(context, neighbor_max, view, 0, 1, 1)
var x_groups := floori((render_size.x / sample_step_multiplier - 1) / 16 + 1)
var y_groups := floori((render_size.y - 1) / 16 + 1)
dispatch_stage(tile_max_x_stage,
[
get_sampler_uniform(custom_velocity_image, 0, false),
get_image_uniform(tile_max_x_image, 1)
],
tile_max_x_push_constants_byte_array,
Vector3i(x_groups, y_groups, 1),
"TileMaxX",
view)
x_groups = floori((render_size.x / sample_step_multiplier - 1) / 16 + 1)
y_groups = floori((render_size.y / sample_step_multiplier - 1) / 16 + 1)
dispatch_stage(tile_max_y_stage,
[
get_sampler_uniform(tile_max_x_image, 0, false),
get_image_uniform(tile_max_image, 1)
],
tile_max_y_push_constants_byte_array,
Vector3i(x_groups, y_groups, 1),
"TileMaxY",
view)
for i in JFA_pass_count:
var jf_push_constants : PackedInt32Array = [
i,
last_iteration_index,
0,
16
]
var step_size : float = round(pow(2 + step_exponent_modifier, last_iteration_index - i));
var jf_float_push_constants_test : PackedFloat32Array = [
perpen_error_threshold,
sample_step_multiplier,
temp_intensity,
0,
0,
0,
0,
step_exponent_modifier,
step_size,
max_dilation_radius,
0,
0
]
var jf_byte_array = jf_push_constants.to_byte_array()
jf_byte_array.append_array(jf_float_push_constants_test.to_byte_array())
dispatch_stage(construct_stage,
[
get_sampler_uniform(tile_max_image, 0, false),
get_image_uniform(buffer_a_image, 1),
get_image_uniform(buffer_b_image, 2),
get_sampler_uniform(buffer_a_image, 3, false),
get_sampler_uniform(buffer_b_image, 4, false),
],
jf_byte_array,
Vector3i(x_groups, y_groups, 1),
"Construct Blur",
view)
dispatch_stage(neighbor_max_stage,
[
get_sampler_uniform(tile_max_image, 0, false),
get_sampler_uniform(buffer_b_image if last_iteration_index % 2 else buffer_a_image, 1, false),
get_image_uniform(neighbor_max_image, 2)
],
neighbor_max_push_constants_byte_array,
Vector3i(x_groups, y_groups, 1),
"NeighborMax",
view)
x_groups = floori((render_size.x - 1) / 16 + 1)
y_groups = floori((render_size.y - 1) / 16 + 1)
dispatch_stage(blur_stage,
[
get_sampler_uniform(color_image, 0, false),
get_sampler_uniform(depth_image, 1, false),
get_sampler_uniform(custom_velocity_image, 2, false),
get_sampler_uniform(neighbor_max_image, 3, false),
get_image_uniform(output_color_image, 4),
get_sampler_uniform(tile_max_image, 5, false),
],
byte_array,
Vector3i(x_groups, y_groups, 1),
"Compute Blur",
view)
dispatch_stage(overlay_stage,
[
get_sampler_uniform(output_color_image, 0),
get_image_uniform(color_image, 1),
],
[],
Vector3i(x_groups, y_groups, 1),
"Overlay Result",
view)
rd.draw_command_end_label()

View File

@ -1,7 +1,7 @@
[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://bk5yd5plopwi2"]
[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_ljx3c"]
[ext_resource type="RDShaderFile" uid="uid://bdm5t4l1y3ts7" path="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_new_blur.glsl" id="2_ase62"]
[ext_resource type="RDShaderFile" uid="uid://bdm5t4l1y3ts7" path="res://addons/SphynxMotionBlurToolkit/JumpFlood/ShaderFiles/jump_flood_simple_blur.glsl" id="2_ase62"]
[resource]
script = ExtResource("1_ljx3c")

View File

@ -1,13 +1,6 @@
extends MotionBlurCompositorEffect
extends "res://addons/SphynxMotionBlurToolkit/JumpFlood/base_jump_flood_motion_blur.gd"
class_name SphynxSimpleJumpFloodMotionBlur
@export_group("Motion Blur", "motion_blur_")
# diminishing returns over 16
@export_range(4, 64) var motion_blur_samples: int = 16
# you really don't want this over 0.5, but you can if you want to try
@export_range(0, 0.5, 0.001, "or_greater") var motion_blur_intensity: float = 1
@export_range(0, 1) var motion_blur_center_fade: float = 0.0
@export_group("Shader Stages")
@export var tile_max_x_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/JumpFlood/jump_flood_tile_max_x_stage.tres"):
set(value):
unsubscribe_shader_stage(tile_max_x_stage)
@ -44,46 +37,6 @@ class_name SphynxSimpleJumpFloodMotionBlur
overlay_stage = value
subscirbe_shader_stage(value)
## the portion of speed that is allowed for side bleed of velocities
## during the jfa dilation passes and before backtracking. Getting this a higher value
## would make it so that meshes at movement blur more reliably, but also bleed
## further perpendicularly to their velocity, thus wash elemets behind them out.
@export var perpen_error_threshold : float = 0.5
## an initial step size that can increase the dilation radius proportionally, at the
## sacrifice of some quality in the final resolution of the dilation.[br][br]
## the formula for the maximum radius of the dilation (in pixels) is: pow(2 + step_exponent_modifier, JFA_pass_count) * sample_step_multiplier
@export var sample_step_multiplier : int = 16
## by default, the jump flood makes samples along distances that start
## at 2 to the power of the pass count you want to perform, which is also
## the dilation radius you desire. You can change it to values higher than
## 2 with this variable, and reach higher dilation radius at the sacrifice of
## some accuracy in the dilation.
## the formula for the maximum radius of the dilation (in pixels) is: pow(2 + step_exponent_modifier, JFA_pass_count) * sample_step_multiplier
@export var step_exponent_modifier : float = 1
## the number of passes performed by the jump flood algorithm based dilation,
## each pass added doubles the maximum radius of dilation available.[br][br]
## the formula for the maximum radius of the dilation (in pixels) is: pow(2 + step_exponent_modifier, JFA_pass_count) * sample_step_multiplier
@export var JFA_pass_count : int = 3
## wether this motion blur stays the same intensity below
## target_constant_framerate
@export var framerate_independent : bool = true
## Description: Removes clamping on motion blur scale to allow framerate independent motion
## blur to scale longer than realistically possible when render framerate is higher
## than target framerate.[br][br]
## [color=yellow]Warning:[/color] Turning this on would allow over-blurring of pixels, which
## produces inaccurate results, and would likely cause nausea in players over
## long exposure durations, use with caution and out of artistic intent
@export var uncapped_independence : bool = false
## if framerate_independent is enabled, the blur would simulate
## sutter speeds at that framerate, and up.
@export var target_constant_framerate : float = 30
var tile_max_x : StringName = "tile_max_x"
var tile_max : StringName = "tile_max"
@ -96,17 +49,7 @@ var buffer_a : StringName = "buffer_a"
var buffer_b : StringName = "buffer_b"
var custom_velocity : StringName = "custom_velocity"
var debug_1 : String = "debug_1"
var debug_2 : String = "debug_2"
var debug_3 : String = "debug_3"
var debug_4 : String = "debug_4"
var debug_5 : String = "debug_5"
var debug_6 : String = "debug_6"
var debug_7 : String = "debug_7"
var debug_8 : String = "debug_8"
var temp_motion_blur_intensity : float
var temp_intensity : float
var previous_time : float = 0
@ -117,7 +60,7 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce
previous_time = time
temp_motion_blur_intensity = motion_blur_intensity
temp_intensity = intensity
if framerate_independent:
var capped_frame_time : float = 1 / target_constant_framerate
@ -125,7 +68,7 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce
if !uncapped_independence:
capped_frame_time = min(capped_frame_time, delta_time)
temp_motion_blur_intensity = motion_blur_intensity * capped_frame_time / delta_time
temp_intensity = intensity * capped_frame_time / delta_time
ensure_texture(custom_velocity, render_scene_buffers)
ensure_texture(tile_max_x, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1.))
@ -134,20 +77,12 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce
ensure_texture(buffer_b, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier))
ensure_texture(neighbor_max, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / sample_step_multiplier, 1. / sample_step_multiplier))
ensure_texture(output_color, render_scene_buffers)
ensure_texture(debug_1, render_scene_buffers)
ensure_texture(debug_2, render_scene_buffers)
ensure_texture(debug_3, render_scene_buffers)
ensure_texture(debug_4, render_scene_buffers)
ensure_texture(debug_5, render_scene_buffers)
ensure_texture(debug_6, render_scene_buffers)
ensure_texture(debug_7, render_scene_buffers)
ensure_texture(debug_8, render_scene_buffers)
rd.draw_command_begin_label("Motion Blur", Color(1.0, 1.0, 1.0, 1.0))
var last_iteration_index : int = JFA_pass_count - 1;
var max_dilation_radius : float = pow(2 + step_exponent_modifier, last_iteration_index) * sample_step_multiplier / motion_blur_intensity;
var max_dilation_radius : float = pow(2 + step_exponent_modifier, last_iteration_index) * sample_step_multiplier;
var tile_max_x_push_constants: PackedFloat32Array = [
0,
@ -194,9 +129,9 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce
neighbor_max_push_constants_byte_array.append_array(int_neighbor_max_push_constants.to_byte_array())
var push_constant: PackedFloat32Array = [
motion_blur_samples,
temp_motion_blur_intensity,
motion_blur_center_fade,
samples,
temp_intensity,
center_fade,
Engine.get_frames_drawn() % 8,
last_iteration_index,
sample_step_multiplier,
@ -223,14 +158,6 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce
var tile_max_x_image := render_scene_buffers.get_texture_slice(context, tile_max_x, view, 0, 1, 1)
var tile_max_image := render_scene_buffers.get_texture_slice(context, tile_max, view, 0, 1, 1)
var neighbor_max_image := render_scene_buffers.get_texture_slice(context, neighbor_max, view, 0, 1, 1)
var debug_1_image := render_scene_buffers.get_texture_slice(context, debug_1, view, 0, 1, 1)
var debug_2_image := render_scene_buffers.get_texture_slice(context, debug_2, view, 0, 1, 1)
var debug_3_image := render_scene_buffers.get_texture_slice(context, debug_3, view, 0, 1, 1)
var debug_4_image := render_scene_buffers.get_texture_slice(context, debug_4, view, 0, 1, 1)
var debug_5_image := render_scene_buffers.get_texture_slice(context, debug_5, view, 0, 1, 1)
var debug_6_image := render_scene_buffers.get_texture_slice(context, debug_6, view, 0, 1, 1)
var debug_7_image := render_scene_buffers.get_texture_slice(context, debug_7, view, 0, 1, 1)
var debug_8_image := render_scene_buffers.get_texture_slice(context, debug_8, view, 0, 1, 1)
var x_groups := floori((render_size.x / sample_step_multiplier - 1) / 16 + 1)
var y_groups := floori((render_size.y - 1) / 16 + 1)
@ -238,8 +165,7 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce
dispatch_stage(tile_max_x_stage,
[
get_sampler_uniform(custom_velocity_image, 0, false),
get_sampler_uniform(depth_image, 1, false),
get_image_uniform(tile_max_x_image, 2)
get_image_uniform(tile_max_x_image, 1)
],
tile_max_x_push_constants_byte_array,
Vector3i(x_groups, y_groups, 1),
@ -272,7 +198,7 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce
var jf_float_push_constants_test : PackedFloat32Array = [
perpen_error_threshold,
sample_step_multiplier,
temp_motion_blur_intensity,
temp_intensity,
0,
0,
0,
@ -293,17 +219,13 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce
get_image_uniform(buffer_a_image, 1),
get_image_uniform(buffer_b_image, 2),
get_sampler_uniform(buffer_a_image, 3, false),
get_sampler_uniform(buffer_b_image, 4, false)
get_sampler_uniform(buffer_b_image, 4, false),
],
jf_byte_array,
Vector3i(x_groups, y_groups, 1),
"Construct Blur",
view)
rd.draw_command_end_label()
dispatch_stage(neighbor_max_stage,
[
get_sampler_uniform(tile_max_image, 0, false),
@ -325,15 +247,7 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce
get_sampler_uniform(custom_velocity_image, 2, false),
get_sampler_uniform(neighbor_max_image, 3, false),
get_image_uniform(output_color_image, 4),
get_image_uniform(debug_1_image, 5),
get_image_uniform(debug_2_image, 6),
get_image_uniform(debug_3_image, 7),
get_image_uniform(debug_4_image, 8),
get_image_uniform(debug_5_image, 9),
get_image_uniform(debug_6_image, 10),
get_image_uniform(debug_7_image, 11),
get_image_uniform(debug_8_image, 12),
get_sampler_uniform(tile_max_image, 13, false)
get_sampler_uniform(tile_max_image, 5, false),
],
byte_array,
Vector3i(x_groups, y_groups, 1),
@ -343,7 +257,7 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce
dispatch_stage(overlay_stage,
[
get_sampler_uniform(output_color_image, 0),
get_image_uniform(color_image, 1)
get_image_uniform(color_image, 1),
],
[],
Vector3i(x_groups, y_groups, 1),

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 sphynx-owner
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,152 @@
shader_type spatial;
render_mode unshaded, depth_draw_always, fog_disabled;
uniform sampler2D screen_texture : hint_screen_texture, filter_nearest;
uniform sampler2D depth_texture : hint_depth_texture, filter_nearest;
uniform vec3 local_stretch_axis = vec3(0, 1, 0);
uniform float movement_speed = 0;
uniform int sample_count = 8;
uniform float debug_toggle = 0;
uniform vec4 debug_color : source_color = vec4(0);
//https://www.shadertoy.com/view/fdtfWM
vec3 rotate(float angle, vec3 axis, vec3 point) // NOTE: axis must be unit!
{
float c = cos(angle);
float s = sin(angle);
return c * point + s * cross(axis, point) + (1.0 - c) * (dot(point, axis) * axis); // Rodrigues' Rotation Formula
}
// from https://www.shadertoy.com/view/ftKfzc
float interleaved_gradient_noise(vec2 uv, int FrameId){
uv += float(FrameId) * (vec2(47, 17) * 0.695);
vec3 magic = vec3( 0.06711056, 0.00583715, 52.9829189 );
return fract(magic.z * fract(dot(uv, magic.xy)));
}
vec3 get_projection_onto_plane(vec3 plane_origin, vec3 normal, vec3 vector)
{
float plane_distance = dot(plane_origin, normal);
return vector * plane_distance / dot(normal, vector);
}
float soft_depth_compare(float x, float y, float sze)
{
return clamp(1. - (x - y) / sze, 0., 1.);
}
vec2 intersect_cylinder(vec3 eye_point, vec3 end_point, vec3 origin, vec3 axis, float radius)
{
eye_point -= axis * dot(eye_point - origin, axis) + origin;
end_point -= axis * dot(end_point - origin, axis) + origin;
vec3 direction = end_point - eye_point;
float A = dot(direction, direction);
float B = 2. * dot(eye_point, direction);
float C = dot(eye_point, eye_point) - radius * radius;
float square_component = sqrt(B * B - 4. * A * C);
return vec2(-B + square_component, -B - square_component) / (2. * A);
}
vec2 within_cylinder(vec3 point, vec3 origin, vec3 axis, float radius, float depth, float axis_offset)
{
float within_depth = step(abs(dot(point - origin - axis * axis_offset, axis)), depth / 2.);
vec3 perpendicular_component = point - axis * dot(axis, point - origin) - origin;
float within_radius = step(dot(perpendicular_component, perpendicular_component), radius * radius);
return vec2(within_depth * within_radius, step(0, dot(point - origin, axis)));
}
vec3 color_corrected(vec3 color)
{
return color / mix(
pow((vec3(1.) + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)),
vec3(1.) * (1.0 / 12.92),
lessThan(vec3(1.), vec3(0.04045)));
}
void fragment() {
vec2 screen_uv = SCREEN_UV;
float depth = texture(depth_texture, screen_uv).x;
vec3 ndc = vec3(screen_uv * 2.0 - 1.0, depth);
vec4 world_position = INV_VIEW_MATRIX * INV_PROJECTION_MATRIX * vec4(ndc, 1.0);
world_position.xyz /= world_position.w;
vec4 world_mesh_position = INV_VIEW_MATRIX * INV_PROJECTION_MATRIX * vec4(screen_uv * 2.0 - 1.0, FRAGCOORD.z, 1.0);
world_mesh_position.xyz /= world_mesh_position.w;
vec3 node_relative_position = world_position.xyz - NODE_POSITION_WORLD;
vec3 camera_node_position = NODE_POSITION_WORLD - CAMERA_POSITION_WORLD;
vec3 camera_relative_position = world_position.xyz - CAMERA_POSITION_WORLD;
float on_mesh = 1.;
vec3 raw_clamped_difference = vec3(0.);
node_relative_position = world_mesh_position.xyz - NODE_POSITION_WORLD;
float noise_variation = interleaved_gradient_noise(SCREEN_UV * vec2(textureSize(screen_texture, 0)), int(TIME * 100.)) / float(sample_count);
float sum = 1.;
vec4 base_sample = texture(screen_texture, screen_uv);
vec4 col = base_sample;
float original_depth = 0.05 / depth;
for(int i = 0; i < sample_count; i++)
{
vec3 node_rotated_sample = node_relative_position.xyz + mat3(MODEL_MATRIX) * vec3(movement_speed * (local_stretch_axis * (float(i) / float(sample_count) + noise_variation)));
vec4 current_ndc = (PROJECTION_MATRIX * VIEW_MATRIX * (vec4(node_rotated_sample, 1) + vec4(NODE_POSITION_WORLD, 0)));
current_ndc.xyz /= current_ndc.w;
vec2 current_uv_sample = ((current_ndc + 1.) / 2.).xy ;
float current_depth = texture(depth_texture, current_uv_sample).x;
vec4 current_world_position = INV_VIEW_MATRIX * INV_PROJECTION_MATRIX * vec4(vec3(current_ndc.xy, current_depth), 1.0);
current_world_position.xyz /= current_world_position.w;
current_depth = 0.05 / current_depth;
float current_sample_depth = 0.05 / current_ndc.z;
if (current_uv_sample.x < 0. || current_uv_sample.x > 1. || current_uv_sample.y < 0. || current_uv_sample.y > 1.)
{
continue;
}
float is_inside = step(current_depth - current_sample_depth, 1);
float original_inside = 1. - step(current_depth - original_depth, 1);
float revert_texture = max(is_inside, original_inside);
float weight = 1.;
sum += weight;
col += mix(base_sample, texture(screen_texture, current_uv_sample), revert_texture) * weight;
}
col /= sum;
ALBEDO = col.xyz + debug_color.xyz;//vec3(depth * 10.);//
}

View File

@ -0,0 +1,21 @@
[gd_scene load_steps=5 format=3 uid="uid://b8aytbebcsmv8"]
[ext_resource type="Shader" path="res://addons/SphynxMotionBlurToolkit/LinearBlurToolkit/LinearMotionBlurMesh.gdshader" id="1_m7mjv"]
[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/LinearBlurToolkit/linear_motion_blur_mesh.gd" id="2_glqur"]
[sub_resource type="BoxMesh" id="BoxMesh_lylv4"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_oosyj"]
resource_local_to_scene = true
render_priority = 0
shader = ExtResource("1_m7mjv")
shader_parameter/local_stretch_axis = Vector3(0, 1, 0)
shader_parameter/movement_speed = 0.0
shader_parameter/sample_count = 8
shader_parameter/debug_toggle = 0.0
shader_parameter/debug_color = Color(0, 0, 0, 0)
[node name="LinearMotionBlurMesh" type="MeshInstance3D"]
mesh = SubResource("BoxMesh_lylv4")
surface_material_override/0 = SubResource("ShaderMaterial_oosyj")
script = ExtResource("2_glqur")

View File

@ -0,0 +1,63 @@
extends MeshInstance3D
class_name LinearMotionBlurMesh
@export var target_node : Node3D
## the rotation vector the current mesh blur's around
## locally
@export_enum("x", "y", "z") var local_stretch_axis : int
@export var negate_local_stretch_axis : bool = false
@onready var local_stretch_vector : Vector3 = Vector3(1 if local_stretch_axis == 0 else 0, 1 if local_stretch_axis == 1 else 0, 1 if local_stretch_axis == 2 else 0) * (1 if !negate_local_stretch_axis else -1)
## At what speed does the mesh become visible and start blurring
@export var speed_visibility_threshold : float = 0.2
## make mesh visible for debugging
@export var show_debug : bool = false
var previous_mesh_transform : Transform3D = Transform3D()
var shape_depth : float = 0
func _ready():
get_surface_override_material(0).set_shader_parameter("debug_color", Color(0, 0, 0, 0) if !show_debug else Color(1, 0, 0, 0))
var mesh_aabb : AABB = mesh.get_aabb()
var extent : Vector3 = mesh_aabb.size * global_basis.get_scale()
var center : Vector3 = mesh_aabb.get_center() * global_basis.get_scale()
var all_axis : Array[float] = [extent.x, extent.y, extent.z]
shape_depth = all_axis[local_stretch_axis]
previous_mesh_transform = target_node.global_transform
deferred_update_cylinder_data.call_deferred()
func deferred_update_cylinder_data():
get_surface_override_material(0).set_shader_parameter("local_stretch_axis", local_stretch_vector)
func _process(delta: float) -> void:
var target_transform : Transform3D = target_node.global_transform
var offset : Vector3 = target_transform.origin - previous_mesh_transform.origin
var distance : float = (offset).length()
visible = distance > speed_visibility_threshold
get_surface_override_material(0).set_shader_parameter("movement_speed", distance / (distance + shape_depth))
global_position = target_transform.origin - offset / 2
previous_mesh_transform = target_transform
var alignment_quaternion : Quaternion = Quaternion(global_basis.orthonormalized() * local_stretch_vector, offset.normalized())
global_basis = Basis(alignment_quaternion) * global_basis;
scale = scale * (Vector3(1, 1, 1) - local_stretch_vector) + local_stretch_vector * (distance + shape_depth)

View File

@ -14,9 +14,9 @@ layout(rgba16f, set = 0, binding = 6) uniform image2D past_color_image;
layout(push_constant, std430) uniform Params
{
float minimum_user_threshold;
float importance_bias;
float maximum_jitter_value;
float nan5;
float nan6;
float nan7;
float nan8;
int tile_size;
int sample_count;

View File

@ -0,0 +1,4 @@
extends "res://addons/SphynxMotionBlurToolkit/BaseClasses/mb_compositor_effect.gd"
@export_group("Shader Parameters")
@export var tile_size : int = 40

View File

@ -1,13 +1,7 @@
extends MotionBlurCompositorEffect
extends "res://addons/SphynxMotionBlurToolkit/McGuire/base_mcguire_motion_blur.gd"
class_name McGuireMotionBlur
@export_group("Motion Blur", "motion_blur_")
# diminishing returns over 16
@export_range(4, 64) var motion_blur_samples: int = 25
# you really don't want this over 0.5, but you can if you want to try
@export_range(0, 0.5, 0.001, "or_greater") var motion_blur_intensity: float = 1
@export_range(0, 1) var motion_blur_center_fade: float = 0.0
@export_group("Shader Stages")
@export var blur_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/McGuire/mcguire_blur_stage.tres"):
set(value):
unsubscribe_shader_stage(blur_stage)
@ -44,16 +38,6 @@ class_name McGuireMotionBlur
tile_variance_stage = value
subscirbe_shader_stage(value)
@export var tile_size : int = 40
@export var linear_falloff_slope : float = 1
@export var importance_bias : float = 40
@export var maximum_jitter_value : float = 0.95
@export var minimum_user_threshold : float = 1.5
var output_color: StringName = "output_color"
var tile_max_x : StringName = "tile_max_x"
@ -145,14 +129,14 @@ func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSce
tile_variance_push_constants_byte_array.append_array(int_tile_variance_push_constants.to_byte_array())
var blur_push_constants: PackedFloat32Array = [
minimum_user_threshold,
importance_bias,
maximum_jitter_value,
0,
0,
0,
0,
]
var int_blur_push_constants : PackedInt32Array = [
tile_size,
motion_blur_samples,
samples,
Engine.get_frames_drawn() % 8,
0
]

View File

@ -0,0 +1,9 @@
[gd_resource type="Resource" script_class="BlurVelocityComponentResource" load_steps=2 format=3 uid="uid://cslvcweyejh3c"]
[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/blur_velocity_component_resource.gd" id="1_856ea"]
[resource]
script = ExtResource("1_856ea")
multiplier = 1.0
lower_threshold = 0.0
upper_threshold = 0.0

View File

@ -0,0 +1,9 @@
[gd_resource type="Resource" script_class="BlurVelocityComponentResource" load_steps=2 format=3 uid="uid://iru8ynu04i00"]
[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/blur_velocity_component_resource.gd" id="1_j2iku"]
[resource]
script = ExtResource("1_j2iku")
multiplier = 1.0
lower_threshold = 0.0
upper_threshold = 0.0

View File

@ -1,16 +1,17 @@
extends EnhancedCompositorEffect
extends "res://addons/SphynxMotionBlurToolkit/BaseClasses/enhanced_compositor_effect.gd"
class_name PreBlurProcessor
@export_group("Shader Stages")
@export var pre_blur_processor_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/pre_blur_processing_stage.tres"):
set(value):
unsubscribe_shader_stage(pre_blur_processor_stage)
pre_blur_processor_stage = value
subscirbe_shader_stage(value)
@export var camera_rotation_component : BlurVelocityComponentResource = preload("res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_component.tres")
@export var camera_movement_component : BlurVelocityComponentResource = preload("res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_component.tres")
@export var object_movement_component : BlurVelocityComponentResource = preload("res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_component.tres")
@export_group("Blur Components")
@export var camera_rotation_component : BlurVelocityComponentResource = preload("res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_camera_rotation_component.tres")
@export var camera_movement_component : BlurVelocityComponentResource = preload("res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_camera_movement_component.tres")
@export var object_movement_component : BlurVelocityComponentResource = preload("res://addons/SphynxMotionBlurToolkit/PreBlurProcessing/default_object_movement_component.tres")
var custom_velocity : StringName = "custom_velocity"

View File

@ -146,7 +146,10 @@ void main()
vec3 past_uv = vec3(view_past_ndc.xy * 0.5 + 0.5, view_past_ndc.z);
vec4 view_past_ndc_cache = view_past_ndc;
vec3 camera_uv_change = past_uv - vec3(uvn, depth);
// get just rotation change
world_local_position = mat4(mat3(scene_data.inv_view_matrix)) * vec4(view_position.xyz, 1.0);
@ -186,5 +189,16 @@ void main()
total_velocity = base_velocity;
}
imageStore(vector_output, uvi, vec4(total_velocity, 1.0));
float total_velocity_length = max(FLT_MIN, length(total_velocity));
total_velocity = total_velocity * clamp(total_velocity_length, 0, 1) / total_velocity_length;
imageStore(vector_output, uvi, vec4(total_velocity * (view_past_ndc_cache.w < 0 ? -1 : 1), depth));//, depth));//
#ifdef DEBUG
vec2 velocity = textureLod(vector_sampler, uvn, 0.0).xy;
float velocity_length = length(velocity);
velocity = velocity * clamp(velocity_length, 0, 10) / velocity_length;
imageStore(debug_6_image, uvi, vec4(velocity * (view_past_ndc_cache.w < 0 ? -1 : 1), view_past_ndc_cache.w < 0 ? 1 : 0, 1));
imageStore(debug_7_image, uvi, vec4(camera_uv_change.xy, 0, 1));
#endif
}

View File

@ -1,7 +1,7 @@
[gd_scene load_steps=5 format=3 uid="uid://8p6li7o742g3"]
[ext_resource type="Shader" path="res://RadialBlurTest/radial_blur_mesh.gdshader" id="1_36vys"]
[ext_resource type="Script" path="res://RadialBlurTest/radial_blur_mesh.gd" id="2_cfhks"]
[ext_resource type="Shader" path="res://addons/SphynxMotionBlurToolkit/RadialBlurToolkit/radial_blur_mesh.gdshader" id="1_36vys"]
[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/RadialBlurToolkit/radial_blur_mesh.gd" id="2_cfhks"]
[sub_resource type="CylinderMesh" id="CylinderMesh_pgvyt"]
resource_local_to_scene = true