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..457ddc7b752 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 = 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; + } + /* 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,