From 6fd65994f309c277b92eb08af1b562e89f012e5a Mon Sep 17 00:00:00 2001 From: crocdialer Date: Tue, 22 Oct 2024 08:05:01 +0200 Subject: [PATCH] workgroup-barrier ftw, now only traces of failed occlusion-culling left --- shaders/pbr/cull_meshlets.task | 45 +++++++++++++++++++--------------- shaders/pbr/indirect_cull.comp | 3 ++- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/shaders/pbr/cull_meshlets.task b/shaders/pbr/cull_meshlets.task index 2cd4a53d..06a1c0e1 100644 --- a/shaders/pbr/cull_meshlets.task +++ b/shaders/pbr/cull_meshlets.task @@ -100,21 +100,25 @@ void main() #if CULLING bool visible = true; + bool visible_last_frame = is_visible(draw_command.meshlet_visibility_index, mi); + barrier(); // occlusion-culling / visibility recording if(post_pass) { + mesh_draw_t draw = draws[object_index]; + // transform bounding volume and normal-cone - mat4 m = camera.view * mat4_cast(draws[object_index].current_matrices.transform); + mat4 m = camera.view * mat4_cast(draw.current_matrices.transform); vec3 cone_axis = normalize(mat3(m) * meshlets[mi].cone_axis); float cone_cutoff = meshlets[mi].cone_cutoff; vec3 center = (m * vec4(meshlets[mi].sphere_center, 1.0)).xyz; - float radius = meshlets[mi].sphere_radius * max(max(abs(draws[object_index].current_matrices.transform.scale_x), - abs(draws[object_index].current_matrices.transform.scale_y)), - abs(draws[object_index].current_matrices.transform.scale_z)); + float radius = meshlets[mi].sphere_radius * max(max(abs(draw.current_matrices.transform.scale_x), + abs(draw.current_matrices.transform.scale_y)), + abs(draw.current_matrices.transform.scale_z)); // cone-culling - visible = materials[draws[object_index].material_index].two_sided || + visible = materials[draw.material_index].two_sided || !cone_cull(center, radius, cone_axis, cone_cutoff, vec3(0)); // frustum-culling @@ -135,22 +139,23 @@ void main() visible = max(screen_area.x, screen_area.y) >= size_thresh; } -// // occlusion-culling -// if(visible && sphere_visible) -// { -// float width = screen_area.x * pyramid_size.x; -// float height = screen_area.y * pyramid_size.y; -// float level = floor(log2(max(width, height))); -// -// // Sampler is set up to do min reduction, so this computes the minimum depth of a 2x2 texel quad -// float depth = camera.near / textureLod(u_depth_pyramid, (aabb.xy + aabb.zw) * 0.5, level).x; -// float depth_sphere = -center.z - radius; -// -// visible = depth_sphere <= depth; -// } + // occlusion-culling + if(visible && sphere_visible) + { + float width = screen_area.x * pyramid_size.x; + float height = screen_area.y * pyramid_size.y; + float level = floor(log2(max(width, height))); + + // Sampler is set up to do min reduction, so this computes the minimum depth of a 2x2 texel quad + float depth = clamp(camera.near / textureLod(u_depth_pyramid, (aabb.xy + aabb.zw) * 0.5, level).x, + camera.near, camera.far); + float depth_sphere = -center.z - 2 * radius; + + visible = depth_sphere <= depth; + } // became visible this frame -> not drawn in 1st-pass - bool needs_post_draw = visible && !is_visible(draw_command.meshlet_visibility_index, mi); + bool needs_post_draw = visible && !visible_last_frame; // if(!visible){ atomicAdd(cull_data.draw_result.v.num_occlusion_culled, 1); } // update visiblity @@ -159,7 +164,7 @@ void main() // post_draw visible = needs_post_draw; } - else{ visible = visible && is_visible(draw_command.meshlet_visibility_index, mi); } + else{ visible = visible_last_frame; } // determine indices/count via ballot uvec4 ballot = subgroupBallot(visible); diff --git a/shaders/pbr/indirect_cull.comp b/shaders/pbr/indirect_cull.comp index 9373fc47..460a36a8 100644 --- a/shaders/pbr/indirect_cull.comp +++ b/shaders/pbr/indirect_cull.comp @@ -128,7 +128,8 @@ void main() float level = floor(log2(max(width, height))); // Sampler is set up to do min reduction, so this computes the minimum depth of a 2x2 texel quad - float depth = cull_data.znear / textureLod(u_depth_pyramid, (aabb.xy + aabb.zw) * 0.5, level).x; + float depth = clamp(cull_data.znear / textureLod(u_depth_pyramid, (aabb.xy + aabb.zw) * 0.5, level).x, + cull_data.znear, cull_data.zfar); float depth_sphere = -center.z - radius; visible = depth_sphere <= depth;