From 9d62cf5ba349c649fdd037dd255d69e07a1026f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Wed, 18 Sep 2024 17:00:16 +0200 Subject: [PATCH 1/2] Fix: #127774: Flat Object matrix leads to incorrect culling Object with degenerate transform matrix can lead to flat bounds on GPU. This in turn lead to NaN intersection planes inside IsectBox. Compute (pseudo) size of matrix and bypass culling is any axis is too small. The other part of the patch makes sure that there is a distinction between disabled culling and invalid bounding boxes. --- source/blender/draw/intern/draw_shader_shared.hh | 9 +++++++++ .../shaders/draw_resource_finalize_comp.glsl | 15 +++++++++++++-- .../draw/intern/shaders/draw_visibility_comp.glsl | 2 +- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/source/blender/draw/intern/draw_shader_shared.hh b/source/blender/draw/intern/draw_shader_shared.hh index 30b6ab30982..6203c06984d 100644 --- a/source/blender/draw/intern/draw_shader_shared.hh +++ b/source/blender/draw/intern/draw_shader_shared.hh @@ -204,7 +204,16 @@ struct ObjectBounds { }; BLI_STATIC_ASSERT_ALIGN(ObjectBounds, 16) +/* Return true if `bounding_corners` are valid. Should be checked before accessing them. + * Does not guarantee that `bounding_sphere` is valid. */ inline bool drw_bounds_are_valid(ObjectBounds bounds) +{ + return bounds.bounding_sphere.w != -1.0f; +} + +/* Return true if bounds are ready for culling. + * In this case, both `bounding_corners` and `bounding_sphere` are valid. */ +inline bool drw_bounds_culling_enabled(ObjectBounds bounds) { return bounds.bounding_sphere.w >= 0.0f; } diff --git a/source/blender/draw/intern/shaders/draw_resource_finalize_comp.glsl b/source/blender/draw/intern/shaders/draw_resource_finalize_comp.glsl index 699519fc2cf..ac7e7f74109 100644 --- a/source/blender/draw/intern/shaders/draw_resource_finalize_comp.glsl +++ b/source/blender/draw/intern/shaders/draw_resource_finalize_comp.glsl @@ -6,7 +6,8 @@ * Finish computation of a few draw resource after sync. */ -#pragma BLENDER_REQUIRE(common_math_lib.glsl) +#pragma BLENDER_REQUIRE(gpu_shader_math_vector_lib.glsl) +#pragma BLENDER_REQUIRE(gpu_shader_math_matrix_lib.glsl) void main() { @@ -31,7 +32,7 @@ void main() p03.z = max(p03.z, 1e-4); vec3 diagonal = p01 + p02 + p03; vec3 center = p0 + diagonal * 0.5; - float min_axis = min_v3(abs(diagonal)); + float min_axis = reduce_min(abs(diagonal)); bounds.bounding_sphere.xyz = transform_point(model_mat, center); /* We have to apply scaling to the diagonal. */ bounds.bounding_sphere.w = length(transform_direction(model_mat, diagonal)) * 0.5; @@ -51,6 +52,16 @@ void main() bounds.bounding_sphere.w = -2.0; } + /* Bypass culling test for objects that are flattenned on one or more axes (see #127774). + * Fixing them is too much computation but might be worth doing if a use case for it. + * Do not compute the real length to save some instructions. */ + vec3 object_scale = to_scale(reduce_add(abs(model_mat[0].xyz)), + reduce_add(abs(model_mat[1].xyz)), + reduce_add(abs(model_mat[2].xyz))); + if (any(lessThan(abs(object_scale), vec3(1e-10)))) { + bounds.bounding_sphere.w = -2.0; + } + /* Update bounds. */ bounds_buf[resource_id] = bounds; } diff --git a/source/blender/draw/intern/shaders/draw_visibility_comp.glsl b/source/blender/draw/intern/shaders/draw_visibility_comp.glsl index 7bfd692d922..9db78f2a3a9 100644 --- a/source/blender/draw/intern/shaders/draw_visibility_comp.glsl +++ b/source/blender/draw/intern/shaders/draw_visibility_comp.glsl @@ -32,7 +32,7 @@ void main() ObjectBounds bounds = bounds_buf[gl_GlobalInvocationID.x]; - if (drw_bounds_are_valid(bounds)) { + if (drw_bounds_culling_enabled(bounds)) { IsectBox box = isect_box_setup(bounds.bounding_corners[0].xyz, bounds.bounding_corners[1].xyz, bounds.bounding_corners[2].xyz, -- 2.30.2 From 5e3bad494c4aa00b3ca3d1f5eec606e8bdde131e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Wed, 18 Sep 2024 17:57:11 +0200 Subject: [PATCH 2/2] Fix stupid --- .../draw/intern/shaders/draw_resource_finalize_comp.glsl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/draw/intern/shaders/draw_resource_finalize_comp.glsl b/source/blender/draw/intern/shaders/draw_resource_finalize_comp.glsl index ac7e7f74109..457ddc7b752 100644 --- a/source/blender/draw/intern/shaders/draw_resource_finalize_comp.glsl +++ b/source/blender/draw/intern/shaders/draw_resource_finalize_comp.glsl @@ -55,9 +55,9 @@ void main() /* Bypass culling test for objects that are flattenned on one or more axes (see #127774). * Fixing them is too much computation but might be worth doing if a use case for it. * Do not compute the real length to save some instructions. */ - vec3 object_scale = to_scale(reduce_add(abs(model_mat[0].xyz)), - reduce_add(abs(model_mat[1].xyz)), - reduce_add(abs(model_mat[2].xyz))); + vec3 object_scale = vec3(reduce_add(abs(model_mat[0].xyz)), + reduce_add(abs(model_mat[1].xyz)), + reduce_add(abs(model_mat[2].xyz))); if (any(lessThan(abs(object_scale), vec3(1e-10)))) { bounds.bounding_sphere.w = -2.0; } -- 2.30.2