mirror of
https://github.com/sphynx-owner/JFA_driven_motion_blur_addon.git
synced 2025-09-19 04:06:08 +08:00
Multiple fixes, Higher blur Quality
- better blending - handle velocity buffer projection edge case - handle blur edge cases
This commit is contained in:
@ -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()
|
||||
|
@ -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")
|
||||
|
@ -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);
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
}
|
@ -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
|
@ -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),
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
}
|
@ -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]
|
||||
|
@ -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));
|
||||
}
|
@ -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);
|
||||
}
|
@ -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
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
@ -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]
|
||||
|
@ -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
|
||||
}
|
@ -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]
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
}
|
@ -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]
|
||||
|
@ -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
|
||||
}
|
@ -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]
|
||||
|
@ -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
|
@ -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()
|
@ -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")
|
@ -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")
|
@ -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),
|
||||
|
@ -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")
|
@ -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()
|
@ -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")
|
||||
|
@ -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),
|
||||
|
21
addons/SphynxMotionBlurToolkit/LICENSE
Normal file
21
addons/SphynxMotionBlurToolkit/LICENSE
Normal 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.
|
@ -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.);//
|
||||
}
|
@ -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")
|
@ -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)
|
@ -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;
|
||||
|
@ -0,0 +1,4 @@
|
||||
extends "res://addons/SphynxMotionBlurToolkit/BaseClasses/mb_compositor_effect.gd"
|
||||
|
||||
@export_group("Shader Parameters")
|
||||
@export var tile_size : int = 40
|
@ -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
|
||||
]
|
||||
|
@ -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
|
@ -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
|
@ -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"
|
||||
|
||||
|
@ -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
|
||||
}
|
@ -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
|
||||
|
Reference in New Issue
Block a user