mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 20:53:53 +00:00
Fix float precision issue in the gizmo shader (#10408)
Fix a precision issue with in the manual near-clipping function. This only affected lines that span large distances (starting at 100_000~ units) in my testing. Fixes #10403
This commit is contained in:
parent
b1fd9eddbb
commit
7b2213a5f3
1 changed files with 7 additions and 4 deletions
|
@ -28,6 +28,8 @@ struct VertexOutput {
|
||||||
@location(0) color: vec4<f32>,
|
@location(0) color: vec4<f32>,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const EPSILON: f32 = 4.88e-04;
|
||||||
|
|
||||||
@vertex
|
@vertex
|
||||||
fn vertex(vertex: VertexInput) -> VertexOutput {
|
fn vertex(vertex: VertexInput) -> VertexOutput {
|
||||||
var positions = array<vec3<f32>, 6>(
|
var positions = array<vec3<f32>, 6>(
|
||||||
|
@ -79,7 +81,6 @@ fn vertex(vertex: VertexInput) -> VertexOutput {
|
||||||
if line_gizmo.depth_bias >= 0. {
|
if line_gizmo.depth_bias >= 0. {
|
||||||
depth = clip.z * (1. - line_gizmo.depth_bias);
|
depth = clip.z * (1. - line_gizmo.depth_bias);
|
||||||
} else {
|
} else {
|
||||||
let epsilon = 4.88e-04;
|
|
||||||
// depth * (clip.w / depth)^-depth_bias. So that when -depth_bias is 1.0, this is equal to clip.w
|
// depth * (clip.w / depth)^-depth_bias. So that when -depth_bias is 1.0, this is equal to clip.w
|
||||||
// and when equal to 0.0, it is exactly equal to depth.
|
// and when equal to 0.0, it is exactly equal to depth.
|
||||||
// the epsilon is here to prevent the depth from exceeding clip.w when -depth_bias = 1.0
|
// the epsilon is here to prevent the depth from exceeding clip.w when -depth_bias = 1.0
|
||||||
|
@ -87,7 +88,7 @@ fn vertex(vertex: VertexInput) -> VertexOutput {
|
||||||
// of this value means nothing can be in front of this
|
// of this value means nothing can be in front of this
|
||||||
// The reason this uses an exponential function is that it makes it much easier for the
|
// The reason this uses an exponential function is that it makes it much easier for the
|
||||||
// user to chose a value that is convenient for them
|
// user to chose a value that is convenient for them
|
||||||
depth = clip.z * exp2(-line_gizmo.depth_bias * log2(clip.w / clip.z - epsilon));
|
depth = clip.z * exp2(-line_gizmo.depth_bias * log2(clip.w / clip.z - EPSILON));
|
||||||
}
|
}
|
||||||
|
|
||||||
var clip_position = vec4(clip.w * ((2. * screen) / resolution - 1.), depth, clip.w);
|
var clip_position = vec4(clip.w * ((2. * screen) / resolution - 1.), depth, clip.w);
|
||||||
|
@ -101,8 +102,10 @@ fn clip_near_plane(a: vec4<f32>, b: vec4<f32>) -> vec4<f32> {
|
||||||
// Interpolate a towards b until it's at the near plane.
|
// Interpolate a towards b until it's at the near plane.
|
||||||
let distance_a = a.z - a.w;
|
let distance_a = a.z - a.w;
|
||||||
let distance_b = b.z - b.w;
|
let distance_b = b.z - b.w;
|
||||||
let t = distance_a / (distance_a - distance_b);
|
// Add an epsilon to the interpolator to ensure that the point is
|
||||||
return a + (b - a) * t;
|
// not just behind the clip plane due to floating-point imprecision.
|
||||||
|
let t = distance_a / (distance_a - distance_b) + EPSILON;
|
||||||
|
return mix(a, b, t);
|
||||||
}
|
}
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue