diff --git a/debug/satellites-custom-layer.js b/debug/satellites-custom-layer.js index 8b7b2fb7f68..243d1604679 100644 --- a/debug/satellites-custom-layer.js +++ b/debug/satellites-custom-layer.js @@ -1,8 +1,3 @@ -const EARTH_RADIUS_METERS = 6371008.8; -const EARTH_CIRCUMFERENCE_METERS = 2 * Math.PI * EARTH_RADIUS_METERS; -const GLOBE_CIRCUMFERENCE_ECEF = 8192; -const METERS_TO_ECEF = GLOBE_CIRCUMFERENCE_ECEF / EARTH_CIRCUMFERENCE_METERS; - const KM_TO_M = 1000; const TIME_STEP = 3 * 1000; @@ -13,12 +8,19 @@ const globeVertCode = ` uniform mat4 u_projection; uniform mat4 u_globeToMercMatrix; uniform float u_globeToMercatorTransition; + uniform vec2 u_centerInMerc; + uniform float u_pixelsPerMeterRatio; void main() { vec4 p = u_projection * u_globeToMercMatrix * vec4(a_pos_ecef, 1.); p /= p.w; if (u_globeToMercatorTransition > 0.) { - vec4 merc = u_projection * vec4(a_pos_merc, 1.); + + vec4 merc = vec4(a_pos_merc, 1.); + merc.xy = (merc.xy - u_centerInMerc) * u_pixelsPerMeterRatio + u_centerInMerc; + merc.z *= u_pixelsPerMeterRatio; + + merc = u_projection * merc; merc /= merc.w; p = mix(p, merc, u_globeToMercatorTransition); } @@ -141,21 +143,22 @@ const satellitesLayer = { } }, - render (gl, projectionMatrix, projection, globeToMercMatrix, transition) { + render (gl, projectionMatrix, projection, globeToMercMatrix, transition, centerInMercator, pixelsPerMeterRatio) { if (this.satData) { this.updateBuffers(); const primitiveCount = this.posEcef.length / 3; - gl.enable(gl.DEPTH_TEST); + gl.disable(gl.DEPTH_TEST); if (projection && projection.name === 'globe') { // globe projection and globe to mercator transition gl.useProgram(this.globeProgram); updateVboAndActivateAttrib(gl, this.globeProgram, this.posEcefVbo, this.posEcef, "a_pos_ecef"); updateVboAndActivateAttrib(gl, this.globeProgram, this.posMercVbo, this.posMerc, "a_pos_merc"); - gl.uniformMatrix4fv(gl.getUniformLocation(this.globeProgram, "u_projection"), false, projectionMatrix); gl.uniformMatrix4fv(gl.getUniformLocation(this.globeProgram, "u_globeToMercMatrix"), false, globeToMercMatrix); gl.uniform1f(gl.getUniformLocation(this.globeProgram, "u_globeToMercatorTransition"), transition); + gl.uniform2f(gl.getUniformLocation(this.globeProgram, "u_centerInMerc"), centerInMercator[0], centerInMercator[1]); + gl.uniform1f(gl.getUniformLocation(this.globeProgram, "u_pixelsPerMeterRatio"), pixelsPerMeterRatio); gl.drawArrays(gl.POINTS, 0, primitiveCount); } else { // mercator projection diff --git a/src/geo/transform.js b/src/geo/transform.js index bcf94181cd6..c7e96e6e710 100644 --- a/src/geo/transform.js +++ b/src/geo/transform.js @@ -1114,6 +1114,12 @@ class Transform { // Point at center in world coordinates. get point(): Point { return this.project(this.center); } + // Point at center in Mercator coordinates. + get pointMerc(): Point { return this.point._div(this.worldSize); } + + // Ratio of pixelsPerMeter in the current projection to Mercator's. + get pixelsPerMeterRatio(): number { return this.pixelsPerMeter / mercatorZfromAltitude(1, this.center.lat) / this.worldSize; } + setLocationAtPoint(lnglat: LngLat, point: Point) { let x, y; const centerPoint = this.centerPoint; diff --git a/src/render/draw_custom.js b/src/render/draw_custom.js index 9b13df75beb..81326e91c1d 100644 --- a/src/render/draw_custom.js +++ b/src/render/draw_custom.js @@ -33,7 +33,8 @@ function drawCustom(painter: Painter, sourceCache: SourceCache, layer: CustomSty context.setColorMode(painter.colorModeForRenderPass()); if (painter.transform.projection.name === "globe") { - prerender.call(implementation, context.gl, painter.transform.customLayerMatrix(), painter.transform.getProjection(), painter.transform.globeToMercatorMatrix(), globeToMercatorTransition(painter.transform.zoom)); + const center = painter.transform.pointMerc; + prerender.call(implementation, context.gl, painter.transform.customLayerMatrix(), painter.transform.getProjection(), painter.transform.globeToMercatorMatrix(), globeToMercatorTransition(painter.transform.zoom), [center.x, center.y], painter.transform.pixelsPerMeterRatio); } else { prerender.call(implementation, context.gl, painter.transform.customLayerMatrix()); } @@ -76,7 +77,8 @@ function drawCustom(painter: Painter, sourceCache: SourceCache, layer: CustomSty context.setDepthMode(depthMode); if (painter.transform.projection.name === "globe") { - implementation.render(context.gl, painter.transform.customLayerMatrix(), painter.transform.getProjection(), painter.transform.globeToMercatorMatrix(), globeToMercatorTransition(painter.transform.zoom)); + const center = painter.transform.pointMerc; + implementation.render(context.gl, painter.transform.customLayerMatrix(), painter.transform.getProjection(), painter.transform.globeToMercatorMatrix(), globeToMercatorTransition(painter.transform.zoom), [center.x, center.y], painter.transform.pixelsPerMeterRatio); } else { implementation.render(context.gl, painter.transform.customLayerMatrix()); } diff --git a/src/style/style_layer/custom_style_layer.js b/src/style/style_layer/custom_style_layer.js index c4120227849..7dc7f4d7e19 100644 --- a/src/style/style_layer/custom_style_layer.js +++ b/src/style/style_layer/custom_style_layer.js @@ -7,7 +7,7 @@ import assert from 'assert'; import type {ValidationErrors} from '../validate_style.js'; import type {ProjectionSpecification} from '../../style-spec/types.js'; -type CustomRenderMethod = (gl: WebGLRenderingContext, matrix: Array, projection: ?ProjectionSpecification, projectionToMercatorMatrix: ?Array, projectionToMercatorTransition: ?number) => void; +type CustomRenderMethod = (gl: WebGLRenderingContext, matrix: Array, projection: ?ProjectionSpecification, projectionToMercatorMatrix: ?Array, projectionToMercatorTransition: ?number, centerInMercator: ?Array, pixelsPerMeterRatio: ?number) => void; /** * Interface for custom style layers. This is a specification for