diff --git a/src/shaders/heatmap.vertex.glsl b/src/shaders/heatmap.vertex.glsl index dda815d3973..a2308f86f01 100644 --- a/src/shaders/heatmap.vertex.glsl +++ b/src/shaders/heatmap.vertex.glsl @@ -6,6 +6,19 @@ uniform float u_intensity; attribute vec2 a_pos; +#ifdef PROJECTION_GLOBE_VIEW +attribute vec3 a_pos_3; // Projected position on the globe +attribute vec3 a_pos_normal_3; // Surface normal at the position +attribute float a_scale; + +// Uniforms required for transition between globe and mercator +uniform mat4 u_inv_rot_matrix; +uniform vec2 u_merc_center; +uniform vec3 u_tile_id; +uniform float u_zoom_transition; +uniform vec3 u_up_dir; +#endif + varying vec2 v_extrude; #pragma mapbox: define highp float weight @@ -48,7 +61,26 @@ void main(void) { // multiply a_pos by 0.5, since we had it * 2 in order to sneak // in extrusion data - vec3 pos = vec3(floor(a_pos * 0.5) + extrude, elevation(floor(a_pos * 0.5))); + vec2 tilePos = floor(a_pos * 0.5); + +#ifdef PROJECTION_GLOBE_VIEW + // Apply extra scaling to extrusion to cover different pixel space ratios (which is dependant on the latitude) + extrude *= a_scale; + + vec3 normal = normalize(mix(a_pos_normal_3 / 16384.0, u_up_dir, u_zoom_transition)); + + // Coordinate frame for the extrusion is the tangent plane at the point location on the globe surface + vec3 xAxis = normalize(vec3(normal.z, 0.0, -normal.x)); + vec3 yAxis = normalize(cross(normal, xAxis)); + + // Compute positions on both globe and mercator plane to support transition between the two modes + vec3 globePos = a_pos_3 + xAxis * extrude.x + yAxis * extrude.y + elevationVector(tilePos) * elevation(tilePos); + vec3 mercPos = mercator_tile_position(u_inv_rot_matrix, tilePos, u_tile_id, u_merc_center) + xAxis * extrude.x + yAxis * extrude.y; + + vec3 pos = mix_globe_mercator(globePos, mercPos, u_zoom_transition); +#else + vec3 pos = vec3(tilePos + extrude, elevation(tilePos)); +#endif gl_Position = u_matrix * vec4(pos, 1);