better heuristics, fixed build error

This commit is contained in:
sphynx-owner
2024-07-22 01:24:01 +03:00
parent 349b3b7c1a
commit 20bcf45ff8
10 changed files with 89 additions and 88 deletions

View File

@ -6,8 +6,8 @@
layout(set = 0, binding = 0) uniform sampler2D depth_sampler;
layout(set = 0, binding = 1) uniform sampler2D velocity_sampler;
layout(rgba16f, set = 0, binding = 2) uniform writeonly image2D buffer_a;
layout(rgba16f, set = 0, binding = 3) uniform writeonly image2D buffer_b;
layout(rg16f, set = 0, binding = 2) uniform writeonly image2D buffer_a;
layout(rg16f, set = 0, binding = 3) uniform writeonly image2D buffer_b;
layout(set = 0, binding = 4) uniform sampler2D buffer_a_sampler;
layout(set = 0, binding = 5) uniform sampler2D buffer_b_sampler;
@ -36,14 +36,14 @@ layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
const int kernel_size = 8;
const vec2 check_step_kernel[kernel_size] = {
vec2(1, 1),
vec2(-1, 0),
vec2(1, 0),
vec2(0, -1),
vec2(0, 1),
vec2(-1, 1),
vec2(1, 0),
vec2(1, -1),
vec2(-1, 0),
vec2(1, 1),
vec2(-1, -1),
vec2(0, -1),
};
vec4 get_value(bool a, vec2 uv, ivec2 render_size)
@ -91,14 +91,16 @@ float get_motion_difference(vec2 V, vec2 V2, float parallel_sensitivity, float p
}
// ----------------------------------------------------------
vec4 sample_fitness(vec2 uv_offset, vec4 uv_sample)
vec4 sample_fitness(vec2 uv_offset, vec4 uv_sample, vec2 render_size)
{
vec2 sample_velocity = -uv_sample.xy;
// if velocity is 0, we never reach it (steps never smaller than 1)
if (dot(sample_velocity, sample_velocity) <= FLT_MIN || uv_sample.w == 0)
{
return vec4(FLT_MAX, FLT_MAX, FLT_MAX, 0);
}
// 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)
@ -118,18 +120,13 @@ vec4 sample_fitness(vec2 uv_offset, vec4 uv_sample)
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 * (1. - step(b.z, a.z))), (1. - step(a.z, b.z)), step(abs(a.w - b.w), 0.5) * step(0.5, a.w));
}
vec2 round_uv(vec2 uv, vec2 render_size)
{
return (round((uv * render_size) - vec2(0.5)) + vec2(0.5)) / render_size;
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));
}
// dilation validation and better sample selection
vec4 get_backtracked_sample(vec2 uvn, vec2 chosen_uv, vec3 chosen_velocity, vec4 best_sample_fitness, vec2 render_size)
{
//return vec4(chosen_uv, best_sample_fitness.z, 0);// comment this to enable backtracking
//return vec4(chosen_uv, best_sample_fitness.z, best_sample_fitness.w);// comment this to enable backtracking
float smallest_step = 1 / max(render_size.x, render_size.y);
// choose maximum range to check along (matches with implementation in blur stage)
@ -137,7 +134,7 @@ vec4 get_backtracked_sample(vec2 uvn, vec2 chosen_uv, vec3 chosen_velocity, vec4
vec2 best_uv = chosen_uv;
//float best_multiplier = best_sample_fitness.y;
float best_multiplier = best_sample_fitness.y;
float best_depth = best_sample_fitness.z;
@ -157,7 +154,7 @@ vec4 get_backtracked_sample(vec2 uvn, vec2 chosen_uv, vec3 chosen_velocity, vec4
continue;
}
vec2 check_uv = round_uv(uvn - chosen_velocity.xy * velocity_multiplier, render_size);
vec2 check_uv = uvn - chosen_velocity.xy * velocity_multiplier;
if(any(notEqual(check_uv, clamp(check_uv, vec2(0.0), vec2(1.0)))))
{
@ -176,18 +173,18 @@ vec4 get_backtracked_sample(vec2 uvn, vec2 chosen_uv, vec3 chosen_velocity, vec4
if((abs(current_depth - best_sample_fitness.z) < params.depth_match_threshold) && (velocity_difference <= smallest_velocity_difference))
{
best_uv = check_uv;
//best_multiplier = velocity_multiplier;
best_multiplier = velocity_multiplier;
best_depth = current_depth;
if(steps_to_compare == 0)
{
return vec4(best_uv, best_depth, 0);
return vec4(best_uv, best_depth, best_multiplier);
}
steps_to_compare--;
}
// if a sample was found and we lost footing after, go with that found sample right away
else if(initial_steps_to_compare > steps_to_compare)
{
return vec4(best_uv, best_depth, 0);
return vec4(best_uv, best_depth, best_multiplier);
}
}
@ -202,10 +199,11 @@ void main()
{
return;
}
// must be on pixel center for whole values (tested)
// must be on pixel center for whole values
vec2 uvn = (vec2(uvi) + vec2(0.5)) / render_size;
vec2 uv_step = vec2(params.step_size) / render_size;
vec2 uv_step = vec2(round(params.step_size)) / render_size;
vec4 best_sample_fitness = vec4(FLT_MAX, FLT_MAX, FLT_MAX, 0);
@ -236,7 +234,7 @@ void main()
vec4 uv_sample = vec4(textureLod(velocity_sampler, check_uv, 0.0).xyz, textureLod(depth_sampler, check_uv, 0.0).x);
vec4 current_sample_fitness = sample_fitness(step_offset, uv_sample);
vec4 current_sample_fitness = sample_fitness(step_offset, uv_sample, render_size);
if (is_sample_better(current_sample_fitness, best_sample_fitness) > 0.5)
{
@ -253,8 +251,8 @@ void main()
}
float depth = textureLod(depth_sampler, uvn, 0.0).x;
// best_sample_fitness.z contains the depth of the texture + offset of velocity z
// best_sample_fitness.z contains the depth of the texture + offset of velocity z
vec4 backtracked_sample = get_backtracked_sample(uvn, chosen_uv, chosen_velocity, best_sample_fitness, render_size);
if(best_sample_fitness.w == 0 || depth > backtracked_sample.z)
@ -263,17 +261,14 @@ void main()
return;
}
set_value(set_a, uvi, vec4(backtracked_sample.xy, 0, backtracked_sample.w), render_size);
set_value(set_a, uvi, backtracked_sample, render_size);
return;
}
// ------ sample fitness conditions -------
//
// if((a.w == b.w) && (a.w == 1))
// {
// return a.z < b.z ? 1. : 0.;
// return a.z < b.z ? 0. : 1.;
// }
//
// float nearer = a.z > b.z ? 1 : 0;
//
// return a.x * b.w * nearer < b.x * a.w ? 1. : 0.;
// return a.x * b.w < b.x * a.w ? 1. : 0.;

View File

@ -2,7 +2,7 @@
importer="glsl"
type="RDShaderFile"
uid="uid://yfjbb3iso4jt"
uid="uid://3v1b0hrdm7nw"
path="res://.godot/imported/jfp_backtracking_experimental.glsl-d67307f6899fed647164be410a7debc8.res"
[deps]

View File

@ -96,6 +96,8 @@ var rd: RenderingDevice
var linear_sampler: RID
var nearest_sampler : RID
var construct_shader : RID
var construct_pipeline : RID
@ -142,7 +144,14 @@ func _initialize_compute():
sampler_state.repeat_u = RenderingDevice.SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE
sampler_state.repeat_v = RenderingDevice.SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE
linear_sampler = rd.sampler_create(sampler_state)
sampler_state.min_filter = RenderingDevice.SAMPLER_FILTER_NEAREST
sampler_state.mag_filter = RenderingDevice.SAMPLER_FILTER_NEAREST
sampler_state.repeat_u = RenderingDevice.SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE
sampler_state.repeat_v = RenderingDevice.SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE
nearest_sampler = rd.sampler_create(sampler_state)
var construct_shader_spirv : RDShaderSPIRV = construction_pass.get_spirv()
construct_shader = rd.shader_create_from_spirv(construct_shader_spirv)
construct_pipeline = rd.compute_pipeline_create(construct_shader)
@ -162,11 +171,11 @@ func get_image_uniform(image: RID, binding: int) -> RDUniform:
uniform.add_id(image)
return uniform
func get_sampler_uniform(image: RID, binding: int) -> RDUniform:
func get_sampler_uniform(image: RID, binding: int, linear : bool = true) -> RDUniform:
var uniform: RDUniform = RDUniform.new()
uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_SAMPLER_WITH_TEXTURE
uniform.binding = binding
uniform.add_id(linear_sampler)
uniform.add_id(linear_sampler if linear else nearest_sampler)
uniform.add_id(image)
return uniform
@ -200,8 +209,8 @@ func _render_callback(p_effect_callback_type, p_render_data):
return
ensure_texture(texture, render_scene_buffers)
ensure_texture(buffer_a, render_scene_buffers)
ensure_texture(buffer_b, render_scene_buffers)
ensure_texture(buffer_a, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16_SFLOAT)
ensure_texture(buffer_b, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16_SFLOAT)
ensure_texture(past_color, render_scene_buffers)
ensure_texture(custom_velocity, render_scene_buffers)
@ -250,12 +259,12 @@ func _render_callback(p_effect_callback_type, p_render_data):
var y_groups := floori((render_size.y - 1) / 16 + 1)
tex_uniform_set = UniformSetCacheRD.get_cache(construct_shader, 0, [
get_sampler_uniform(depth_image, 0),
get_sampler_uniform(custom_velocity_image, 1),
get_sampler_uniform(depth_image, 0, false),
get_sampler_uniform(custom_velocity_image, 1, false),
get_image_uniform(buffer_a_image, 2),
get_image_uniform(buffer_b_image, 3),
get_sampler_uniform(buffer_a_image, 4),
get_sampler_uniform(buffer_b_image, 5)
get_sampler_uniform(buffer_a_image, 4, false),
get_sampler_uniform(buffer_b_image, 5, false)
])
compute_list = rd.compute_list_begin()
@ -300,10 +309,10 @@ func _render_callback(p_effect_callback_type, p_render_data):
rd.draw_command_begin_label("Compute blur " + str(view), Color(1.0, 1.0, 1.0, 1.0))
tex_uniform_set = UniformSetCacheRD.get_cache(motion_blur_shader, 0, [
get_sampler_uniform(color_image, 0),
get_sampler_uniform(depth_image, 1),
get_sampler_uniform(custom_velocity_image, 2),
get_sampler_uniform(buffer_b_image if last_iteration_index % 2 else buffer_a_image, 3),
get_sampler_uniform(color_image, 0, false),
get_sampler_uniform(depth_image, 1, false),
get_sampler_uniform(custom_velocity_image, 2, false),
get_sampler_uniform(buffer_b_image if last_iteration_index % 2 else buffer_a_image, 3, false),
get_image_uniform(texture_image, 4),
get_image_uniform(past_color_image, 5),
])

View File

@ -64,11 +64,6 @@ float soft_depth_compare(float depth_X, float depth_Y)
}
// -------------------------------------------------------
vec2 round_uv(vec2 uv, vec2 render_size)
{
return (round((uv * render_size) - vec2(0.5)) + vec2(0.5)) / render_size;
}
void main()
{
ivec2 render_size = ivec2(textureSize(color_sampler, 0));
@ -122,11 +117,7 @@ void main()
vec4 col = base_color * total_weight;
float dominant_depth = textureLod(depth_sampler, velocity_map_sample.xy, 0.0).x;
float naive_depth = textureLod(depth_sampler, uvn, 0.0).x;
// is dilation in front of ground truth (have we started sampling inside a dilation)
float dilation_foreground = step(naive_depth, dominant_depth - 0.000001);
for (int i = 1; i < params.motion_blur_samples; i++)
{
@ -134,9 +125,9 @@ void main()
naive_offset += naive_step_sample;
vec2 dominant_uvo = round_uv(uvn + dominant_offset.xy, render_size);
vec2 dominant_uvo = uvn + dominant_offset.xy;
vec2 naive_uvo = round_uv(uvn + naive_offset.xy, render_size);
vec2 naive_uvo = uvn + naive_offset.xy;
if (any(notEqual(dominant_uvo, clamp(dominant_uvo, vec2(0.0), vec2(1.0)))))
{
@ -145,27 +136,21 @@ void main()
velocity_map_step_sample = textureLod(velocity_map, dominant_uvo, 0.0);
vec3 current_velocity = -textureLod(vector_sampler, velocity_map_step_sample.xy, 0.0).xyz;
float current_dominant_depth = textureLod(depth_sampler, velocity_map_step_sample.xy, 0.0).x;
vec3 current_dominant_velocity = -textureLod(vector_sampler, velocity_map_step_sample.xy, 0.0).xyz;
float current_naive_depth = textureLod(depth_sampler, dominant_uvo, 0.0).x;
// is current velocity different than dilated velocity
float motion_difference = get_motion_difference(dominant_velocity.xy, current_velocity.xy, 0.1);
float motion_difference = get_motion_difference(dominant_velocity.xy, current_dominant_velocity.xy, 0.1);
// is current depth closer than origin of dilation (object in the foreground)
float foreground = step(naive_depth + dominant_offset.z, current_naive_depth - 0.0001);
// is dilation in front of current ground truth (are we within a dilation still)
float naive_foreground = step(0.05 / dominant_depth + 0.1, 0.05 / current_naive_depth);
// if we are sampling a foreground object and its velocity is different, discard this sample (prevent ghosting)
float sample_weight = 1 - (foreground * motion_difference);
float naive_sample_weight = 1 - (foreground * motion_difference);
// if we started from and are still inside a dilation, choose the naive values for blurring
float dominant_naive_mix = dilation_foreground * naive_foreground;
float dominant_naive_mix = 1. - step(0.9, motion_difference);
vec2 sample_uv = mix(dominant_uvo, naive_uvo, dominant_naive_mix);
vec2 sample_uv = mix(naive_uvo, dominant_uvo, dominant_naive_mix);
total_weight += mix(sample_weight, naive_sample_weight, dominant_naive_mix);
total_weight += sample_weight;
col += textureLod(color_sampler, sample_uv, 0.0) * sample_weight;
}
@ -197,8 +182,8 @@ void main()
if(params.debug_page == 1)
{
tl_col = vec4(naive_depth * 10);
tr_col = vec4(dilation_foreground);
bl_col = vec4(dominant_depth * 10);
tr_col = textureLod(color_sampler, velocity_map_sample.xy, 0.0);//
//bl_col = vec4(dominant_depth * 10);
br_col = col;
}

View File

@ -2,7 +2,7 @@
importer="glsl"
type="RDShaderFile"
uid="uid://c3hemlr50tv6p"
uid="uid://wfmvke70qcpa"
path="res://.godot/imported/jump_flood_blur.glsl-df0c6b7cc65d8b0520871790f9075253.res"
[deps]

View File

@ -2,7 +2,7 @@
importer="glsl"
type="RDShaderFile"
uid="uid://d03sqqhg3n1ys"
uid="uid://bbnb4hw0aoqy1"
path="res://.godot/imported/jump_flood_overlay.glsl-764d3c488a9e9576eab825591e868325.res"
[deps]

View File

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

View File

@ -6,9 +6,9 @@ class_name PreBlurProcessor
pre_blur_processor_shader_file = value
_init()
@export var camera_rotation_component : BlurVelocityComponentResource = BlurVelocityComponentResource.new()
@export var camera_movement_component : BlurVelocityComponentResource = BlurVelocityComponentResource.new()
@export var object_movement_component : BlurVelocityComponentResource = BlurVelocityComponentResource.new()
@export var camera_rotation_component : BlurVelocityComponentResource = preload("res://addons/PreBlurProcessing/default_component.tres")
@export var camera_movement_component : BlurVelocityComponentResource = preload("res://addons/PreBlurProcessing/default_component.tres")
@export var object_movement_component : BlurVelocityComponentResource = preload("res://addons/PreBlurProcessing/default_component.tres")
var context: StringName = "MotionBlur"
@ -16,6 +16,8 @@ var rd: RenderingDevice
var linear_sampler: RID
var nearest_sampler : RID
var construct_shader : RID
var construct_pipeline : RID
@ -47,6 +49,12 @@ func _initialize_compute():
sampler_state.repeat_v = RenderingDevice.SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE
linear_sampler = rd.sampler_create(sampler_state)
sampler_state.min_filter = RenderingDevice.SAMPLER_FILTER_NEAREST
sampler_state.mag_filter = RenderingDevice.SAMPLER_FILTER_NEAREST
sampler_state.repeat_u = RenderingDevice.SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE
sampler_state.repeat_v = RenderingDevice.SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE
nearest_sampler = rd.sampler_create(sampler_state)
var shader_spirv: RDShaderSPIRV = pre_blur_processor_shader_file.get_spirv()
pre_blur_processor_shader = rd.shader_create_from_spirv(shader_spirv)
pre_blur_processor_pipeline = rd.compute_pipeline_create(pre_blur_processor_shader)
@ -58,11 +66,11 @@ func get_image_uniform(image: RID, binding: int) -> RDUniform:
uniform.add_id(image)
return uniform
func get_sampler_uniform(image: RID, binding: int) -> RDUniform:
func get_sampler_uniform(image: RID, binding: int, linear : bool = true) -> RDUniform:
var uniform: RDUniform = RDUniform.new()
uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_SAMPLER_WITH_TEXTURE
uniform.binding = binding
uniform.add_id(linear_sampler)
uniform.add_id(linear_sampler if linear else nearest_sampler)
uniform.add_id(image)
return uniform
@ -102,7 +110,6 @@ func _render_callback(p_effect_callback_type, p_render_data : RenderData):
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 velocity_image := render_scene_buffers.get_velocity_layer(view)
var custom_velocity_image := render_scene_buffers.get_texture_slice(context, custom_velocity, view, 0, 1, 1)
@ -121,11 +128,9 @@ func _render_callback(p_effect_callback_type, p_render_data : RenderData):
rd.draw_command_begin_label("Process Velocity Buffer " + str(view), Color(1.0, 1.0, 1.0, 1.0))
tex_uniform_set = UniformSetCacheRD.get_cache(pre_blur_processor_shader, 0, [
get_sampler_uniform(color_image, 0),
get_sampler_uniform(depth_image, 1),
get_sampler_uniform(velocity_image, 2),
get_image_uniform(custom_velocity_image, 3),
get_image_uniform(color_image, 4),
get_sampler_uniform(depth_image, 0, false),
get_sampler_uniform(velocity_image, 1, false),
get_image_uniform(custom_velocity_image, 2),
scene_data_buffer_uniform,
])

View File

@ -4,11 +4,9 @@
#define FLT_MAX 3.402823466e+38
#define FLT_MIN 1.175494351e-38
layout(set = 0, binding = 0) uniform sampler2D color_sampler;
layout(set = 0, binding = 1) uniform sampler2D depth_sampler;
layout(set = 0, binding = 2) uniform sampler2D vector_sampler;
layout(rgba32f, set = 0, binding = 3) uniform writeonly image2D vector_output;
layout(rgba16f, set = 0, binding = 4) uniform writeonly image2D color_output;
layout(set = 0, binding = 0) uniform sampler2D depth_sampler;
layout(set = 0, binding = 1) uniform sampler2D vector_sampler;
layout(rgba32f, set = 0, binding = 2) uniform writeonly image2D vector_output;
struct SceneData {
highp mat4 projection_matrix;
@ -119,7 +117,7 @@ float get_view_depth(float depth)
void main()
{
ivec2 render_size = ivec2(textureSize(color_sampler, 0));
ivec2 render_size = ivec2(textureSize(vector_sampler, 0));
ivec2 uvi = ivec2(gl_GlobalInvocationID.xy);
if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y))
{

View File

@ -2,7 +2,7 @@
importer="glsl"
type="RDShaderFile"
uid="uid://tx5dpg4cese4"
uid="uid://ccg27o4i1gfty"
path="res://.godot/imported/pre_blur_processor.glsl-15aad2fcd84f6b03da65e9fe7bb8e345.res"
[deps]