Skip to content

Commit fcf6067

Browse files
authored
Fix OIT depth test (#15991)
# Objective - The depth test was only using the final depth but it should be testing each fragments - Fully transparent fragments should not be added to the list ## Solution - Test each fragment after sorting ## Testing before: TODO after: TODO
1 parent 16b39c2 commit fcf6067

File tree

2 files changed

+21
-9
lines changed

2 files changed

+21
-9
lines changed

crates/bevy_core_pipeline/src/oit/oit_draw.wgsl

+6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@
55
#ifdef OIT_ENABLED
66
// Add the fragment to the oit buffer
77
fn oit_draw(position: vec4f, color: vec4f) {
8+
// Don't add fully transparent fragments to the list
9+
// because we don't want to have to sort them in the resolve pass
10+
// TODO should this be comparing with < espilon ?
11+
if color.a == 0.0 {
12+
return;
13+
}
814
// get the index of the current fragment relative to the screen size
915
let screen_index = i32(floor(position.x) + floor(position.y) * view.viewport.z);
1016
// get the size of the buffer.

crates/bevy_core_pipeline/src/oit/resolve/oit_resolve.wgsl

+15-9
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,13 @@ fn fragment(in: FullscreenVertexOutput) -> @location(0) vec4<f32> {
3434
}
3535
return vec4(0.0);
3636
} else {
37-
let result = sort(screen_index, buffer_size);
38-
reset_indices(screen_index);
39-
40-
// Manually do depth testing.
37+
// Load depth for manual depth testing.
4138
// This is necessary because early z doesn't seem to trigger in the transparent pass.
42-
// Once we have a per pixel linked list it should be done much earlier
39+
// This should be done during the draw pass so those fragments simply don't exist in the list,
40+
// but this requires a bigger refactor
4341
let d = textureLoad(depth, vec2<i32>(in.position.xy), 0);
44-
if d > result.depth {
45-
discard;
46-
}
42+
let result = sort(screen_index, buffer_size, d);
43+
reset_indices(screen_index);
4744

4845
return result.color;
4946
}
@@ -61,7 +58,7 @@ struct SortResult {
6158
depth: f32,
6259
}
6360

64-
fn sort(screen_index: i32, buffer_size: i32) -> SortResult {
61+
fn sort(screen_index: i32, buffer_size: i32, opaque_depth: f32) -> SortResult {
6562
var counter = atomicLoad(&layer_ids[screen_index]);
6663

6764
// fill list
@@ -90,10 +87,19 @@ fn sort(screen_index: i32, buffer_size: i32) -> SortResult {
9087
// resolve blend
9188
var final_color = vec4(0.0);
9289
for (var i = 0; i <= counter; i += 1) {
90+
// depth testing
91+
// This needs to happen here because we can only stop iterating if the fragment is
92+
// occluded by something opaque and the fragments need to be sorted first
93+
if fragment_list[i].depth < opaque_depth {
94+
break;
95+
}
9396
let color = fragment_list[i].color;
9497
let alpha = fragment_list[i].alpha;
9598
var base_color = vec4(color.rgb * alpha, alpha);
9699
final_color = blend(final_color, base_color);
100+
if final_color.a == 1.0 {
101+
break;
102+
}
97103
}
98104
var result: SortResult;
99105
result.color = final_color;

0 commit comments

Comments
 (0)