From d11047cfae8959a9e1f6b6a24c75495442b18d38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A5=9D=E6=96=B9=E8=88=9F?= Date: Sun, 12 Jul 2026 02:58:47 +0800 Subject: [PATCH] Fix SceneData UBO layout for Godot 4.7 (pre-blur processor) Godot 4.7 changed the internal SceneData layout mirrored at binding 5: - inv_view_matrix / view_matrix are now packed mat3x4 instead of mat4 - three new fields (radiance_pixel_size, radiance_border_size, reflection_atlas_border_size) precede the light-count fields The stale struct is 32 bytes short per {data, prev_data} (5696 vs 5728), so uniform_set_create fails every frame and the pre-blur pass never runs. Update the struct to the 4.7 layout and reconstruct 4x4 view matrices from the packed mat3x4, matching the engine's scene_data_inc.glsl. Verified on Godot 4.7-stable (Forward+/Metal): enabled 60/60 frames 0 errors with visible directional blur; disabled control sharp; MSAA 2x no artifacts at default post-opaque placement. --- .../Shaders/pre_blur_processor.glsl | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/addons/SphynxMotionBlurToolkit/PreBlurProcessing/Shaders/pre_blur_processor.glsl b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/Shaders/pre_blur_processor.glsl index 06e101c..01943f6 100644 --- a/addons/SphynxMotionBlurToolkit/PreBlurProcessing/Shaders/pre_blur_processor.glsl +++ b/addons/SphynxMotionBlurToolkit/PreBlurProcessing/Shaders/pre_blur_processor.glsl @@ -11,8 +11,8 @@ layout(rgba32f, set = 0, binding = 2) uniform writeonly image2D vector_output; struct SceneData { mat4 projection_matrix; mat4 inv_projection_matrix; - mat4 inv_view_matrix; - mat4 view_matrix; + mat3x4 inv_view_matrix; + mat3x4 view_matrix; // only used for multiview mat4 projection_matrix_view[2]; @@ -34,6 +34,10 @@ struct SceneData { vec2 shadow_atlas_pixel_size; vec2 directional_shadow_pixel_size; + float radiance_pixel_size; + float radiance_border_size; + vec2 reflection_atlas_border_size; + uint directional_light_count; float dual_paraboloid_side; float z_far; @@ -105,6 +109,16 @@ float get_view_depth(float depth) return 0.; } +mat4 unpack_transform(mat3x4 transform) +{ + return transpose(mat4( + transform[0], + transform[1], + transform[2], + vec4(0.0, 0.0, 0.0, 1.0) + )); +} + void main() { ivec2 render_size = ivec2(textureSize(vector_sampler, 0)); @@ -119,6 +133,8 @@ void main() SceneData scene_data = scene.data; SceneData previous_scene_data = scene.prev_data; + mat4 view_matrix = unpack_transform(scene_data.view_matrix); + mat4 previous_view_matrix = unpack_transform(previous_scene_data.view_matrix); float depth = textureLod(depth_sampler, uvn, 0.0).x; @@ -126,9 +142,9 @@ void main() 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 world_local_position = inverse(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_position = previous_view_matrix * vec4(world_local_position.xyz, 1.0); vec4 view_past_ndc = previous_scene_data.projection_matrix * view_past_position; @@ -141,9 +157,9 @@ void main() 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); + world_local_position = mat4(mat3(inverse(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_position = mat4(mat3(previous_view_matrix)) * vec4(world_local_position.xyz, 1.0); view_past_ndc = previous_scene_data.projection_matrix * view_past_position; @@ -191,4 +207,4 @@ void main() 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 -} \ No newline at end of file +}