mirror of
https://github.com/sphynx-owner/JFA_driven_motion_blur_addon.git
synced 2025-09-19 04:06:08 +08:00
Complete overhaul, new implementations
- Overhauled file structure to be on addons for universality - Streamlined compositor shader stages with custom classes and resources - Added previous proven implementations (McGuire, Guertin) - entirely new and improved jump flood implementation, more realistic, robust, and performant
This commit is contained in:
@ -0,0 +1,156 @@
|
||||
#[compute]
|
||||
#version 450
|
||||
|
||||
#define FLT_MAX 3.402823466e+38
|
||||
#define FLT_MIN 1.175494351e-38
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D color_sampler;
|
||||
layout(set = 0, binding = 1) uniform sampler2D depth_sampler;
|
||||
layout(set = 0, binding = 2) uniform sampler2D velocity_sampler;
|
||||
layout(set = 0, binding = 3) uniform sampler2D neighbor_max;
|
||||
layout(set = 0, binding = 4) uniform sampler2D tile_variance;
|
||||
layout(rgba16f, set = 0, binding = 5) uniform writeonly image2D output_color;
|
||||
layout(rgba16f, set = 0, binding = 6) uniform image2D debug_1_image;
|
||||
layout(rgba16f, set = 0, binding = 7) uniform image2D debug_2_image;
|
||||
|
||||
layout(push_constant, std430) uniform Params
|
||||
{
|
||||
float minimum_user_threshold;
|
||||
float importance_bias;
|
||||
float maximum_jitter_value;
|
||||
float nan8;
|
||||
int tile_size;
|
||||
int sample_count;
|
||||
int frame;
|
||||
int nan4;
|
||||
} params;
|
||||
|
||||
layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
|
||||
|
||||
// McGuire's functions https://docs.google.com/document/d/1IIlAKTj-O01hcXEdGxTErQbCHO9iBmRx6oFUy_Jm0fI/edit
|
||||
// ----------------------------------------------------------
|
||||
float soft_depth_compare(float depth_X, float depth_Y, float sze)
|
||||
{
|
||||
return clamp(1 - (depth_X - depth_Y) / sze, 0, 1);
|
||||
}
|
||||
|
||||
float cone(float T, float v)
|
||||
{
|
||||
return clamp(1 - abs(T) / v, 0, 1);
|
||||
}
|
||||
|
||||
float cylinder(float T, float v)
|
||||
{
|
||||
return 1.0 - smoothstep(0.95 * v, 1.05 * v, abs(T));
|
||||
}
|
||||
// ----------------------------------------------------------
|
||||
|
||||
// Guertin's functions https://research.nvidia.com/sites/default/files/pubs/2013-11_A-Fast-and/Guertin2013MotionBlur-small.pdf
|
||||
// ----------------------------------------------------------
|
||||
float z_compare(float a, float b)
|
||||
{
|
||||
return clamp(1. - (a - b) / min(a, b), 0, 1);
|
||||
}
|
||||
// ----------------------------------------------------------
|
||||
|
||||
// from https://www.shadertoy.com/view/ftKfzc
|
||||
// ----------------------------------------------------------
|
||||
float interleaved_gradient_noise(vec2 uv, int FrameId){
|
||||
uv += float(FrameId) * (vec2(47, 17) * 0.695);
|
||||
|
||||
vec3 magic = vec3( 0.06711056, 0.00583715, 52.9829189 );
|
||||
|
||||
return fract(magic.z * fract(dot(uv, magic.xy)));
|
||||
}
|
||||
// ----------------------------------------------------------
|
||||
|
||||
vec2 sample_random_offset(vec2 uv, float j)
|
||||
{
|
||||
return vec2(0);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 render_size = ivec2(textureSize(color_sampler, 0));
|
||||
ivec2 tile_render_size = ivec2(textureSize(neighbor_max, 0));
|
||||
ivec2 uvi = ivec2(gl_GlobalInvocationID.xy);
|
||||
if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
vec2 x = (vec2(uvi) + vec2(0.5)) / vec2(render_size);
|
||||
|
||||
float j = interleaved_gradient_noise(uvi, params.frame) * 2. - 1.;
|
||||
|
||||
vec2 vn = textureLod(neighbor_max, x, 0.0).xy * render_size / 2;
|
||||
|
||||
float vn_length = max(0.5, length(vn));
|
||||
|
||||
vec4 base_color = textureLod(color_sampler, x, 0.0);
|
||||
|
||||
if(vn_length <= 0.5)
|
||||
{
|
||||
imageStore(output_color, uvi, base_color);
|
||||
imageStore(debug_1_image, uvi, base_color);
|
||||
imageStore(debug_2_image, uvi, vec4(vn / render_size * 2, 0, 1));
|
||||
return;
|
||||
}
|
||||
|
||||
vec2 wn = normalize(vn);
|
||||
|
||||
vec2 vx = textureLod(velocity_sampler, x, 0.0).xy * render_size / 2;
|
||||
|
||||
float vx_length = max(0.5, length(vx));
|
||||
|
||||
vec2 wp = vec2(-wn.y, wn.x);
|
||||
|
||||
if(dot(wp, vx) < 0)
|
||||
{
|
||||
wp = -wp;
|
||||
}
|
||||
|
||||
vec2 wc = normalize(mix(wp, normalize(vx), (vx_length - 0.5) / params.minimum_user_threshold));
|
||||
|
||||
float zx = -0.05 / textureLod(depth_sampler, x, 0.0).x;
|
||||
|
||||
float weight = params.sample_count / (params.importance_bias * vx_length);
|
||||
|
||||
vec4 sum = base_color * weight;
|
||||
|
||||
for(int i = 0; i < params.sample_count; i++)
|
||||
{
|
||||
float t = mix(-1.0, 1.0, (i + j * params.maximum_jitter_value + 1.0) / (params.sample_count + 1.0));
|
||||
|
||||
vec2 d = ((i % 2) > 0) ? vx : vn;
|
||||
|
||||
float T = t * vn_length;
|
||||
|
||||
vec2 y = x + t * d / render_size;
|
||||
|
||||
vec2 vy = textureLod(velocity_sampler, y, 0.0).xy * render_size / 2;
|
||||
|
||||
float vy_length = max(0.5, length(vy));
|
||||
|
||||
float zy = -0.05 / textureLod(depth_sampler, y, 0.0).x;
|
||||
|
||||
float f = z_compare(zx, zy);
|
||||
float b = z_compare(zy, zx);
|
||||
|
||||
float wa = dot(wc, d);
|
||||
float wb = dot(normalize(vy), d);
|
||||
|
||||
float ay = f * cone(T, 1. / vy_length) * max(FLT_MIN, abs(wb))
|
||||
+ b * cone(T, 1. / vx_length) * max(FLT_MIN, abs(wa))
|
||||
+ cylinder(T, min(vx_length, vy_length)) * 2 * max(FLT_MIN, max(abs(wa), abs(wb)));
|
||||
|
||||
weight += abs(ay);
|
||||
sum += ay * textureLod(color_sampler, y, 0.0);
|
||||
}
|
||||
|
||||
sum /= weight;
|
||||
|
||||
imageStore(output_color, uvi, sum);
|
||||
imageStore(debug_1_image, uvi, sum);
|
||||
imageStore(debug_2_image, uvi, vec4(vn / render_size * 2, 0, 1));
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
[remap]
|
||||
|
||||
importer="glsl"
|
||||
type="RDShaderFile"
|
||||
uid="uid://cbdyfuhewqag8"
|
||||
path="res://.godot/imported/guertin_blur.glsl-bc647b2d965e982b702f0e036903e801.res"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_blur.glsl"
|
||||
dest_files=["res://.godot/imported/guertin_blur.glsl-bc647b2d965e982b702f0e036903e801.res"]
|
||||
|
||||
[params]
|
||||
|
@ -0,0 +1,184 @@
|
||||
#[compute]
|
||||
#version 450
|
||||
|
||||
#define FLT_MAX 3.402823466e+38
|
||||
#define FLT_MIN 1.175494351e-38
|
||||
#define M_PI 3.1415926535897932384626433832795
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D color_sampler;
|
||||
layout(set = 0, binding = 1) uniform sampler2D depth_sampler;
|
||||
layout(set = 0, binding = 2) uniform sampler2D velocity_sampler;
|
||||
layout(set = 0, binding = 3) uniform sampler2D neighbor_max;
|
||||
layout(set = 0, binding = 4) uniform sampler2D tile_variance;
|
||||
layout(rgba16f, set = 0, binding = 5) uniform writeonly image2D output_color;
|
||||
layout(rgba16f, set = 0, binding = 6) uniform image2D past_color_image;
|
||||
layout(rgba16f, set = 0, binding = 6) uniform image2D debug_1_image;
|
||||
layout(rgba16f, set = 0, binding = 7) uniform image2D debug_2_image;
|
||||
layout(rgba16f, set = 0, binding = 8) uniform image2D debug_3_image;
|
||||
layout(rgba16f, set = 0, binding = 9) uniform image2D debug_4_image;
|
||||
|
||||
layout(push_constant, std430) uniform Params
|
||||
{
|
||||
float minimum_user_threshold;
|
||||
float importance_bias;
|
||||
float maximum_jitter_value;
|
||||
float nan8;
|
||||
int tile_size;
|
||||
int sample_count;
|
||||
int frame;
|
||||
int nan4;
|
||||
} params;
|
||||
|
||||
layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
|
||||
|
||||
// McGuire's functions https://docs.google.com/document/d/1IIlAKTj-O01hcXEdGxTErQbCHO9iBmRx6oFUy_Jm0fI/edit
|
||||
// ----------------------------------------------------------
|
||||
float soft_depth_compare(float depth_X, float depth_Y, float sze)
|
||||
{
|
||||
return clamp(1 - (depth_X - depth_Y) / sze, 0, 1);
|
||||
}
|
||||
|
||||
float cone(float T, float v)
|
||||
{
|
||||
return clamp(1 - T / v, 0, 1);
|
||||
}
|
||||
|
||||
float cylinder(float T, float v)
|
||||
{
|
||||
return 1.0 - smoothstep(0.95 * v, 1.05 * v, T);
|
||||
}
|
||||
// ----------------------------------------------------------
|
||||
|
||||
// Guertin's functions https://research.nvidia.com/sites/default/files/pubs/2013-11_A-Fast-and/Guertin2013MotionBlur-small.pdf
|
||||
// ----------------------------------------------------------
|
||||
float z_compare(float a, float b, float sze)
|
||||
{
|
||||
return clamp(1. - sze * (a - b) / min(a, b), 0, 1);
|
||||
}
|
||||
// ----------------------------------------------------------
|
||||
|
||||
// from https://www.shadertoy.com/view/ftKfzc
|
||||
// ----------------------------------------------------------
|
||||
float interleaved_gradient_noise(vec2 uv){
|
||||
uv += float(params.frame) * (vec2(47, 17) * 0.695);
|
||||
|
||||
vec3 magic = vec3( 0.06711056, 0.00583715, 52.9829189 );
|
||||
|
||||
return fract(magic.z * fract(dot(uv, magic.xy)));
|
||||
}
|
||||
// ----------------------------------------------------------
|
||||
|
||||
// from https://github.com/bradparks/KinoMotion__unity_motion_blur/tree/master
|
||||
// ----------------------------------------------------------
|
||||
vec2 safenorm(vec2 v)
|
||||
{
|
||||
float l = max(length(v), 1e-6);
|
||||
return v / l * int(1 >= 0.5);
|
||||
}
|
||||
|
||||
vec2 jitter_tile(vec2 uvi)
|
||||
{
|
||||
float rx, ry;
|
||||
float angle = interleaved_gradient_noise(uvi + vec2(2, 0)) * M_PI * 2;
|
||||
rx = cos(angle);
|
||||
ry = sin(angle);
|
||||
return vec2(rx, ry) / textureSize(neighbor_max, 0) / 4;
|
||||
}
|
||||
// ----------------------------------------------------------
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 render_size = ivec2(textureSize(color_sampler, 0));
|
||||
ivec2 tile_render_size = ivec2(textureSize(neighbor_max, 0));
|
||||
ivec2 uvi = ivec2(gl_GlobalInvocationID.xy);
|
||||
if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
vec2 x = (vec2(uvi) + vec2(0.5)) / vec2(render_size);
|
||||
|
||||
float j = interleaved_gradient_noise(uvi) * 2. - 1.;
|
||||
|
||||
vec2 vn = textureLod(neighbor_max, x + jitter_tile(uvi), 0.0).xy * render_size / 2.;
|
||||
|
||||
float vn_length = length(vn);
|
||||
|
||||
vec4 base_color = textureLod(color_sampler, x, 0.0);
|
||||
|
||||
if(vn_length < 0.5)
|
||||
{
|
||||
imageStore(output_color, uvi, base_color);
|
||||
imageStore(debug_1_image, uvi, base_color);
|
||||
imageStore(debug_2_image, uvi, vec4(vn / render_size * 2, 0, 1));
|
||||
imageStore(debug_3_image, uvi, vec4(0));
|
||||
imageStore(debug_4_image, uvi, vec4(0));
|
||||
return;
|
||||
}
|
||||
|
||||
vec2 wn = safenorm(vn);
|
||||
|
||||
vec2 vx = textureLod(velocity_sampler, x, 0.0).xy * render_size / 2.;
|
||||
|
||||
float vx_length = max(0.5, length(vx));
|
||||
|
||||
vec2 wx = safenorm(vx);
|
||||
|
||||
vec2 wp = vec2(-wn.y, wn.x);
|
||||
|
||||
if(dot(wp, vx) < 0)
|
||||
{
|
||||
wp = -wp;
|
||||
}
|
||||
|
||||
vec2 wc = safenorm(mix(wp, wx, clamp((vx_length - 0.5) / params.minimum_user_threshold, 0, 1)));
|
||||
|
||||
float zx = -0.05 / max(FLT_MIN, textureLod(depth_sampler, x, 0.0).x);
|
||||
|
||||
float total_weight = params.sample_count / (params.importance_bias * vx_length);
|
||||
|
||||
vec4 sum = base_color * total_weight;
|
||||
|
||||
for(int i = 0; i < params.sample_count; i++)
|
||||
{
|
||||
float t = mix(-1.0, 1.0, (i + j * params.maximum_jitter_value + 1.0) / (params.sample_count + 1.0));
|
||||
|
||||
vec2 d = ((i % 2) > 0) ? vx : vn;
|
||||
|
||||
vec2 wd = safenorm(d);
|
||||
|
||||
float T = abs(t * vn_length);
|
||||
|
||||
vec2 y = x + t * d / render_size;
|
||||
|
||||
float wa = dot(wc, wd);
|
||||
|
||||
vec2 vy = textureLod(velocity_sampler, y, 0.0).xy * render_size / 2;
|
||||
|
||||
float vy_length = max(0.5, length(vy));
|
||||
|
||||
float zy = -0.05 / max(FLT_MIN, textureLod(depth_sampler, y, 0.0).x);
|
||||
|
||||
float f = z_compare(zy, zx, 15);
|
||||
float b = z_compare(zx, zy, 15);
|
||||
|
||||
float wb = abs(dot(vy / vy_length, wd));
|
||||
|
||||
float weight = 0.0;
|
||||
weight += f * cone(T, vy_length) * wb;
|
||||
weight += b * cone(T, vx_length) * wa;
|
||||
weight += cylinder(T, min(vy_length, vx_length)) * 2. * max(wa, wb);
|
||||
|
||||
total_weight += weight;
|
||||
|
||||
sum += weight * textureLod(color_sampler, y, 0.0);
|
||||
}
|
||||
|
||||
sum /= total_weight;
|
||||
|
||||
imageStore(output_color, uvi, sum);
|
||||
imageStore(debug_1_image, uvi, sum);
|
||||
imageStore(debug_2_image, uvi, vec4(vn / render_size * 2, 0, 1));
|
||||
imageStore(debug_3_image, uvi, vec4(0));
|
||||
imageStore(debug_4_image, uvi, vec4(0));
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
[remap]
|
||||
|
||||
importer="glsl"
|
||||
type="RDShaderFile"
|
||||
uid="uid://m6rlgfu6i0b3"
|
||||
path="res://.godot/imported/guertin_kino_blur.glsl-71e9932045a7522115793d60f179d67e.res"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_kino_blur.glsl"
|
||||
dest_files=["res://.godot/imported/guertin_kino_blur.glsl-71e9932045a7522115793d60f179d67e.res"]
|
||||
|
||||
[params]
|
||||
|
@ -0,0 +1,72 @@
|
||||
#[compute]
|
||||
#version 450
|
||||
|
||||
#define FLT_MAX 3.402823466e+38
|
||||
#define FLT_MIN 1.175494351e-38
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D tile_max;
|
||||
layout(rgba16f, set = 0, binding = 1) uniform writeonly image2D neighbor_max;
|
||||
|
||||
layout(push_constant, std430) uniform Params
|
||||
{
|
||||
float nan5;
|
||||
float nan6;
|
||||
float nan7;
|
||||
float nan8;
|
||||
int nan1;
|
||||
int nan2;
|
||||
int nan3;
|
||||
int nan4;
|
||||
} params;
|
||||
|
||||
layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 render_size = ivec2(textureSize(tile_max, 0));
|
||||
ivec2 uvi = ivec2(gl_GlobalInvocationID.xy);
|
||||
if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
vec2 uvn = (vec2(uvi) + vec2(0.5)) / render_size;
|
||||
|
||||
vec2 max_neighbor_velocity = vec2(0);
|
||||
|
||||
float max_neighbor_velocity_length = 0;
|
||||
|
||||
for(int i = -1; i < 2; i++)
|
||||
{
|
||||
for(int j = -1; j < 2; j++)
|
||||
{
|
||||
vec2 current_offset = vec2(1) / vec2(render_size) * vec2(i, j);
|
||||
vec2 current_uv = uvn + current_offset;
|
||||
if(current_uv.x < 0 || current_uv.x > 1 || current_uv.y < 0 || current_uv.y > 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
bool is_diagonal = (abs(i) + abs(j) == 2);
|
||||
|
||||
vec2 current_neighbor_velocity = textureLod(tile_max, current_uv, 0.0).xy;
|
||||
|
||||
bool facing_center = dot(current_neighbor_velocity, current_offset) > 0;
|
||||
|
||||
if(is_diagonal && !facing_center)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
float current_neighbor_velocity_length = dot(current_neighbor_velocity, current_neighbor_velocity);
|
||||
if(current_neighbor_velocity_length > max_neighbor_velocity_length)
|
||||
{
|
||||
max_neighbor_velocity_length = current_neighbor_velocity_length;
|
||||
max_neighbor_velocity = current_neighbor_velocity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
imageStore(neighbor_max, uvi, vec4(max_neighbor_velocity, 0, 1));
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
[remap]
|
||||
|
||||
importer="glsl"
|
||||
type="RDShaderFile"
|
||||
uid="uid://bn88jkvr17x4j"
|
||||
path="res://.godot/imported/guertin_neighbor_max.glsl-91e836516679e0c51b67df5b480ef0af.res"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_neighbor_max.glsl"
|
||||
dest_files=["res://.godot/imported/guertin_neighbor_max.glsl-91e836516679e0c51b67df5b480ef0af.res"]
|
||||
|
||||
[params]
|
||||
|
@ -0,0 +1,18 @@
|
||||
#[compute]
|
||||
#version 450
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D blur_sampler;
|
||||
layout(rgba16f, set = 0, binding = 1) uniform image2D color_image;
|
||||
|
||||
layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
|
||||
void main()
|
||||
{
|
||||
ivec2 render_size = ivec2(textureSize(blur_sampler, 0));
|
||||
ivec2 output_size = imageSize(color_image);
|
||||
ivec2 uv = ivec2(gl_GlobalInvocationID.xy);
|
||||
if ((uv.x >= output_size.x) || (uv.y >= output_size.y))
|
||||
{
|
||||
return;
|
||||
}
|
||||
imageStore(color_image, uv, textureLod(blur_sampler, (vec2(uv) + 0.5) / output_size, 0.0));
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
[remap]
|
||||
|
||||
importer="glsl"
|
||||
type="RDShaderFile"
|
||||
uid="uid://i6rnwhmss334"
|
||||
path="res://.godot/imported/guertin_overlay.glsl-506c18362b63cb0a2477b4a4fbfea046.res"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_overlay.glsl"
|
||||
dest_files=["res://.godot/imported/guertin_overlay.glsl-506c18362b63cb0a2477b4a4fbfea046.res"]
|
||||
|
||||
[params]
|
||||
|
@ -0,0 +1,55 @@
|
||||
#[compute]
|
||||
#version 450
|
||||
|
||||
#define FLT_MAX 3.402823466e+38
|
||||
#define FLT_MIN 1.175494351e-38
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D velocity_sampler;
|
||||
layout(set = 0, binding = 1) uniform sampler2D depth_sampler;
|
||||
layout(rgba16f, set = 0, binding = 2) uniform writeonly image2D tile_max_x;
|
||||
|
||||
layout(push_constant, std430) uniform Params
|
||||
{
|
||||
float nan5;
|
||||
float nan6;
|
||||
float nan7;
|
||||
float nan8;
|
||||
int tile_size;
|
||||
int nan2;
|
||||
int nan3;
|
||||
int nan4;
|
||||
} params;
|
||||
|
||||
layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 render_size = ivec2(textureSize(velocity_sampler, 0));
|
||||
ivec2 output_size = imageSize(tile_max_x);
|
||||
ivec2 uvi = ivec2(gl_GlobalInvocationID.xy);
|
||||
ivec2 global_uvi = uvi * ivec2(params.tile_size, 1);
|
||||
if ((uvi.x >= output_size.x) || (uvi.y >= output_size.y) || (global_uvi.x >= render_size.x) || (global_uvi.y >= render_size.y))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
vec2 uvn = (vec2(global_uvi) + vec2(0.5)) / render_size;
|
||||
|
||||
vec4 max_velocity = vec4(0);
|
||||
|
||||
float max_velocity_length = -1;
|
||||
|
||||
for(int i = 0; i < params.tile_size; i++)
|
||||
{
|
||||
vec2 current_uv = uvn + vec2(float(i) / render_size.x, 0);
|
||||
vec3 velocity_sample = textureLod(velocity_sampler, current_uv, 0.0).xyz;
|
||||
float current_velocity_length = dot(velocity_sample.xy, velocity_sample.xy);
|
||||
if(current_velocity_length > max_velocity_length)
|
||||
{
|
||||
max_velocity_length = current_velocity_length;
|
||||
max_velocity = vec4(velocity_sample, textureLod(depth_sampler, current_uv, 0.0).x);
|
||||
}
|
||||
}
|
||||
imageStore(tile_max_x, uvi, max_velocity);
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
[remap]
|
||||
|
||||
importer="glsl"
|
||||
type="RDShaderFile"
|
||||
uid="uid://d0s5upcgm7r6l"
|
||||
path="res://.godot/imported/guertin_tile_max_x.glsl-7ca561425618287b0f2821fd8c232f09.res"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_x.glsl"
|
||||
dest_files=["res://.godot/imported/guertin_tile_max_x.glsl-7ca561425618287b0f2821fd8c232f09.res"]
|
||||
|
||||
[params]
|
||||
|
@ -0,0 +1,54 @@
|
||||
#[compute]
|
||||
#version 450
|
||||
|
||||
#define FLT_MAX 3.402823466e+38
|
||||
#define FLT_MIN 1.175494351e-38
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D tile_max_x;
|
||||
layout(rgba16f, set = 0, binding = 1) uniform writeonly image2D tile_max;
|
||||
|
||||
layout(push_constant, std430) uniform Params
|
||||
{
|
||||
float nan5;
|
||||
float nan6;
|
||||
float nan7;
|
||||
float nan8;
|
||||
int tile_size;
|
||||
int nan2;
|
||||
int nan3;
|
||||
int nan4;
|
||||
} params;
|
||||
|
||||
layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 render_size = ivec2(textureSize(tile_max_x, 0));
|
||||
ivec2 output_size = imageSize(tile_max);
|
||||
ivec2 uvi = ivec2(gl_GlobalInvocationID.xy);
|
||||
ivec2 global_uvi = uvi * ivec2(1, params.tile_size);
|
||||
if ((uvi.x >= output_size.x) || (uvi.y >= output_size.y) || (global_uvi.x >= render_size.x) || (global_uvi.y >= render_size.y))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
vec2 uvn = (vec2(global_uvi) + vec2(0.5)) / render_size;
|
||||
|
||||
vec4 max_velocity = vec4(0);
|
||||
|
||||
float max_velocity_length = -1;
|
||||
|
||||
for(int i = 0; i < params.tile_size; i++)
|
||||
{
|
||||
vec2 current_uv = uvn + vec2(0, float(i) / render_size.y);
|
||||
vec4 velocity_sample = textureLod(tile_max_x, current_uv, 0.0);
|
||||
float current_velocity_length = dot(velocity_sample.xy, velocity_sample.xy);
|
||||
if(current_velocity_length > max_velocity_length)
|
||||
{
|
||||
max_velocity_length = current_velocity_length;
|
||||
max_velocity = velocity_sample;
|
||||
}
|
||||
}
|
||||
imageStore(tile_max, uvi, max_velocity);
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
[remap]
|
||||
|
||||
importer="glsl"
|
||||
type="RDShaderFile"
|
||||
uid="uid://ceetvitdbio4l"
|
||||
path="res://.godot/imported/guertin_tile_max_y.glsl-60f045725ff6917c4bd911cf3710a444.res"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_y.glsl"
|
||||
dest_files=["res://.godot/imported/guertin_tile_max_y.glsl-60f045725ff6917c4bd911cf3710a444.res"]
|
||||
|
||||
[params]
|
||||
|
@ -0,0 +1,68 @@
|
||||
#[compute]
|
||||
#version 450
|
||||
|
||||
#define FLT_MAX 3.402823466e+38
|
||||
#define FLT_MIN 1.175494351e-38
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D tile_max;
|
||||
layout(rgba16f, set = 0, binding = 1) uniform writeonly image2D tile_variance;
|
||||
|
||||
layout(push_constant, std430) uniform Params
|
||||
{
|
||||
float nan5;
|
||||
float nan6;
|
||||
float nan7;
|
||||
float nan8;
|
||||
int nan1;
|
||||
int nan2;
|
||||
int nan3;
|
||||
int nan4;
|
||||
} params;
|
||||
|
||||
layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 render_size = ivec2(textureSize(tile_max, 0));
|
||||
ivec2 uvi = ivec2(gl_GlobalInvocationID.xy);
|
||||
if ((uvi.x >= render_size.x) || (uvi.y >= render_size.y))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
vec2 uvn = (vec2(uvi) + vec2(0.5)) / render_size;
|
||||
|
||||
float variance = 0;
|
||||
|
||||
vec2 current_velocity = abs(normalize(textureLod(tile_max, uvn, 0.0).xy));
|
||||
|
||||
float tile_count = 0;
|
||||
|
||||
for(int i = -1; i < 2; i++)
|
||||
{
|
||||
for(int j = -1; j < 2; j++)
|
||||
{
|
||||
vec2 current_offset = vec2(1) / vec2(render_size) * vec2(i, j);
|
||||
vec2 current_uv = uvn + current_offset;
|
||||
if(current_uv.x < 0 || current_uv.x > 1 || current_uv.y < 0 || current_uv.y > 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if(i == j && i == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
tile_count += 1;
|
||||
|
||||
vec2 current_neighbor_velocity = abs(normalize(textureLod(tile_max, current_uv, 0.0).xy));
|
||||
|
||||
variance += dot(current_velocity, current_neighbor_velocity);
|
||||
}
|
||||
}
|
||||
|
||||
variance /= tile_count;
|
||||
|
||||
imageStore(tile_variance, uvi, vec4(1 - variance));
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
[remap]
|
||||
|
||||
importer="glsl"
|
||||
type="RDShaderFile"
|
||||
uid="uid://by6mslkv0palh"
|
||||
path="res://.godot/imported/guertin_tile_variance.glsl-2fb44423dc25efae19822b8cfbe32a55.res"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_variance.glsl"
|
||||
dest_files=["res://.godot/imported/guertin_tile_variance.glsl-2fb44423dc25efae19822b8cfbe32a55.res"]
|
||||
|
||||
[params]
|
||||
|
@ -0,0 +1,8 @@
|
||||
[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://dre56ajymywpr"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_loemu"]
|
||||
[ext_resource type="RDShaderFile" uid="uid://m6rlgfu6i0b3" path="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_kino_blur.glsl" id="2_uo41r"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_loemu")
|
||||
shader_file = ExtResource("2_uo41r")
|
262
addons/SphynxMotionBlurToolkit/Guertin/guertin_motion_blur.gd
Normal file
262
addons/SphynxMotionBlurToolkit/Guertin/guertin_motion_blur.gd
Normal file
@ -0,0 +1,262 @@
|
||||
extends MotionBlurCompositorEffect
|
||||
class_name GuertinMotionBlur
|
||||
|
||||
@export_group("Motion Blur", "motion_blur_")
|
||||
# diminishing returns over 16
|
||||
@export_range(4, 64) var motion_blur_samples: int = 25
|
||||
# you really don't want this over 0.5, but you can if you want to try
|
||||
@export_range(0, 0.5, 0.001, "or_greater") var motion_blur_intensity: float = 1
|
||||
@export_range(0, 1) var motion_blur_center_fade: float = 0.0
|
||||
|
||||
@export var blur_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/Guertin/guertin_blur_stage.tres"):
|
||||
set(value):
|
||||
unsubscribe_shader_stage(blur_stage)
|
||||
blur_stage = value
|
||||
subscirbe_shader_stage(value)
|
||||
|
||||
@export var overlay_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/Guertin/guertin_overlay_stage.tres"):
|
||||
set(value):
|
||||
unsubscribe_shader_stage(overlay_stage)
|
||||
overlay_stage = value
|
||||
subscirbe_shader_stage(value)
|
||||
|
||||
@export var tile_max_x_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_max_x_stage.tres"):
|
||||
set(value):
|
||||
unsubscribe_shader_stage(tile_max_x_stage)
|
||||
tile_max_x_stage = value
|
||||
subscirbe_shader_stage(value)
|
||||
|
||||
@export var tile_max_y_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_max_y_stage.tres"):
|
||||
set(value):
|
||||
unsubscribe_shader_stage(tile_max_y_stage)
|
||||
tile_max_y_stage = value
|
||||
subscirbe_shader_stage(value)
|
||||
|
||||
@export var neighbor_max_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/Guertin/guertin_neighbor_max_stage.tres"):
|
||||
set(value):
|
||||
unsubscribe_shader_stage(neighbor_max_stage)
|
||||
neighbor_max_stage = value
|
||||
subscirbe_shader_stage(value)
|
||||
|
||||
@export var tile_variance_stage : ShaderStageResource = preload("res://addons/SphynxMotionBlurToolkit/Guertin/guertin_tile_variance_stage.tres"):
|
||||
set(value):
|
||||
unsubscribe_shader_stage(tile_variance_stage)
|
||||
tile_variance_stage = value
|
||||
subscirbe_shader_stage(value)
|
||||
|
||||
@export var tile_size : int = 40
|
||||
|
||||
@export var linear_falloff_slope : float = 1
|
||||
|
||||
@export var importance_bias : float = 40
|
||||
|
||||
@export var maximum_jitter_value : float = 0.95
|
||||
|
||||
@export var minimum_user_threshold : float = 1.5
|
||||
|
||||
var output_color: StringName = "output_color"
|
||||
|
||||
var tile_max_x : StringName = "tile_max_x"
|
||||
|
||||
var tile_max : StringName = "tile_max"
|
||||
|
||||
var neighbor_max : StringName = "neighbor_max"
|
||||
|
||||
var tile_variance : StringName = "tile_variance"
|
||||
|
||||
var custom_velocity : StringName = "custom_velocity"
|
||||
|
||||
var debug_1 : StringName = "debug_1"
|
||||
var debug_2 : StringName = "debug_2"
|
||||
var debug_3 : StringName = "debug_3"
|
||||
var debug_4 : StringName = "debug_4"
|
||||
|
||||
var freeze : bool = false
|
||||
|
||||
func _get_max_dilation_range() -> float:
|
||||
return tile_size;
|
||||
|
||||
func _render_callback_2(render_size : Vector2i, render_scene_buffers : RenderSceneBuffersRD, render_scene_data : RenderSceneDataRD):
|
||||
ensure_texture(tile_max_x, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / tile_size, 1.))
|
||||
ensure_texture(tile_max, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / tile_size, 1. / tile_size))
|
||||
ensure_texture(neighbor_max, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / tile_size, 1. / tile_size))
|
||||
ensure_texture(tile_variance, render_scene_buffers, RenderingDevice.DATA_FORMAT_R16G16B16A16_SFLOAT, Vector2(1. / tile_size, 1. / tile_size))
|
||||
ensure_texture(custom_velocity, render_scene_buffers)
|
||||
ensure_texture(output_color, render_scene_buffers)
|
||||
ensure_texture(debug_1, render_scene_buffers)
|
||||
ensure_texture(debug_2, render_scene_buffers)
|
||||
ensure_texture(debug_3, render_scene_buffers)
|
||||
ensure_texture(debug_4, render_scene_buffers)
|
||||
|
||||
rd.draw_command_begin_label("Motion Blur", Color(1.0, 1.0, 1.0, 1.0))
|
||||
|
||||
var tile_max_x_push_constants: PackedFloat32Array = [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
var int_tile_max_x_push_constants : PackedInt32Array = [
|
||||
tile_size,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
var tile_max_x_push_constants_byte_array = tile_max_x_push_constants.to_byte_array()
|
||||
tile_max_x_push_constants_byte_array.append_array(int_tile_max_x_push_constants.to_byte_array())
|
||||
|
||||
var tile_max_y_push_constants: PackedFloat32Array = [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
var int_tile_max_y_push_constants : PackedInt32Array = [
|
||||
tile_size,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
var tile_max_y_push_constants_byte_array = tile_max_y_push_constants.to_byte_array()
|
||||
tile_max_y_push_constants_byte_array.append_array(int_tile_max_y_push_constants.to_byte_array())
|
||||
|
||||
var neighbor_max_push_constants: PackedFloat32Array = [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
var int_neighbor_max_push_constants : PackedInt32Array = [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
var neighbor_max_push_constants_byte_array = neighbor_max_push_constants.to_byte_array()
|
||||
neighbor_max_push_constants_byte_array.append_array(int_neighbor_max_push_constants.to_byte_array())
|
||||
|
||||
var tile_variance_push_constants: PackedFloat32Array = [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
var int_tile_variance_push_constants : PackedInt32Array = [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
var tile_variance_push_constants_byte_array = tile_variance_push_constants.to_byte_array()
|
||||
tile_variance_push_constants_byte_array.append_array(int_tile_variance_push_constants.to_byte_array())
|
||||
|
||||
var blur_push_constants: PackedFloat32Array = [
|
||||
minimum_user_threshold,
|
||||
importance_bias,
|
||||
maximum_jitter_value,
|
||||
0,
|
||||
]
|
||||
var int_blur_push_constants : PackedInt32Array = [
|
||||
tile_size,
|
||||
motion_blur_samples,
|
||||
Engine.get_frames_drawn() % 8,
|
||||
0
|
||||
]
|
||||
var blur_push_constants_byte_array = blur_push_constants.to_byte_array()
|
||||
blur_push_constants_byte_array.append_array(int_blur_push_constants.to_byte_array())
|
||||
|
||||
var view_count = render_scene_buffers.get_view_count()
|
||||
|
||||
for view in range(view_count):
|
||||
var color_image := render_scene_buffers.get_color_layer(view)
|
||||
var depth_image := render_scene_buffers.get_depth_layer(view)
|
||||
var output_color_image := render_scene_buffers.get_texture_slice(context, output_color, view, 0, 1, 1)
|
||||
var tile_max_x_image := render_scene_buffers.get_texture_slice(context, tile_max_x, view, 0, 1, 1)
|
||||
var tile_max_image := render_scene_buffers.get_texture_slice(context, tile_max, view, 0, 1, 1)
|
||||
var neighbor_max_image := render_scene_buffers.get_texture_slice(context, neighbor_max, view, 0, 1, 1)
|
||||
var tile_variance_image := render_scene_buffers.get_texture_slice(context, tile_variance, view, 0, 1, 1)
|
||||
var custom_velocity_image := render_scene_buffers.get_texture_slice(context, custom_velocity, view, 0, 1, 1)
|
||||
var debug_1_image := render_scene_buffers.get_texture_slice(context, debug_1, view, 0, 1, 1)
|
||||
var debug_2_image := render_scene_buffers.get_texture_slice(context, debug_2, view, 0, 1, 1)
|
||||
var debug_3_image := render_scene_buffers.get_texture_slice(context, debug_3, view, 0, 1, 1)
|
||||
var debug_4_image := render_scene_buffers.get_texture_slice(context, debug_4, view, 0, 1, 1)
|
||||
|
||||
var x_groups := floori((render_size.x / tile_size - 1) / 16 + 1)
|
||||
var y_groups := floori((render_size.y - 1) / 16 + 1)
|
||||
|
||||
dispatch_stage(tile_max_x_stage,
|
||||
[
|
||||
get_sampler_uniform(custom_velocity_image, 0, false),
|
||||
get_sampler_uniform(depth_image, 1, false),
|
||||
get_image_uniform(tile_max_x_image, 2)
|
||||
],
|
||||
tile_max_x_push_constants_byte_array,
|
||||
Vector3i(x_groups, y_groups, 1),
|
||||
"TileMaxX",
|
||||
view)
|
||||
|
||||
x_groups = floori((render_size.x / tile_size - 1) / 16 + 1)
|
||||
y_groups = floori((render_size.y / tile_size - 1) / 16 + 1)
|
||||
|
||||
dispatch_stage(tile_max_y_stage,
|
||||
[
|
||||
get_sampler_uniform(tile_max_x_image, 0, false),
|
||||
get_image_uniform(tile_max_image, 1)
|
||||
],
|
||||
tile_max_y_push_constants_byte_array,
|
||||
Vector3i(x_groups, y_groups, 1),
|
||||
"TileMaxY",
|
||||
view)
|
||||
|
||||
dispatch_stage(neighbor_max_stage,
|
||||
[
|
||||
get_sampler_uniform(tile_max_image, 0, false),
|
||||
get_image_uniform(neighbor_max_image, 1)
|
||||
],
|
||||
neighbor_max_push_constants_byte_array,
|
||||
Vector3i(x_groups, y_groups, 1),
|
||||
"NeighborMax",
|
||||
view)
|
||||
|
||||
dispatch_stage(tile_variance_stage,
|
||||
[
|
||||
get_sampler_uniform(tile_max_image, 0, false),
|
||||
get_image_uniform(tile_variance_image, 1)
|
||||
],
|
||||
tile_variance_push_constants_byte_array,
|
||||
Vector3i(x_groups, y_groups, 1),
|
||||
"TileVariance",
|
||||
view)
|
||||
|
||||
x_groups = floori((render_size.x - 1) / 16 + 1)
|
||||
y_groups = floori((render_size.y - 1) / 16 + 1)
|
||||
|
||||
dispatch_stage(blur_stage,
|
||||
[
|
||||
get_sampler_uniform(color_image, 0, false),
|
||||
get_sampler_uniform(depth_image, 1, false),
|
||||
get_sampler_uniform(custom_velocity_image, 2, false),
|
||||
get_sampler_uniform(neighbor_max_image, 3, false),
|
||||
get_sampler_uniform(tile_variance_image, 4, true),
|
||||
get_image_uniform(output_color_image, 5),
|
||||
get_image_uniform(debug_1_image, 6),
|
||||
get_image_uniform(debug_2_image, 7),
|
||||
get_image_uniform(debug_3_image, 8),
|
||||
get_image_uniform(debug_4_image, 9)
|
||||
],
|
||||
blur_push_constants_byte_array,
|
||||
Vector3i(x_groups, y_groups, 1),
|
||||
"Blur",
|
||||
view)
|
||||
|
||||
dispatch_stage(overlay_stage,
|
||||
[
|
||||
get_sampler_uniform(output_color_image, 0, false),
|
||||
get_image_uniform(color_image, 1)
|
||||
],
|
||||
[],
|
||||
Vector3i(x_groups, y_groups, 1),
|
||||
"Overlay result",
|
||||
view)
|
||||
|
||||
rd.draw_command_end_label()
|
@ -0,0 +1,8 @@
|
||||
[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://cvb65hfs2lrxo"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_i1bu0"]
|
||||
[ext_resource type="RDShaderFile" uid="uid://bn88jkvr17x4j" path="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_neighbor_max.glsl" id="2_jp4do"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_i1bu0")
|
||||
shader_file = ExtResource("2_jp4do")
|
@ -0,0 +1,8 @@
|
||||
[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://bidsfymvdyhek"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_2uett"]
|
||||
[ext_resource type="RDShaderFile" uid="uid://i6rnwhmss334" path="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_overlay.glsl" id="2_evkw4"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_2uett")
|
||||
shader_file = ExtResource("2_evkw4")
|
@ -0,0 +1,8 @@
|
||||
[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://dipvwksvqb3dm"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_bxcqf"]
|
||||
[ext_resource type="RDShaderFile" uid="uid://d0s5upcgm7r6l" path="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_x.glsl" id="2_q6kae"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_bxcqf")
|
||||
shader_file = ExtResource("2_q6kae")
|
@ -0,0 +1,8 @@
|
||||
[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://bxfg45ubc2pv7"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_gy5dj"]
|
||||
[ext_resource type="RDShaderFile" uid="uid://ceetvitdbio4l" path="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_max_y.glsl" id="2_grpec"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_gy5dj")
|
||||
shader_file = ExtResource("2_grpec")
|
@ -0,0 +1,8 @@
|
||||
[gd_resource type="Resource" script_class="ShaderStageResource" load_steps=3 format=3 uid="uid://bqehecsdgt70s"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/SphynxMotionBlurToolkit/BaseClasses/shader_pass_resource.gd" id="1_kkpwt"]
|
||||
[ext_resource type="RDShaderFile" uid="uid://by6mslkv0palh" path="res://addons/SphynxMotionBlurToolkit/Guertin/ShaderFiles/guertin_tile_variance.glsl" id="2_r5u5d"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_kkpwt")
|
||||
shader_file = ExtResource("2_r5u5d")
|
Reference in New Issue
Block a user