Skip to content

Commit

Permalink
Fix globe terrain holes at poles (#5232)
Browse files Browse the repository at this point in the history
* Fix terrain pole holes

* Fix unit test

* Bring back globe/terrain/fill-planet-pole test

* Update build size

* Changelog update, _meshDict -> _meshCache

* Do not use terrain pole meshes when globe is disabled

* Add test for mercator terrain

* Fix unit tests
  • Loading branch information
kubapelc authored Dec 17, 2024
1 parent 9a05cb2 commit ab63cf4
Show file tree
Hide file tree
Showing 12 changed files with 178 additions and 30 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

### 🐞 Bug fixes

- Fix holes at the poles when terrain is used with globe ([#5232](https://github.com/maplibre/maplibre-gl-js/pull/5232))
- Fix geometry artifacts when globe terrain is zoomed out too much ([#5232](https://github.com/maplibre/maplibre-gl-js/pull/5232))
- _...Add new stuff here..._

## 5.0.0-pre.10
Expand Down
6 changes: 3 additions & 3 deletions src/render/draw_terrain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ function drawDepth(painter: Painter, terrain: Terrain) {
const tr = painter.transform;
const colorMode = ColorMode.unblended;
const depthMode = new DepthMode(gl.LEQUAL, DepthMode.ReadWrite, [0, 1]);
const mesh = terrain.getTerrainMesh();
const tiles = terrain.sourceCache.getRenderableTiles();
const program = painter.useProgram('terrainDepth');
context.bindFramebuffer.set(terrain.getFramebuffer('depth').framebuffer);
context.viewport.set([0, 0, painter.width / devicePixelRatio, painter.height / devicePixelRatio]);
context.clear({color: Color.transparent, depth: 1});
for (const tile of tiles) {
const mesh = terrain.getTerrainMesh(tile.tileID);
const terrainData = terrain.getTerrainData(tile.tileID);
const projectionData = tr.getProjectionData({overscaledTileID: tile.tileID, applyTerrainMatrix: false, applyGlobeMatrix: true});
const uniformValues = terrainDepthUniformValues(terrain.getMeshFrameDelta(tr.zoom));
Expand All @@ -46,7 +46,6 @@ function drawCoords(painter: Painter, terrain: Terrain) {
const tr = painter.transform;
const colorMode = ColorMode.unblended;
const depthMode = new DepthMode(gl.LEQUAL, DepthMode.ReadWrite, [0, 1]);
const mesh = terrain.getTerrainMesh();
const coords = terrain.getCoordsTexture();
const tiles = terrain.sourceCache.getRenderableTiles();

Expand All @@ -57,6 +56,7 @@ function drawCoords(painter: Painter, terrain: Terrain) {
context.clear({color: Color.transparent, depth: 1});
terrain.coordsIndex = [];
for (const tile of tiles) {
const mesh = terrain.getTerrainMesh(tile.tileID);
const terrainData = terrain.getTerrainData(tile.tileID);
context.activeTexture.set(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, coords.texture);
Expand All @@ -77,12 +77,12 @@ function drawTerrain(painter: Painter, terrain: Terrain, tiles: Array<Tile>, ren
const colorMode = painter.colorModeForRenderPass();
const depthMode = painter.getDepthModeFor3D();
const program = painter.useProgram('terrain');
const mesh = terrain.getTerrainMesh();

context.bindFramebuffer.set(null);
context.viewport.set([0, 0, painter.width, painter.height]);

for (const tile of tiles) {
const mesh = terrain.getTerrainMesh(tile.tileID);
const texture = painter.renderToTexture.getTexture(tile);
const terrainData = terrain.getTerrainData(tile.tileID);
context.activeTexture.set(gl.TEXTURE0);
Expand Down
3 changes: 3 additions & 0 deletions src/render/render_to_texture.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ describe('render to texture', () => {
'maine-hillshade': hillshadeLayer,
'maine-line': lineLayer,
'maine-symbol': symbolLayer
},
projection: {
transitionState: 0,
}
} as any as Style;
painter.style = style;
Expand Down
11 changes: 8 additions & 3 deletions src/render/terrain.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,11 @@ describe('Terrain', () => {
},
width: 1,
height: 1,
style: {
projection: {
transitionState: 0,
}
}
} as any as Painter;
const sourceCache = {
_source: {maxzoom: 12, tileSize: 512},
Expand All @@ -249,10 +254,10 @@ describe('Terrain', () => {
{exaggeration: 1} as any as TerrainSpecification,
);
terrain.meshSize = 4;
terrain.getTerrainMesh();
terrain.getTerrainMesh(new OverscaledTileID(2, 0, 2, 1, 1));
expect(terrain.getMeshFrameDelta(16)).toBe(122.16256373312942);
expect(actualIndexArray).toStrictEqual([0, 5, 6, 0, 6, 1, 1, 6, 7, 1, 7, 2, 2, 7, 8, 2, 8, 3, 3, 8, 9, 3, 9, 4, 5, 10, 11, 5, 11, 6, 6, 11, 12, 6, 12, 7, 7, 12, 13, 7, 13, 8, 8, 13, 14, 8, 14, 9, 10, 15, 16, 10, 16, 11, 11, 16, 17, 11, 17, 12, 12, 17, 18, 12, 18, 13, 13, 18, 19, 13, 19, 14, 15, 20, 21, 15, 21, 16, 16, 21, 22, 16, 22, 17, 17, 22, 23, 17, 23, 18, 18, 23, 24, 18, 24, 19, 35, 36, 38, 35, 38, 37, 25, 28, 26, 25, 27, 28, 37, 38, 40, 37, 40, 39, 27, 30, 28, 27, 29, 30, 39, 40, 42, 39, 42, 41, 29, 32, 30, 29, 31, 32, 41, 42, 44, 41, 44, 43, 31, 34, 32, 31, 33, 34, 45, 46, 48, 45, 48, 47, 55, 58, 56, 55, 57, 58, 47, 48, 50, 47, 50, 49, 57, 60, 58, 57, 59, 60, 49, 50, 52, 49, 52, 51, 59, 62, 60, 59, 61, 62, 51, 52, 54, 51, 54, 53, 61, 64, 62, 61, 63, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
expect(actualVertexArray).toStrictEqual([0, 0, 0, 2048, 0, 0, 4096, 0, 0, 6144, 0, 0, 8192, 0, 0, 0, 2048, 0, 2048, 2048, 0, 4096, 2048, 0, 6144, 2048, 0, 8192, 2048, 0, 0, 4096, 0, 2048, 4096, 0, 4096, 4096, 0, 6144, 4096, 0, 8192, 4096, 0, 0, 6144, 0, 2048, 6144, 0, 4096, 6144, 0, 6144, 6144, 0, 8192, 6144, 0, 0, 8192, 0, 2048, 8192, 0, 4096, 8192, 0, 6144, 8192, 0, 8192, 8192, 0, 0, 0, 0, 0, 0, 1, 2048, 0, 0, 2048, 0, 1, 4096, 0, 0, 4096, 0, 1, 6144, 0, 0, 6144, 0, 1, 8192, 0, 0, 8192, 0, 1, 0, 8192, 0, 0, 8192, 1, 2048, 8192, 0, 2048, 8192, 1, 4096, 8192, 0, 4096, 8192, 1, 6144, 8192, 0, 6144, 8192, 1, 8192, 8192, 0, 8192, 8192, 1, 0, 0, 0, 0, 0, 1, 0, 2048, 0, 0, 2048, 1, 0, 4096, 0, 0, 4096, 1, 0, 6144, 0, 0, 6144, 1, 0, 8192, 0, 0, 8192, 1, 8192, 0, 0, 8192, 0, 1, 8192, 2048, 0, 8192, 2048, 1, 8192, 4096, 0, 8192, 4096, 1, 8192, 6144, 0, 8192, 6144, 1, 8192, 8192, 0, 8192, 8192, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
expect(actualIndexArray).toStrictEqual([0, 5, 6, 0, 6, 1, 1, 6, 7, 1, 7, 2, 2, 7, 8, 2, 8, 3, 3, 8, 9, 3, 9, 4, 5, 10, 11, 5, 11, 6, 6, 11, 12, 6, 12, 7, 7, 12, 13, 7, 13, 8, 8, 13, 14, 8, 14, 9, 10, 15, 16, 10, 16, 11, 11, 16, 17, 11, 17, 12, 12, 17, 18, 12, 18, 13, 13, 18, 19, 13, 19, 14, 15, 20, 21, 15, 21, 16, 16, 21, 22, 16, 22, 17, 17, 22, 23, 17, 23, 18, 18, 23, 24, 18, 24, 19, 20, 30, 31, 20, 31, 21, 0, 26, 25, 0, 1, 26, 21, 31, 32, 21, 32, 22, 1, 27, 26, 1, 2, 27, 22, 32, 33, 22, 33, 23, 2, 28, 27, 2, 3, 28, 23, 33, 34, 23, 34, 24, 3, 29, 28, 3, 4, 29, 35, 36, 38, 35, 38, 37, 45, 48, 46, 45, 47, 48, 37, 38, 40, 37, 40, 39, 47, 50, 48, 47, 49, 50, 39, 40, 42, 39, 42, 41, 49, 52, 50, 49, 51, 52, 41, 42, 44, 41, 44, 43, 51, 54, 52, 51, 53, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
expect(actualVertexArray).toStrictEqual([0, 0, 0, 2048, 0, 0, 4096, 0, 0, 6144, 0, 0, 8192, 0, 0, 0, 2048, 0, 2048, 2048, 0, 4096, 2048, 0, 6144, 2048, 0, 8192, 2048, 0, 0, 4096, 0, 2048, 4096, 0, 4096, 4096, 0, 6144, 4096, 0, 8192, 4096, 0, 0, 6144, 0, 2048, 6144, 0, 4096, 6144, 0, 6144, 6144, 0, 8192, 6144, 0, 0, 8192, 0, 2048, 8192, 0, 4096, 8192, 0, 6144, 8192, 0, 8192, 8192, 0, 0, 0, 1, 2048, 0, 1, 4096, 0, 1, 6144, 0, 1, 8192, 0, 1, 0, 8192, 1, 2048, 8192, 1, 4096, 8192, 1, 6144, 8192, 1, 8192, 8192, 1, 0, 0, 0, 0, 0, 1, 0, 2048, 0, 0, 2048, 1, 0, 4096, 0, 0, 4096, 1, 0, 6144, 0, 0, 6144, 1, 0, 8192, 0, 0, 8192, 1, 8192, 0, 0, 8192, 0, 1, 8192, 2048, 0, 8192, 2048, 1, 8192, 4096, 0, 8192, 4096, 1, 8192, 6144, 0, 8192, 6144, 1, 8192, 8192, 0, 8192, 8192, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
});

test('interpolation works', () => {
Expand Down
61 changes: 43 additions & 18 deletions src/render/terrain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import type {TerrainSpecification} from '@maplibre/maplibre-gl-style-spec';
import {type LngLat, earthRadius} from '../geo/lng_lat';
import {Mesh} from './mesh';
import {isInBoundsForZoomLngLat} from '../util/world_bounds';
import {NORTH_POLE_Y, SOUTH_POLE_Y} from './subdivision';

/**
* @internal
Expand Down Expand Up @@ -108,7 +109,7 @@ export class Terrain {
* GL Objects for the terrain-mesh
* The mesh is a regular mesh, which has the advantage that it can be reused for all tiles.
*/
_mesh: Mesh;
_meshCache: { [key: string]: Mesh } = {};
/**
* coords index contains a list of tileID.keys. This index is used to identify
* the tile via the alpha-cannel in the coords-texture.
Expand Down Expand Up @@ -376,46 +377,70 @@ export class Terrain {
* create a regular mesh which will be used by all terrain-tiles
* @returns the created regular mesh
*/
getTerrainMesh(): Mesh {
if (this._mesh) return this._mesh;
getTerrainMesh(tileId: OverscaledTileID): Mesh {
const globeEnabled = this.painter.style.projection.transitionState > 0;
const northPole = globeEnabled && tileId.canonical.y === 0;
const southPole = globeEnabled && tileId.canonical.y === (1 << tileId.canonical.z) - 1;
const key = `m_${northPole ? 'n' : ''}_${southPole ? 's' : ''}`;
if (this._meshCache[key]) {
return this._meshCache[key];
}
const context = this.painter.context;

const vertexArray = new Pos3dArray();
const indexArray = new TriangleIndexArray();
const meshSize = this.meshSize;
const delta = EXTENT / meshSize;
const meshSize2 = meshSize * meshSize;
for (let y = 0; y <= meshSize; y++) for (let x = 0; x <= meshSize; x++)
for (let y = 0; y <= meshSize; y++) for (let x = 0; x <= meshSize; x++) {
vertexArray.emplaceBack(x * delta, y * delta, 0);
}
for (let y = 0; y < meshSize2; y += meshSize + 1) for (let x = 0; x < meshSize; x++) {
indexArray.emplaceBack(x + y, meshSize + x + y + 1, meshSize + x + y + 2);
indexArray.emplaceBack(x + y, meshSize + x + y + 2, x + y + 1);
}
// add an extra frame around the mesh to avoid stitching on tile boundaries with different zoomlevels
// first code-block is for top-bottom frame and second for left-right frame
const offsetTop = vertexArray.length, offsetBottom = offsetTop + (meshSize + 1) * 2;
for (const y of [0, 1]) for (let x = 0; x <= meshSize; x++) for (const z of [0, 1])
vertexArray.emplaceBack(x * delta, y * EXTENT, z);
for (let x = 0; x < meshSize * 2; x += 2) {
indexArray.emplaceBack(offsetBottom + x, offsetBottom + x + 1, offsetBottom + x + 3);
indexArray.emplaceBack(offsetBottom + x, offsetBottom + x + 3, offsetBottom + x + 2);
indexArray.emplaceBack(offsetTop + x, offsetTop + x + 3, offsetTop + x + 1);
indexArray.emplaceBack(offsetTop + x, offsetTop + x + 2, offsetTop + x + 3);
// top-bottom frame + pole vertices, if needed
const offsetTop = vertexArray.length;
const offsetTopEdge = 0;
const offsetBottom = offsetTop + (meshSize + 1);
const offsetBottomEdge = (meshSize + 1) * meshSize;
const northY = northPole ? NORTH_POLE_Y : 0;
const northZ = northPole ? 0 : 1;
const southY = southPole ? SOUTH_POLE_Y : EXTENT;
const southZ = southPole ? 0 : 1;
for (let x = 0; x <= meshSize; x++) {
vertexArray.emplaceBack(x * delta, northY, northZ);
}
for (let x = 0; x <= meshSize; x++) {
vertexArray.emplaceBack(x * delta, southY, southZ);
}
const offsetLeft = vertexArray.length, offsetRight = offsetLeft + (meshSize + 1) * 2;
for (const x of [0, 1]) for (let y = 0; y <= meshSize; y++) for (const z of [0, 1])
for (let x = 0; x < meshSize; x++) {
indexArray.emplaceBack(offsetBottomEdge + x, offsetBottom + x, offsetBottom + x + 1);
indexArray.emplaceBack(offsetBottomEdge + x, offsetBottom + x + 1, offsetBottomEdge + x + 1);
indexArray.emplaceBack(offsetTopEdge + x, offsetTop + x + 1, offsetTop + x);
indexArray.emplaceBack(offsetTopEdge + x, offsetTopEdge + x + 1, offsetTop + x + 1);
}
// left-right frame
const offsetLeft = vertexArray.length;
const offsetRight = offsetLeft + (meshSize + 1) * 2;
for (const x of [0, 1]) for (let y = 0; y <= meshSize; y++) for (const z of [0, 1]) {
vertexArray.emplaceBack(x * EXTENT, y * delta, z);
}
for (let y = 0; y < meshSize * 2; y += 2) {
indexArray.emplaceBack(offsetLeft + y, offsetLeft + y + 1, offsetLeft + y + 3);
indexArray.emplaceBack(offsetLeft + y, offsetLeft + y + 3, offsetLeft + y + 2);
indexArray.emplaceBack(offsetRight + y, offsetRight + y + 3, offsetRight + y + 1);
indexArray.emplaceBack(offsetRight + y, offsetRight + y + 2, offsetRight + y + 3);
}
this._mesh = new Mesh(

const mesh = new Mesh(
context.createVertexBuffer(vertexArray, pos3dAttributes.members),
context.createIndexBuffer(indexArray),
SegmentVector.simpleSegment(0, 0, vertexArray.length, indexArray.length)
);
return this._mesh;
this._meshCache[key] = mesh;
return mesh;
}

/**
Expand All @@ -426,7 +451,7 @@ export class Terrain {
*/
getMeshFrameDelta(zoom: number): number {
// divide by 5 is evaluated by trial & error to get a frame in the right height
return 2 * Math.PI * earthRadius / Math.pow(2, zoom) / 5;
return 2 * Math.PI * earthRadius / Math.pow(2, Math.max(zoom, 0)) / 5;
}

getMinTileElevationForLngLatZoom(lnglat: LngLat, zoom: number) {
Expand Down
5 changes: 5 additions & 0 deletions src/shaders/_prelude.vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,11 @@ float ele(vec2 pos) {
// calculate the elevation with linear interpolation for a coordinate
float get_elevation(vec2 pos) {
#ifdef TERRAIN3D
#ifdef GLOBE
if ((pos.y < -32767.5) || (pos.y > 32766.5)) {
return 0.0;
}
#endif
vec2 coord = (u_terrain_matrix * vec4(pos, 0.0, 1.0)).xy * u_terrain_dim + 1.0;
vec2 f = fract(coord);
vec2 c = (floor(coord) + 0.5) / (u_terrain_dim + 2.0); // get the pixel center
Expand Down
14 changes: 9 additions & 5 deletions src/shaders/_projection_globe.vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,13 @@ float projectLineThickness(float tileY) {
}
}

// get position inside the tile in range 0..8192 and project it onto the surface of a unit sphere
vec3 projectToSphere(vec2 posInTile, vec2 rawPos) {
// Get position inside the tile in range 0..8192 and project it onto the surface of a unit sphere.
// Additionally project special Y values to the poles.
// - translatedPos: tile-space vertex position, optionally with user-specified translation already applied
// - rawPos: the original tile-space vertex position *without translation* - needed because we would not be able to detect pole vertices from coordinates modified by translation.
vec3 projectToSphere(vec2 translatedPos, vec2 rawPos) {
// Compute position in range 0..1 of the base tile of web mercator
vec2 mercator_pos = u_projection_tile_mercator_coords.xy + u_projection_tile_mercator_coords.zw * posInTile;
vec2 mercator_pos = u_projection_tile_mercator_coords.xy + u_projection_tile_mercator_coords.zw * translatedPos;

// Now compute angular coordinates on the surface of a perfect sphere
vec2 spherical;
Expand Down Expand Up @@ -129,7 +132,7 @@ vec4 projectTile(vec2 posInTile) {
return interpolateProjection(posInTile, projectToSphere(posInTile), 0.0);
}

// A variant that supports special pole and planet center vertices.
// A variant that supports special pole vertices.
vec4 projectTile(vec2 posInTile, vec2 rawPos) {
return interpolateProjection(posInTile, projectToSphere(posInTile, rawPos), 0.0);
}
Expand All @@ -142,7 +145,8 @@ vec4 projectTileWithElevation(vec2 posInTile, float elevation) {
}

// Projects the tile coordinates+elevation while **preserving Z** value from multiplication with the projection matrix.
// Applies pole vertices.
vec4 projectTileFor3D(vec2 posInTile, float elevation) {
vec3 spherePos = projectToSphere(posInTile);
vec3 spherePos = projectToSphere(posInTile, posInTile);
return interpolateProjectionFor3D(posInTile, spherePos, elevation);
}
2 changes: 1 addition & 1 deletion test/build/min.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ describe('test min build', () => {
const decreaseQuota = 4096;

// feel free to update this value after you've checked that it has changed on purpose :-)
const expectedBytes = 907610;
const expectedBytes = 907350;

expect(actualBytes).toBeLessThan(expectedBytes + increaseQuota);
expect(actualBytes).toBeGreaterThan(expectedBytes - decreaseQuota);
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"version": 8,
"metadata": {
"test": {}
},
"sky": {
"atmosphere-blend": 0.0
},
"center": [
0.0,
80.0
],
"zoom": -0.5,
"projection": {
"type": "globe"
},
"terrain": {
"source": "terrain",
"exaggeration": 2
},
"sources": {
"terrain": {
"type": "raster-dem",
"tiles": ["local://tiles/{z}-{x}-{y}.terrain.png"],
"maxzoom": 15,
"tileSize": 256
},
"vector_tiles": {
"type": "vector",
"maxzoom": 0,
"tiles": [
"local://tiles/{z}-{x}-{y}.mvt"
]
}
},
"layers": [
{
"id": "background",
"type": "background",
"paint": {
"background-color": "white"
}
},
{
"id": "land",
"type": "fill",
"source": "vector_tiles",
"source-layer": "water",
"paint": {
"fill-color": "blue"
}
}
]
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit ab63cf4

Please sign in to comment.