godot-karrot-starter-theme/addons/SphynxMotionBlurToolkit/PreBlurProcessing/Shaders/pre_blur_processor.glsl
2024-11-12 18:09:47 +01:00

204 lines
7.0 KiB
GLSL

#[compute]
#version 450
#define FLT_MAX 3.402823466e+38
#define FLT_MIN 1.175494351e-38
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;
highp mat4 inv_projection_matrix;
highp mat4 inv_view_matrix;
highp mat4 view_matrix;
// only used for multiview
highp mat4 projection_matrix_view[2];
highp mat4 inv_projection_matrix_view[2];
highp vec4 eye_offset[2];
// Used for billboards to cast correct shadows.
highp mat4 main_cam_inv_view_matrix;
highp vec2 viewport_size;
highp vec2 screen_pixel_size;
// Use vec4s because std140 doesn't play nice with vec2s, z and w are wasted.
highp vec4 directional_penumbra_shadow_kernel[32];
highp vec4 directional_soft_shadow_kernel[32];
highp vec4 penumbra_shadow_kernel[32];
highp vec4 soft_shadow_kernel[32];
mediump mat3 radiance_inverse_xform;
mediump vec4 ambient_light_color_energy;
mediump float ambient_color_sky_mix;
bool use_ambient_light;
bool use_ambient_cubemap;
bool use_reflection_cubemap;
highp vec2 shadow_atlas_pixel_size;
highp vec2 directional_shadow_pixel_size;
uint directional_light_count;
mediump float dual_paraboloid_side;
highp float z_far;
highp float z_near;
bool roughness_limiter_enabled;
mediump float roughness_limiter_amount;
mediump float roughness_limiter_limit;
mediump float opaque_prepass_threshold;
bool fog_enabled;
uint fog_mode;
highp float fog_density;
highp float fog_height;
highp float fog_height_density;
highp float fog_depth_curve;
highp float pad;
highp float fog_depth_begin;
mediump vec3 fog_light_color;
highp float fog_depth_end;
mediump float fog_sun_scatter;
mediump float fog_aerial_perspective;
highp float time;
mediump float reflection_multiplier; // one normally, zero when rendering reflections
vec2 taa_jitter;
bool material_uv2_mode;
float emissive_exposure_normalization;
float IBL_exposure_normalization;
bool pancake_shadows;
uint camera_visible_layers;
float pass_alpha_multiplier;
};
layout(set = 0, binding = 5, std140) uniform SceneDataBlock {
SceneData data;
SceneData prev_data;
}
scene;
layout(push_constant, std430) uniform Params
{
float rotation_velocity_multiplier;
float movement_velocity_multiplier;
float object_velocity_multiplier;
float rotation_velocity_lower_threshold;
float movement_velocity_lower_threshold;
float object_velocity_lower_threshold;
float rotation_velocity_upper_threshold;
float movement_velocity_upper_threshold;
float object_velocity_upper_threshold;
float is_fsr2;
float motion_blur_intensity;
float nan_fl_2;
} params;
layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
float sharp_step(float lower, float upper, float x)
{
return clamp((x - lower) / (upper - lower), 0, 1);
}
float get_view_depth(float depth)
{
return 0.;
}
void main()
{
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))
{
return;
}
// must be on pixel center for whole values (tested)
vec2 uvn = vec2(uvi + vec2(0.5)) / render_size;
SceneData scene_data = scene.data;
SceneData previous_scene_data = scene.prev_data;
float depth = textureLod(depth_sampler, uvn, 0.0).x;
vec4 view_position = inverse(scene_data.projection_matrix) * vec4(uvn * 2.0 - 1.0, depth, 1.0);
view_position.xyz /= view_position.w;
// get full change
vec4 world_local_position = inverse(scene_data.view_matrix) * vec4(view_position.xyz, 1.0);
vec4 view_past_position = mat4(previous_scene_data.view_matrix) * vec4(world_local_position.xyz, 1.0);
vec4 view_past_ndc = previous_scene_data.projection_matrix * view_past_position;
view_past_ndc.xyz /= view_past_ndc.w;
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(inverse(scene_data.view_matrix))) * vec4(view_position.xyz, 1.0);
view_past_position = mat4(mat3(previous_scene_data.view_matrix)) * vec4(world_local_position.xyz, 1.0);
view_past_ndc = previous_scene_data.projection_matrix * view_past_position;
view_past_ndc.xyz /= view_past_ndc.w;
past_uv = vec3(view_past_ndc.xy * 0.5 + 0.5, view_past_ndc.z);
vec3 camera_rotation_uv_change = past_uv - vec3(uvn, depth);
// get just movement change
vec3 camera_movement_uv_change = camera_uv_change - camera_rotation_uv_change;
// fill in gaps in base velocity (skybox, z velocity)
vec3 base_velocity = vec3(textureLod(vector_sampler, uvn, 0.0).xy + mix(vec2(0), camera_uv_change.xy, step(depth, 0.)), camera_uv_change.z);
// fsr just makes it so values are larger than 1, I assume its the only case when it happens
if(params.is_fsr2 > 0.5 && dot(base_velocity.xy, base_velocity.xy) >= 1)
{
base_velocity = camera_uv_change;
}
// get object velocity
vec3 object_uv_change = base_velocity - camera_uv_change.xyz;
// construct final velocity with user defined weights
vec3 total_velocity = camera_rotation_uv_change * params.rotation_velocity_multiplier * sharp_step(params.rotation_velocity_lower_threshold, params.rotation_velocity_upper_threshold, length(camera_rotation_uv_change) * params.rotation_velocity_multiplier * params.motion_blur_intensity)
+ camera_movement_uv_change * params.movement_velocity_multiplier * sharp_step(params.movement_velocity_lower_threshold, params.movement_velocity_upper_threshold, length(camera_movement_uv_change) * params.movement_velocity_multiplier * params.motion_blur_intensity)
+ object_uv_change * params.object_velocity_multiplier * sharp_step(params.object_velocity_lower_threshold, params.object_velocity_upper_threshold, length(object_uv_change) * params.object_velocity_multiplier * params.motion_blur_intensity);
// if objects move, clear z direction, (z only correct for static environment)
if(dot(object_uv_change.xy, object_uv_change.xy) > 0.000001)
{
total_velocity.z = 0;
base_velocity.z = 0;
}
// choose the smaller option out of the two based on amgnitude, seems to work well
if(dot(total_velocity.xy * 99, total_velocity.xy * 100) >= dot(base_velocity.xy * 100, base_velocity.xy * 100))
{
total_velocity = base_velocity;
}
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
}