mirror of
https://github.com/bevyengine/bevy
synced 2024-11-21 12:13:25 +00:00
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
This commit is contained in:
parent
16b39c2b36
commit
fcf6067a10
2 changed files with 21 additions and 9 deletions
|
@ -5,6 +5,12 @@
|
|||
#ifdef OIT_ENABLED
|
||||
// Add the fragment to the oit buffer
|
||||
fn oit_draw(position: vec4f, color: vec4f) {
|
||||
// Don't add fully transparent fragments to the list
|
||||
// because we don't want to have to sort them in the resolve pass
|
||||
// TODO should this be comparing with < espilon ?
|
||||
if color.a == 0.0 {
|
||||
return;
|
||||
}
|
||||
// get the index of the current fragment relative to the screen size
|
||||
let screen_index = i32(floor(position.x) + floor(position.y) * view.viewport.z);
|
||||
// get the size of the buffer.
|
||||
|
|
|
@ -34,16 +34,13 @@ fn fragment(in: FullscreenVertexOutput) -> @location(0) vec4<f32> {
|
|||
}
|
||||
return vec4(0.0);
|
||||
} else {
|
||||
let result = sort(screen_index, buffer_size);
|
||||
reset_indices(screen_index);
|
||||
|
||||
// Manually do depth testing.
|
||||
// Load depth for manual depth testing.
|
||||
// This is necessary because early z doesn't seem to trigger in the transparent pass.
|
||||
// Once we have a per pixel linked list it should be done much earlier
|
||||
// This should be done during the draw pass so those fragments simply don't exist in the list,
|
||||
// but this requires a bigger refactor
|
||||
let d = textureLoad(depth, vec2<i32>(in.position.xy), 0);
|
||||
if d > result.depth {
|
||||
discard;
|
||||
}
|
||||
let result = sort(screen_index, buffer_size, d);
|
||||
reset_indices(screen_index);
|
||||
|
||||
return result.color;
|
||||
}
|
||||
|
@ -61,7 +58,7 @@ struct SortResult {
|
|||
depth: f32,
|
||||
}
|
||||
|
||||
fn sort(screen_index: i32, buffer_size: i32) -> SortResult {
|
||||
fn sort(screen_index: i32, buffer_size: i32, opaque_depth: f32) -> SortResult {
|
||||
var counter = atomicLoad(&layer_ids[screen_index]);
|
||||
|
||||
// fill list
|
||||
|
@ -90,10 +87,19 @@ fn sort(screen_index: i32, buffer_size: i32) -> SortResult {
|
|||
// resolve blend
|
||||
var final_color = vec4(0.0);
|
||||
for (var i = 0; i <= counter; i += 1) {
|
||||
// depth testing
|
||||
// This needs to happen here because we can only stop iterating if the fragment is
|
||||
// occluded by something opaque and the fragments need to be sorted first
|
||||
if fragment_list[i].depth < opaque_depth {
|
||||
break;
|
||||
}
|
||||
let color = fragment_list[i].color;
|
||||
let alpha = fragment_list[i].alpha;
|
||||
var base_color = vec4(color.rgb * alpha, alpha);
|
||||
final_color = blend(final_color, base_color);
|
||||
if final_color.a == 1.0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
var result: SortResult;
|
||||
result.color = final_color;
|
||||
|
|
Loading…
Reference in a new issue