Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Z fighting with improved depth offset math #1661

Merged
merged 2 commits into from
Mar 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions crates/re_renderer/shader/global_bindings.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ struct FrameUniformBuffer {

// Size used for all line radii given with Size::AUTO.
auto_size_lines: f32,

/// Factor used to compute depth offsets, see `depth_offset.wgsl`.
depth_offset_factor: f32,
};
@group(0) @binding(0)
var<uniform> frame: FrameUniformBuffer;
Expand Down
35 changes: 24 additions & 11 deletions crates/re_renderer/shader/utils/depth_offset.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,34 @@
#import <../types.wgsl>

fn apply_depth_offset(position: Vec4, offset: f32) -> Vec4 {
// Z buffer z is computed using position.z/position.w,
// Therefore, to affect the final output by a given offset we need to multiply it with position.w.
// This also means though that we're loosing a lot of precision
//
// We're using inverse z, i.e. 0.0 is far, 1.0 is near.
// We want a positive depth_offset_factor to move towards the viewer, so offset needs to be added.
// We want a positive offset to move towards the viewer, so offset needs to be added.
//
// With this in place we still may cross over to 0.0 (the far plane) too early,
// making objects disappear into the far when they'd be otherwise stilil rendered.
// making objects disappear into the far when they'd be otherwise still rendered.
// Since we're actually supposed to have an *infinite* far plane this should never happen!
// Therefore we simply dictacte a minimum z value.
// This ofc wrecks the depth offset and may cause z fighting with all very far away objects, but it's better than having things disappear!
return Vec4(
position.xy,
max(position.z + frame.depth_offset_factor * offset * position.w, f32eps),
position.w
);

if true {
// This path assumes a `f32` depth buffer!

// 1.0 * eps _should_ be enough, but in practice it causes Z-fighting for unknown reasons.
// Maybe because of GPU interpolation of vertex coordinates?
let eps = 5.0 * f32eps;

return Vec4(
position.xy,
max(position.z * (1.0 + eps * offset), f32eps),
position.w
);
} else {
// Causes Z-collision at far distances
let eps = f32eps;
return Vec4(
position.xy,
max(position.z + eps * offset * position.w, f32eps),
position.w
);
}
}
2 changes: 1 addition & 1 deletion crates/re_renderer/src/global_bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub(crate) struct FrameUniformBuffer {
pub auto_size_lines: f32,

/// Factor used to compute depth offsets, see `depth_offset.wgsl`.
pub depth_offset_factor: wgpu_buffer_types::F32RowPadded,
pub end_padding: wgpu_buffer_types::PaddingRow,
}

pub(crate) struct GlobalBindings {
Expand Down
6 changes: 1 addition & 5 deletions crates/re_renderer/src/view_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -405,10 +405,6 @@ impl ViewBuilder {
config.auto_size_config.line_radius
};

// See `depth_offset.wgsl`.
// Factor applied to depth offsets.
let depth_offset_factor = 1.0e-08; // Value determined by experimentation. Quite close to the f32 machine epsilon but a bit lower.

// Setup frame uniform buffer
let frame_uniform_buffer = create_and_fill_uniform_buffer(
ctx,
Expand All @@ -426,7 +422,7 @@ impl ViewBuilder {
auto_size_points: auto_size_points.0,
auto_size_lines: auto_size_lines.0,

depth_offset_factor: depth_offset_factor.into(),
end_padding: Default::default(),
},
);

Expand Down