From e517016385bf578b437f8286f24951fb1b40fb4c Mon Sep 17 00:00:00 2001 From: Chris Loer Date: Mon, 19 Mar 2018 19:11:48 -0700 Subject: [PATCH] Make shaders clamp perspective ratio to reasonable ranges. This fixes issue #6363, but also guards against a class of bugs: We previously relied on the assumption that the perspective ratio was calculated with the same anchor point as the item we were drawing. If that assumption was violated, it was possible for overzoomed items far outside of the viewport to grow larger faster than they moved away from the viewport. They could eventually grow large enough to cover the viewport entirely, causing brief "flashes" during map animations. This commit does _not_ clamp the perspective ratios on the CPU side, to avoid extra work in the inner loop of very performance sensitive collision/projection code. On the collision side, anything far outside of the viewport should be collided/ignored anyway, and on the projection side, we have a filter requiring that the anchor of the label be within the viewport before the projection logic begins. --- src/shaders/collision_box.vertex.glsl | 5 ++++- src/shaders/symbol_icon.vertex.glsl | 5 ++++- src/shaders/symbol_sdf.vertex.glsl | 5 ++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/shaders/collision_box.vertex.glsl b/src/shaders/collision_box.vertex.glsl index a035ca58f9e..902efce076b 100644 --- a/src/shaders/collision_box.vertex.glsl +++ b/src/shaders/collision_box.vertex.glsl @@ -13,7 +13,10 @@ varying float v_notUsed; void main() { vec4 projectedPoint = u_matrix * vec4(a_anchor_pos, 0, 1); highp float camera_to_anchor_distance = projectedPoint.w; - highp float collision_perspective_ratio = 0.5 + 0.5 * (u_camera_to_center_distance / camera_to_anchor_distance); + highp float collision_perspective_ratio = clamp( + 0.5 + 0.5 * (u_camera_to_center_distance / camera_to_anchor_distance), + 0.0, // Prevents oversized near-field boxes in pitched/overzoomed tiles + 4.0); gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0); gl_Position.xy += a_extrude * u_extrude_scale * gl_Position.w * collision_perspective_ratio; diff --git a/src/shaders/symbol_icon.vertex.glsl b/src/shaders/symbol_icon.vertex.glsl index 31edb089676..9b6d19a878e 100644 --- a/src/shaders/symbol_icon.vertex.glsl +++ b/src/shaders/symbol_icon.vertex.glsl @@ -57,7 +57,10 @@ void main() { highp float distance_ratio = u_pitch_with_map ? camera_to_anchor_distance / u_camera_to_center_distance : u_camera_to_center_distance / camera_to_anchor_distance; - highp float perspective_ratio = 0.5 + 0.5 * distance_ratio; + highp float perspective_ratio = clamp( + 0.5 + 0.5 * distance_ratio, + 0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles + 4.0); size *= perspective_ratio; diff --git a/src/shaders/symbol_sdf.vertex.glsl b/src/shaders/symbol_sdf.vertex.glsl index c562dda1efb..e5f12731d4e 100644 --- a/src/shaders/symbol_sdf.vertex.glsl +++ b/src/shaders/symbol_sdf.vertex.glsl @@ -77,7 +77,10 @@ void main() { highp float distance_ratio = u_pitch_with_map ? camera_to_anchor_distance / u_camera_to_center_distance : u_camera_to_center_distance / camera_to_anchor_distance; - highp float perspective_ratio = 0.5 + 0.5 * distance_ratio; + highp float perspective_ratio = clamp( + 0.5 + 0.5 * distance_ratio, + 0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles + 4.0); size *= perspective_ratio;