Skip to content

Commit 2a5c800

Browse files
authored
Merge pull request bevyengine#23 from rodolphito/meshlet-orthographic
Fix occlusion culling in orthographic views
2 parents d0789ae + 4dcc424 commit 2a5c800

File tree

1 file changed

+34
-19
lines changed

1 file changed

+34
-19
lines changed

crates/bevy_pbr/src/meshlet/cull_meshlets.wgsl

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,9 @@ fn cull_meshlets(@builtin(global_invocation_id) thread_id: vec3<u32>) {
5252
let aabb = project_view_space_sphere_to_screen_space_aabb(bounding_sphere_center_view_space, bounding_sphere_radius);
5353

5454
let depth_pyramid_size_mip_0 = vec2<f32>(textureDimensions(depth_pyramid, 0));
55-
let width = (aabb.z - aabb.x) * depth_pyramid_size_mip_0.x;
56-
let height = (aabb.w - aabb.y) * depth_pyramid_size_mip_0.y;
55+
// we halve the size because the first depth mip resampling pass cut the full screen resolution into a power of two conservatively
56+
let width = (aabb.z - aabb.x) * 0.5 * depth_pyramid_size_mip_0.x;
57+
let height = (aabb.w - aabb.y) * 0.5 * depth_pyramid_size_mip_0.y;
5758
let depth_level = max(0, i32(ceil(log2(max(width, height))))); // TODO: Naga doesn't like this being a u32
5859
let depth_pyramid_size = vec2<f32>(textureDimensions(depth_pyramid, depth_level));
5960
let aabb_top_left = vec2<u32>(aabb.xy * depth_pyramid_size);
@@ -63,9 +64,15 @@ fn cull_meshlets(@builtin(global_invocation_id) thread_id: vec3<u32>) {
6364
let depth_quad_c = textureLoad(depth_pyramid, aabb_top_left + vec2(0u, 1u), depth_level).x;
6465
let depth_quad_d = textureLoad(depth_pyramid, aabb_top_left + vec2(1u, 1u), depth_level).x;
6566
let occluder_depth = min(min(depth_quad_a, depth_quad_b), min(depth_quad_c, depth_quad_d));
66-
67-
let sphere_depth = -view.projection[3][2] / (bounding_sphere_center_view_space.z + bounding_sphere_radius);
68-
meshlet_visible &= sphere_depth >= occluder_depth;
67+
if view.projection[3][3] == 1.0 {
68+
// Orthographic
69+
let sphere_depth = view.projection[3][2] + (bounding_sphere_center_view_space.z + bounding_sphere_radius) * view.projection[2][2];
70+
meshlet_visible &= sphere_depth >= occluder_depth;
71+
} else {
72+
// Perspective
73+
let sphere_depth = -view.projection[3][2] / (bounding_sphere_center_view_space.z + bounding_sphere_radius);
74+
meshlet_visible &= sphere_depth >= occluder_depth;
75+
}
6976
}
7077
#endif
7178

@@ -76,23 +83,31 @@ fn cull_meshlets(@builtin(global_invocation_id) thread_id: vec3<u32>) {
7683

7784
// https://zeux.io/2023/01/12/approximate-projected-bounds
7885
fn project_view_space_sphere_to_screen_space_aabb(cp: vec3<f32>, r: f32) -> vec4<f32> {
79-
let c = vec3(cp.xy, -cp.z);
80-
// No need to clip near plane because frustum culling already checked that
86+
let inv_width = view.projection[0][0] * 0.5;
87+
let inv_height = view.projection[1][1] * 0.5;
88+
if view.projection[3][3] == 1.0 {
89+
// Orthographic
90+
let min_x = cp.x - r;
91+
let max_x = cp.x + r;
8192

82-
let cr = c * r;
83-
let czr2 = c.z * c.z - r * r;
93+
let min_y = cp.y - r;
94+
let max_y = cp.y + r;
8495

85-
let vx = sqrt(c.x * c.x + czr2);
86-
let min_x = (vx * c.x - cr.z) / (vx * c.z + cr.x);
87-
let max_x = (vx * c.x + cr.z) / (vx * c.z - cr.x);
96+
return vec4(min_x * inv_width, 1.0 - max_y * inv_height, max_x * inv_width, 1.0 - min_y * inv_height);
97+
} else {
98+
// Perspective
99+
let c = vec3(cp.xy, -cp.z);
100+
let cr = c * r;
101+
let czr2 = c.z * c.z - r * r;
88102

89-
let vy = sqrt(c.y * c.y + czr2);
90-
let min_y = (vy * c.y - cr.z) / (vy * c.z + cr.y);
91-
let max_y = (vy * c.y + cr.z) / (vy * c.z - cr.y);
103+
let vx = sqrt(c.x * c.x + czr2);
104+
let min_x = (vx * c.x - cr.z) / (vx * c.z + cr.x);
105+
let max_x = (vx * c.x + cr.z) / (vx * c.z - cr.x);
92106

93-
let p00 = view.projection[0][0];
94-
let p11 = view.projection[1][1];
107+
let vy = sqrt(c.y * c.y + czr2);
108+
let min_y = (vy * c.y - cr.z) / (vy * c.z + cr.y);
109+
let max_y = (vy * c.y + cr.z) / (vy * c.z - cr.y);
95110

96-
var aabb = vec4(min_x * p00, min_y * p11, max_x * p00, max_y * p11);
97-
return aabb.xwzy * vec4(0.5, -0.5, 0.5, -0.5) + vec4(0.5);
111+
return vec4(min_x * inv_width, -max_y * inv_height, max_x * inv_width, -min_y * inv_height) + vec4(0.5);
112+
}
98113
}

0 commit comments

Comments
 (0)