maplibre-gl 6.0.0 → 6.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. package/build/readme.md +0 -2
  2. package/dist/maplibre-gl-dev.mjs +433 -573
  3. package/dist/maplibre-gl-dev.mjs.map +1 -1
  4. package/dist/maplibre-gl-shared-dev.mjs +984 -850
  5. package/dist/maplibre-gl-shared-dev.mjs.map +1 -1
  6. package/dist/maplibre-gl-shared.mjs +2 -2
  7. package/dist/maplibre-gl-shared.mjs.map +1 -1
  8. package/dist/maplibre-gl-worker-dev.mjs +14 -12
  9. package/dist/maplibre-gl-worker-dev.mjs.map +1 -1
  10. package/dist/maplibre-gl-worker.mjs +2 -2
  11. package/dist/maplibre-gl-worker.mjs.map +1 -1
  12. package/dist/maplibre-gl.css +1 -1
  13. package/dist/maplibre-gl.d.ts +119 -42
  14. package/dist/maplibre-gl.mjs +22 -22
  15. package/dist/maplibre-gl.mjs.map +1 -1
  16. package/package.json +20 -22
  17. package/src/css/maplibre-gl.css +4 -0
  18. package/src/data/bucket/circle_bucket.ts +3 -2
  19. package/src/data/bucket/fill_bucket.ts +3 -2
  20. package/src/data/bucket/fill_extrusion_bucket.test.ts +22 -0
  21. package/src/data/bucket/fill_extrusion_bucket.ts +17 -4
  22. package/src/data/bucket/line_bucket.test.ts +5 -5
  23. package/src/data/bucket/line_bucket.ts +3 -2
  24. package/src/data/bucket/round_polygon_corners.test.ts +159 -0
  25. package/src/data/bucket/round_polygon_corners.ts +121 -0
  26. package/src/data/bucket/symbol_bucket.test.ts +7 -7
  27. package/src/data/dem_data.test.ts +23 -23
  28. package/src/data/feature_position_map.test.ts +1 -1
  29. package/src/data/segment.test.ts +14 -14
  30. package/src/geo/bounds.test.ts +4 -4
  31. package/src/geo/lng_lat_bounds.test.ts +1 -1
  32. package/src/geo/projection/covering_tiles.bench.ts +39 -0
  33. package/src/geo/projection/covering_tiles.test.ts +3 -7
  34. package/src/geo/projection/covering_tiles.ts +37 -2
  35. package/src/geo/projection/globe_covering_tiles_details_provider.ts +4 -4
  36. package/src/geo/projection/globe_projection.test.ts +2 -2
  37. package/src/geo/projection/globe_projection.ts +6 -15
  38. package/src/geo/projection/globe_transform.test.ts +3 -6
  39. package/src/geo/projection/globe_transform.ts +4 -7
  40. package/src/geo/projection/mercator_covering_tiles_details_provider.ts +4 -4
  41. package/src/geo/projection/mercator_projection.ts +1 -13
  42. package/src/geo/projection/mercator_transform.test.ts +1 -1
  43. package/src/geo/projection/mercator_transform.ts +2 -1
  44. package/src/geo/projection/mercator_utils.test.ts +8 -8
  45. package/src/geo/projection/projection.ts +0 -27
  46. package/src/geo/projection/projection_data.ts +8 -0
  47. package/src/geo/projection/projection_factory.ts +3 -3
  48. package/src/geo/projection/vertical_perspective_projection.ts +3 -60
  49. package/src/geo/projection/vertical_perspective_transform.ts +16 -23
  50. package/src/geo/transform_interface.ts +1 -2
  51. package/src/index.test.ts +7 -12
  52. package/src/index.ts +4 -2
  53. package/src/render/glyph_manager.test.ts +7 -22
  54. package/src/render/painter.test.ts +2 -0
  55. package/src/render/painter.ts +8 -11
  56. package/src/render/subdivision.bench.ts +39 -0
  57. package/src/render/subdivision.test.ts +22 -23
  58. package/src/render/subdivision.ts +46 -0
  59. package/src/render/terrain.test.ts +68 -34
  60. package/src/render/terrain.ts +69 -26
  61. package/src/shaders/glsl/_projection_globe.fragment.glsl +12 -0
  62. package/src/shaders/glsl/_projection_globe.fragment.glsl.g.ts +2 -0
  63. package/src/shaders/glsl/_projection_globe.vertex.glsl +29 -10
  64. package/src/shaders/glsl/_projection_globe.vertex.glsl.g.ts +1 -1
  65. package/src/shaders/glsl/_projection_mercator.fragment.glsl +4 -0
  66. package/src/shaders/glsl/_projection_mercator.fragment.glsl.g.ts +2 -0
  67. package/src/shaders/glsl/line.fragment.glsl +2 -0
  68. package/src/shaders/glsl/line.fragment.glsl.g.ts +1 -1
  69. package/src/shaders/glsl/line_gradient.fragment.glsl +2 -0
  70. package/src/shaders/glsl/line_gradient.fragment.glsl.g.ts +1 -1
  71. package/src/shaders/glsl/line_gradient_sdf.fragment.glsl +2 -0
  72. package/src/shaders/glsl/line_gradient_sdf.fragment.glsl.g.ts +1 -1
  73. package/src/shaders/glsl/line_pattern.fragment.glsl +2 -0
  74. package/src/shaders/glsl/line_pattern.fragment.glsl.g.ts +1 -1
  75. package/src/shaders/glsl/line_sdf.fragment.glsl +2 -0
  76. package/src/shaders/glsl/line_sdf.fragment.glsl.g.ts +1 -1
  77. package/src/shaders/shaders.ts +4 -6
  78. package/src/source/canvas_source.test.ts +1 -1
  79. package/src/source/geojson_source.test.ts +32 -4
  80. package/src/source/geojson_source.ts +41 -0
  81. package/src/source/geojson_source_diff.test.ts +2 -2
  82. package/src/source/geojson_worker_source.test.ts +9 -5
  83. package/src/source/image_source.test.ts +137 -62
  84. package/src/source/image_source.ts +49 -12
  85. package/src/source/raster_dem_tile_source.test.ts +2 -2
  86. package/src/source/raster_tile_source.test.ts +64 -9
  87. package/src/source/raster_tile_source.ts +2 -1
  88. package/src/source/rtl_text_plugin_main_thread.test.ts +14 -14
  89. package/src/source/source.test.ts +8 -8
  90. package/src/source/vector_tile_source.test.ts +1 -1
  91. package/src/source/vector_tile_worker_source.test.ts +7 -5
  92. package/src/source/video_source.test.ts +1 -1
  93. package/src/source/worker.test.ts +1 -1
  94. package/src/source/worker_tile.test.ts +10 -8
  95. package/src/style/light.test.ts +9 -9
  96. package/src/style/light.ts +3 -3
  97. package/src/style/load_glyph_range.test.ts +8 -8
  98. package/src/style/load_sprite.test.ts +1 -1
  99. package/src/style/properties.test.ts +94 -2
  100. package/src/style/properties.ts +30 -1
  101. package/src/style/sky.test.ts +9 -9
  102. package/src/style/sky.ts +2 -2
  103. package/src/style/style.test.ts +38 -36
  104. package/src/style/style.ts +3 -3
  105. package/src/style/style_layer/color_relief_style_layer.test.ts +1 -1
  106. package/src/style/style_layer/fill_extrusion_style_layer.ts +6 -3
  107. package/src/style/style_layer/fill_extrusion_style_layer_properties.g.ts +14 -1
  108. package/src/style/style_layer/raster_style_layer.test.ts +2 -2
  109. package/src/style/style_layer.test.ts +5 -51
  110. package/src/style/validate_style.test.ts +1 -1
  111. package/src/symbol/collision_index.test.ts +1 -1
  112. package/src/symbol/grid_index.test.ts +1 -1
  113. package/src/tile/terrain_tile_manager.test.ts +2 -2
  114. package/src/tile/tile_id.test.ts +5 -5
  115. package/src/tile/tile_manager.test.ts +113 -72
  116. package/src/tile/tile_manager.ts +2 -2
  117. package/src/tile/tile_manager_in_view_tiles.test.ts +2 -2
  118. package/src/ui/camera.test.ts +138 -135
  119. package/src/ui/control/geolocate_control.test.ts +7 -30
  120. package/src/ui/handler/dblclick_zoom.test.ts +2 -2
  121. package/src/ui/handler/mouse.ts +15 -7
  122. package/src/ui/handler/mouse_handler_interface.test.ts +21 -1
  123. package/src/ui/handler/scroll_zoom.test.ts +2 -0
  124. package/src/ui/handler_manager.test.ts +7 -7
  125. package/src/ui/hash.test.ts +1 -0
  126. package/src/ui/map.ts +45 -20
  127. package/src/ui/map_tests/map_basic.test.ts +11 -23
  128. package/src/ui/map_tests/map_calculate_camera_options.test.ts +6 -6
  129. package/src/ui/map_tests/map_events.test.ts +5 -7
  130. package/src/ui/map_tests/map_global_state.test.ts +3 -3
  131. package/src/ui/map_tests/map_images.test.ts +4 -3
  132. package/src/ui/map_tests/map_is_moving.test.ts +1 -1
  133. package/src/ui/map_tests/map_is_rotating.test.ts +1 -1
  134. package/src/ui/map_tests/map_layer.test.ts +2 -1
  135. package/src/ui/map_tests/map_options.test.ts +1 -5
  136. package/src/ui/map_tests/map_pitch.test.ts +6 -6
  137. package/src/ui/map_tests/map_refresh_tiles.test.ts +2 -2
  138. package/src/ui/map_tests/map_render.test.ts +1 -1
  139. package/src/ui/map_tests/map_set_lod_params.test.ts +1 -1
  140. package/src/ui/map_tests/map_style.test.ts +9 -1
  141. package/src/ui/map_tests/map_terrain.test.ts +41 -1
  142. package/src/ui/map_tests/map_zoom.test.ts +15 -15
  143. package/src/ui/marker.test.ts +71 -14
  144. package/src/ui/marker.ts +30 -6
  145. package/src/ui/popup.test.ts +3 -3
  146. package/src/util/actor.test.ts +6 -6
  147. package/src/util/ajax.test.ts +27 -39
  148. package/src/util/browser.test.ts +7 -9
  149. package/src/util/create_tile_mesh.test.ts +2 -2
  150. package/src/util/dispatcher.test.ts +1 -1
  151. package/src/util/evented.test.ts +4 -1
  152. package/src/util/fast_maths.test.ts +4 -4
  153. package/src/util/image_request.test.ts +6 -4
  154. package/src/util/primitives/bounding_volume_cache.ts +3 -1
  155. package/src/util/struct_array.test.ts +2 -2
  156. package/src/util/task_queue.test.ts +1 -1
  157. package/src/util/test/util.ts +1 -0
  158. package/src/util/time_control.test.ts +2 -2
  159. package/src/util/transferable_grid_index.test.ts +1 -1
  160. package/src/util/util.test.ts +27 -13
  161. package/src/util/verticalize_punctuation.test.ts +4 -4
  162. package/src/util/web_worker_transfer.test.ts +5 -5
  163. package/src/webgl/draw/draw_custom.test.ts +13 -13
  164. package/src/webgl/draw/draw_debug.test.ts +1 -1
  165. package/src/webgl/draw/draw_fill.test.ts +13 -12
  166. package/src/webgl/draw/draw_symbol.test.ts +17 -16
  167. package/src/webgl/program/program_uniforms.ts +0 -3
  168. package/src/webgl/program/projection_program.ts +12 -10
  169. package/src/webgl/program/terrain_program.test.ts +2 -2
  170. package/src/webgl/program.ts +6 -4
  171. package/src/webgl/render_to_texture.test.ts +5 -5
  172. package/src/webgl/state.test.ts +1 -1
  173. package/src/webgl/texture.test.ts +3 -3
  174. package/src/webgl/vertex_buffer.test.ts +1 -1
  175. package/build/rolldown_plugins.ts +0 -18
  176. package/src/geo/projection/globe_projection_error_measurement.ts +0 -229
  177. package/src/shaders/glsl/projection_error_measurement.fragment.glsl +0 -5
  178. package/src/shaders/glsl/projection_error_measurement.fragment.glsl.g.ts +0 -2
  179. package/src/shaders/glsl/projection_error_measurement.vertex.glsl +0 -22
  180. package/src/shaders/glsl/projection_error_measurement.vertex.glsl.g.ts +0 -2
  181. package/src/webgl/program/projection_error_measurement_program.ts +0 -23
@@ -218,7 +218,7 @@ export class MercatorTransform implements ITransform {
218
218
  public get autoCalculateNearFarZ(): boolean {
219
219
  return this._helper.autoCalculateNearFarZ;
220
220
  }
221
- setTransitionState(_value: number, _error: number): void {
221
+ setTransitionState(_value: number): void {
222
222
  // Do nothing
223
223
  }
224
224
  //
@@ -748,6 +748,7 @@ export class MercatorTransform implements ITransform {
748
748
  clippingPlane: [0, 0, 0, 0],
749
749
  projectionTransition: 0.0, // Range 0..1, where 0 is mercator, 1 is another projection, mostly globe.
750
750
  fallbackMatrix: mainMatrix,
751
+ clipAntimeridian: false,
751
752
  };
752
753
  }
753
754
 
@@ -58,25 +58,25 @@ describe('mercator utils', () => {
58
58
  describe('tileCoordinatesToMercatorCoordinates', () => {
59
59
  const precisionDigits = 10;
60
60
 
61
- test('Test 0,0', () => {
61
+ test('0,0', () => {
62
62
  const result = tileCoordinatesToMercatorCoordinates(0, 0, new CanonicalTileID(0, 0, 0));
63
63
  expect(result.x).toBe(0);
64
64
  expect(result.y).toBe(0);
65
65
  });
66
66
 
67
- test('Test tile center', () => {
67
+ test('tile center', () => {
68
68
  const result = tileCoordinatesToMercatorCoordinates(EXTENT / 2, EXTENT / 2, new CanonicalTileID(0, 0, 0));
69
69
  expect(result.x).toBeCloseTo(0.5, precisionDigits);
70
70
  expect(result.y).toBeCloseTo(0.5, precisionDigits);
71
71
  });
72
72
 
73
- test('Test higher zoom 0,0', () => {
73
+ test('higher zoom 0,0', () => {
74
74
  const result = tileCoordinatesToMercatorCoordinates(0, 0, new CanonicalTileID(3, 0, 0));
75
75
  expect(result.x).toBe(0);
76
76
  expect(result.y).toBe(0);
77
77
  });
78
78
 
79
- test('Test higher zoom tile center', () => {
79
+ test('higher zoom tile center', () => {
80
80
  const result = tileCoordinatesToMercatorCoordinates(EXTENT / 2, EXTENT / 2, new CanonicalTileID(3, 0, 0));
81
81
  expect(result.x).toBeCloseTo(1 / 16, precisionDigits);
82
82
  expect(result.y).toBeCloseTo(1 / 16, precisionDigits);
@@ -86,25 +86,25 @@ describe('mercator utils', () => {
86
86
  describe('tileCoordinatesToLocation', () => {
87
87
  const precisionDigits = 5;
88
88
 
89
- test('Test 0,0', () => {
89
+ test('0,0', () => {
90
90
  const result = tileCoordinatesToLocation(0, 0, new CanonicalTileID(0, 0, 0));
91
91
  expect(result.lng).toBeCloseTo(-180, precisionDigits);
92
92
  expect(result.lat).toBeCloseTo(MAX_VALID_LATITUDE, precisionDigits);
93
93
  });
94
94
 
95
- test('Test tile center', () => {
95
+ test('tile center', () => {
96
96
  const result = tileCoordinatesToLocation(EXTENT / 2, EXTENT / 2, new CanonicalTileID(0, 0, 0));
97
97
  expect(result.lng).toBeCloseTo(0, precisionDigits);
98
98
  expect(result.lat).toBeCloseTo(0, precisionDigits);
99
99
  });
100
100
 
101
- test('Test higher zoom 0,0', () => {
101
+ test('higher zoom 0,0', () => {
102
102
  const result = tileCoordinatesToLocation(0, 0, new CanonicalTileID(3, 0, 0));
103
103
  expect(result.lng).toBeCloseTo(-180, precisionDigits);
104
104
  expect(result.lat).toBeCloseTo(MAX_VALID_LATITUDE, precisionDigits);
105
105
  });
106
106
 
107
- test('Test higher zoom mercator center', () => {
107
+ test('higher zoom mercator center', () => {
108
108
  const result = tileCoordinatesToLocation(EXTENT, EXTENT, new CanonicalTileID(3, 3, 3));
109
109
  expect(result.lng).toBeCloseTo(0, precisionDigits);
110
110
  expect(result.lat).toBeCloseTo(0, precisionDigits);
@@ -2,7 +2,6 @@ import type {CanonicalTileID} from '../../tile/tile_id.ts';
2
2
  import type {PreparedShader} from '../../shaders/shaders.ts';
3
3
  import type {Context} from '../../webgl/context.ts';
4
4
  import type {Mesh} from '../../render/mesh.ts';
5
- import type {Program} from '../../webgl/program.ts';
6
5
  import type {SubdivisionGranularitySetting} from '../../render/subdivision_granularity_settings.ts';
7
6
  import type {ProjectionSpecification} from '@maplibre/maplibre-gl-style-spec';
8
7
  import type {EvaluationParameters} from '../../style/evaluation_parameters.ts';
@@ -23,14 +22,6 @@ import type {EvaluationParameters} from '../../style/evaluation_parameters.ts';
23
22
  * - must be explicitly disposed of after usage using the `destroy` function - this allows the implementing class to free any allocated resources
24
23
  */
25
24
 
26
- /**
27
- * @internal
28
- */
29
- export type ProjectionGPUContext = {
30
- context: Context;
31
- useProgram: (name: string) => Program<any>;
32
- };
33
-
34
25
  /**
35
26
  * @internal
36
27
  * Specifies the usage for a square tile mesh:
@@ -99,24 +90,12 @@ export interface Projection {
99
90
  */
100
91
  get transitionState(): number;
101
92
 
102
- /**
103
- * @internal
104
- * Gets the error correction latitude in radians.
105
- */
106
- get latitudeErrorCorrectionRadians(): number;
107
-
108
93
  /**
109
94
  * @internal
110
95
  * Cleans up any resources the projection created, especially GPU buffers.
111
96
  */
112
97
  destroy(): void;
113
98
 
114
- /**
115
- * @internal
116
- * Runs any GPU-side tasks this projection required. Called at the beginning of every frame.
117
- */
118
- updateGPUdependent(renderContext: ProjectionGPUContext): void;
119
-
120
99
  /**
121
100
  * @internal
122
101
  * Returns a subdivided mesh for a given tile ID, covering 0..EXTENT range.
@@ -140,10 +119,4 @@ export interface Projection {
140
119
  * Returns true if the projection is currently transitioning between two states.
141
120
  */
142
121
  hasTransition(): boolean;
143
-
144
- /**
145
- * @internal
146
- * Sets the error query latidude in degrees
147
- */
148
- setErrorQueryLatitudeDegrees(value: number): void;
149
122
  }
@@ -60,6 +60,14 @@ export type ProjectionData<MainMatrix extends mat4 = mat4, FallbackMatrix extend
60
60
  * Uniform name: `u_projection_fallback_matrix`.
61
61
  */
62
62
  fallbackMatrix: FallbackMatrix;
63
+ /**
64
+ * Whether line fragments outside the tile's X extent should be discarded: true for the zoom 0 tile under globe projection, false otherwise.
65
+ * The z0 tile covers the whole world, so its buffer wraps around the planet onto the tile itself,
66
+ * drawing geometry near the antimeridian twice. Stencil clipping cannot remove this same-pixel overlap,
67
+ * so lines are clipped in the fragment shader instead (fills are clipped during subdivision).
68
+ * Uniform name: `u_projection_clip_antimeridian`.
69
+ */
70
+ clipAntimeridian: boolean;
63
71
  };
64
72
 
65
73
  /**
@@ -14,14 +14,14 @@ import type {Projection} from './projection.ts';
14
14
  import type {ITransform, TransformConstrainFunction} from '../transform_interface.ts';
15
15
  import type {ICameraHelper} from './camera_helper.ts';
16
16
 
17
- export function createProjectionFromName(name: ProjectionSpecification['type'], transformConstrain?: TransformConstrainFunction): {
17
+ export function createProjectionFromName(name: ProjectionSpecification['type'], transformConstrain: TransformConstrainFunction | undefined, globalState: Record<string, any>): {
18
18
  projection: Projection;
19
19
  transform: ITransform;
20
20
  cameraHelper: ICameraHelper;
21
21
  } {
22
22
  const transformOptions = {constrainOverride: transformConstrain};
23
23
  if (Array.isArray(name)) {
24
- const globeProjection = new GlobeProjection({type: name});
24
+ const globeProjection = new GlobeProjection({type: name}, globalState);
25
25
  return {
26
26
  projection: globeProjection,
27
27
  transform: new GlobeTransform(transformOptions),
@@ -47,7 +47,7 @@ export function createProjectionFromName(name: ProjectionSpecification['type'],
47
47
  'vertical-perspective',
48
48
  12,
49
49
  'mercator'
50
- ]});
50
+ ]}, {});
51
51
  return {
52
52
  projection: globeProjection,
53
53
  transform: new GlobeTransform(transformOptions),
@@ -1,23 +1,15 @@
1
1
  import type {Context} from '../../webgl/context.ts';
2
2
  import type {CanonicalTileID} from '../../tile/tile_id.ts';
3
3
  import {type Mesh} from '../../render/mesh.ts';
4
- import {now} from '../../util/time_control.ts';
5
- import {easeCubicInOut, lerp} from '../../util/util.ts';
6
- import {mercatorYfromLat} from '../mercator_coordinate.ts';
7
4
  import {SubdivisionGranularityExpression, SubdivisionGranularitySetting} from '../../render/subdivision_granularity_settings.ts';
8
- import type {Projection, ProjectionGPUContext, TileMeshUsage} from './projection.ts';
5
+ import type {Projection, TileMeshUsage} from './projection.ts';
9
6
  import {type PreparedShader, shaders} from '../../shaders/shaders.ts';
10
- import {ProjectionErrorMeasurement} from './globe_projection_error_measurement.ts';
11
7
  import {createTileMeshWithBuffers, type CreateTileMeshOptions} from '../../util/create_tile_mesh.ts';
12
8
  import {type EvaluationParameters} from '../../style/evaluation_parameters.ts';
13
9
 
14
10
  export const VerticalPerspectiveShaderDefine = '#define GLOBE';
15
11
  export const VerticalPerspectiveShaderVariantKey = 'globe';
16
12
 
17
- export const globeConstants = {
18
- errorTransitionTimeSeconds: 0.5
19
- };
20
-
21
13
  const granularitySettingsGlobe: SubdivisionGranularitySetting = new SubdivisionGranularitySetting({
22
14
  fill: new SubdivisionGranularityExpression(128, 2),
23
15
  line: new SubdivisionGranularityExpression(512, 0),
@@ -36,14 +28,6 @@ const granularitySettingsGlobe: SubdivisionGranularitySetting = new SubdivisionG
36
28
  export class VerticalPerspectiveProjection implements Projection {
37
29
  private _tileMeshCache: {[_: string]: Mesh} = {};
38
30
 
39
- // GPU atan() error correction
40
- private _errorMeasurement: ProjectionErrorMeasurement;
41
- private _errorQueryLatitudeDegrees: number;
42
- private _errorCorrectionUsable: number = 0.0;
43
- private _errorMeasurementLastValue: number = 0.0;
44
- private _errorCorrectionPreviousValue: number = 0.0;
45
- private _errorMeasurementLastChangeTime: number = -1000.0;
46
-
47
31
  get name(): 'vertical-perspective' {
48
32
  return 'vertical-perspective';
49
33
  }
@@ -80,39 +64,8 @@ export class VerticalPerspectiveProjection implements Projection {
80
64
  return true;
81
65
  }
82
66
 
83
- /**
84
- * @internal
85
- * Globe projection periodically measures the error of the GPU's
86
- * projection from mercator to globe and computes how much to correct
87
- * the globe's latitude alignment.
88
- * This stores the correction that should be applied to the projection matrix.
89
- */
90
- get latitudeErrorCorrectionRadians(): number { return this._errorCorrectionUsable; }
91
-
92
67
  public destroy(): void {
93
- if (this._errorMeasurement) {
94
- this._errorMeasurement.destroy();
95
- }
96
- }
97
-
98
- public updateGPUdependent(renderContext: ProjectionGPUContext): void {
99
- this._errorMeasurement ||= new ProjectionErrorMeasurement(renderContext);
100
- const mercatorY = mercatorYfromLat(this._errorQueryLatitudeDegrees);
101
- const expectedResult = 2.0 * Math.atan(Math.exp(Math.PI - (mercatorY * Math.PI * 2.0))) - Math.PI * 0.5;
102
- const newValue = this._errorMeasurement.updateErrorLoop(mercatorY, expectedResult);
103
-
104
- const currentTime = now();
105
-
106
- if (newValue !== this._errorMeasurementLastValue) {
107
- this._errorCorrectionPreviousValue = this._errorCorrectionUsable; // store the interpolated value
108
- this._errorMeasurementLastValue = newValue;
109
- this._errorMeasurementLastChangeTime = currentTime;
110
- }
111
-
112
- const sinceUpdateSeconds = (currentTime - this._errorMeasurementLastChangeTime) / 1000.0;
113
- const mix = Math.min(Math.max(sinceUpdateSeconds / globeConstants.errorTransitionTimeSeconds, 0.0), 1.0);
114
- const newCorrection = -this._errorMeasurementLastValue; // Note the negation
115
- this._errorCorrectionUsable = lerp(this._errorCorrectionPreviousValue, newCorrection, easeCubicInOut(mix));
68
+ // Do nothing.
116
69
  }
117
70
 
118
71
  private _getMeshKey(options: CreateTileMeshOptions): string {
@@ -150,16 +103,6 @@ export class VerticalPerspectiveProjection implements Projection {
150
103
  }
151
104
 
152
105
  hasTransition(): boolean {
153
- const currentTime = now();
154
- let dirty = false;
155
- // Error correction transition
156
- dirty ||= (currentTime - this._errorMeasurementLastChangeTime) / 1000.0 < (globeConstants.errorTransitionTimeSeconds + 0.2);
157
- // Error correction query in flight
158
- dirty ||= (this._errorMeasurement?.awaitingQuery);
159
- return dirty;
160
- }
161
-
162
- setErrorQueryLatitudeDegrees(value: number): void {
163
- this._errorQueryLatitudeDegrees = value;
106
+ return false;
164
107
  }
165
108
  }
@@ -245,12 +245,11 @@ export class VerticalPerspectiveTransform implements ITransform {
245
245
  private _cachedFrustum: Frustum;
246
246
  private _projectionMatrix: mat4 = createIdentityMat4f64();
247
247
  private _globeViewProjMatrix32f: Mat4f32 = createIdentityMat4f32(); // Must be 32 bit floats, otherwise WebGL calls in Chrome get very slow.
248
- private _globeViewProjMatrixNoCorrection: mat4 = createIdentityMat4f64();
249
- private _globeViewProjMatrixNoCorrectionInverted: mat4 = createIdentityMat4f64();
248
+ private _globeViewProjMatrixF64: mat4 = createIdentityMat4f64();
249
+ private _globeViewProjMatrixF64Inverted: mat4 = createIdentityMat4f64();
250
250
  private _globeProjMatrixInverted: mat4 = createIdentityMat4f64();
251
251
 
252
252
  private _cameraPosition: vec3 = createVec3f64();
253
- private _globeLatitudeErrorCorrectionRadians: number = 0;
254
253
  /**
255
254
  * Globe projection can smoothly interpolate between globe view and mercator. This variable controls this interpolation.
256
255
  * Value 0 is mercator, value 1 is globe, anything between is an interpolation between the two projections.
@@ -272,14 +271,13 @@ export class VerticalPerspectiveTransform implements ITransform {
272
271
  return clone;
273
272
  }
274
273
 
275
- public apply(that: IReadonlyTransform, constrain: boolean, globeLatitudeErrorCorrectionRadians?: number): void {
276
- this._globeLatitudeErrorCorrectionRadians = globeLatitudeErrorCorrectionRadians || 0;
274
+ public apply(that: IReadonlyTransform, constrain: boolean): void {
277
275
  this._helper.apply(that, constrain);
278
276
  }
279
277
 
280
278
  public get projectionMatrix(): mat4 { return this._projectionMatrix; }
281
279
 
282
- public get modelViewProjectionMatrix(): mat4 { return this._globeViewProjMatrixNoCorrection; }
280
+ public get modelViewProjectionMatrix(): mat4 { return this._globeViewProjMatrixF64; }
283
281
 
284
282
  public get inverseProjectionMatrix(): mat4 { return this._globeProjMatrixInverted; }
285
283
 
@@ -306,6 +304,7 @@ export class VerticalPerspectiveTransform implements ITransform {
306
304
  clippingPlane: this._cachedClippingPlane as [number, number, number, number],
307
305
  projectionTransition: applyGlobeMatrix ? 1 : 0,
308
306
  fallbackMatrix: this._globeViewProjMatrix32f,
307
+ clipAntimeridian: overscaledTileID?.canonical.z === 0,
309
308
  };
310
309
  }
311
310
 
@@ -427,7 +426,7 @@ export class VerticalPerspectiveTransform implements ITransform {
427
426
  const elevation = getElevation ? getElevation(x, y) : 0.0;
428
427
  const vectorMultiplier = 1.0 + elevation / earthRadius;
429
428
  const pos: vec4 = [spherePos[0] * vectorMultiplier, spherePos[1] * vectorMultiplier, spherePos[2] * vectorMultiplier, 1];
430
- vec4.transformMat4(pos, pos, this._globeViewProjMatrixNoCorrection);
429
+ vec4.transformMat4(pos, pos, this._globeViewProjMatrixF64);
431
430
 
432
431
  // Also check whether the point projects to the backfacing side of the sphere.
433
432
  const plane = this._cachedClippingPlane;
@@ -451,7 +450,6 @@ export class VerticalPerspectiveTransform implements ITransform {
451
450
 
452
451
  // Construct a completely separate matrix for globe view
453
452
  const globeMatrix = createMat4f64();
454
- const globeMatrixUncorrected = createMat4f64();
455
453
  if (this._helper.autoCalculateNearFarZ) {
456
454
  this._helper._nearZ = 0.5;
457
455
  this._helper._farZ = this.cameraToCenterDistance + globeRadiusPixels * 2.0; // just set the far plane far enough - we will calculate our own z in the vertex shader anyway
@@ -478,19 +476,14 @@ export class VerticalPerspectiveTransform implements ITransform {
478
476
  scaleVec[1] = globeRadiusPixels;
479
477
  scaleVec[2] = globeRadiusPixels;
480
478
 
481
- // Keep a atan-correction-free matrix for transformations done on the CPU with accurate math
482
- mat4.rotateX(globeMatrixUncorrected, globeMatrix, this.center.lat * Math.PI / 180.0);
483
- mat4.rotateY(globeMatrixUncorrected, globeMatrixUncorrected, -this.center.lng * Math.PI / 180.0);
484
- mat4.scale(globeMatrixUncorrected, globeMatrixUncorrected, scaleVec); // Scale the unit sphere to a sphere with diameter of 1
485
- this._globeViewProjMatrixNoCorrection = globeMatrixUncorrected;
486
-
487
- mat4.rotateX(globeMatrix, globeMatrix, this.center.lat * Math.PI / 180.0 - this._globeLatitudeErrorCorrectionRadians);
479
+ mat4.rotateX(globeMatrix, globeMatrix, this.center.lat * Math.PI / 180.0);
488
480
  mat4.rotateY(globeMatrix, globeMatrix, -this.center.lng * Math.PI / 180.0);
489
481
  mat4.scale(globeMatrix, globeMatrix, scaleVec); // Scale the unit sphere to a sphere with diameter of 1
482
+ this._globeViewProjMatrixF64 = globeMatrix;
490
483
  this._globeViewProjMatrix32f = new Float32Array(globeMatrix);
491
484
 
492
- this._globeViewProjMatrixNoCorrectionInverted = createMat4f64();
493
- mat4.invert(this._globeViewProjMatrixNoCorrectionInverted, globeMatrixUncorrected);
485
+ this._globeViewProjMatrixF64Inverted = createMat4f64();
486
+ mat4.invert(this._globeViewProjMatrixF64Inverted, globeMatrix);
494
487
 
495
488
  const zero = createVec3f64();
496
489
  this._cameraPosition = createVec3f64();
@@ -504,7 +497,7 @@ export class VerticalPerspectiveTransform implements ITransform {
504
497
 
505
498
  this._cachedClippingPlane = this._computeClippingPlane(globeRadiusPixels);
506
499
 
507
- const matrix = mat4.clone(this._globeViewProjMatrixNoCorrectionInverted);
500
+ const matrix = mat4.clone(this._globeViewProjMatrixF64Inverted);
508
501
  mat4.scale(matrix, matrix, [1, 1, -1]);
509
502
  this._cachedFrustum = Frustum.fromInvProjectionMatrix(matrix, 1, 0, this._cachedClippingPlane, true);
510
503
  }
@@ -557,13 +550,13 @@ export class VerticalPerspectiveTransform implements ITransform {
557
550
  }
558
551
 
559
552
  lngLatToCameraDepth(lngLat: LngLat, elevation: number): number {
560
- if (!this._globeViewProjMatrixNoCorrection) {
553
+ if (!this._globeViewProjMatrixF64) {
561
554
  return 1.0; // _calcMatrices hasn't run yet
562
555
  }
563
556
  const vec = angularCoordinatesToSurfaceVector(lngLat);
564
557
  vec3.scale(vec, vec, (1.0 + elevation / earthRadius));
565
558
  const result = createVec4f64();
566
- vec4.transformMat4(result, [vec[0], vec[1], vec[2], 1], this._globeViewProjMatrixNoCorrection);
559
+ vec4.transformMat4(result, [vec[0], vec[1], vec[2], 1], this._globeViewProjMatrixF64);
567
560
  return result[2] / result[3];
568
561
  }
569
562
 
@@ -783,7 +776,7 @@ export class VerticalPerspectiveTransform implements ITransform {
783
776
  */
784
777
  private _projectSurfacePointToScreen(pos: vec3): Point {
785
778
  const projected = createVec4f64();
786
- vec4.transformMat4(projected, [...pos, 1] as vec4, this._globeViewProjMatrixNoCorrection);
779
+ vec4.transformMat4(projected, [...pos, 1] as vec4, this._globeViewProjMatrixF64);
787
780
  projected[0] /= projected[3];
788
781
  projected[1] /= projected[3];
789
782
  return new Point(
@@ -826,7 +819,7 @@ export class VerticalPerspectiveTransform implements ITransform {
826
819
  pos[1] = ((p.y / this.height) * 2.0 - 1.0) * -1.0;
827
820
  pos[2] = 1;
828
821
  pos[3] = 1;
829
- vec4.transformMat4(pos, pos, this._globeViewProjMatrixNoCorrectionInverted);
822
+ vec4.transformMat4(pos, pos, this._globeViewProjMatrixF64Inverted);
830
823
  pos[0] /= pos[3];
831
824
  pos[1] /= pos[3];
832
825
  pos[2] /= pos[3];
@@ -860,7 +853,7 @@ export class VerticalPerspectiveTransform implements ITransform {
860
853
  }
861
854
 
862
855
  const projected = createVec4f64();
863
- vec4.transformMat4(projected, [...vec, 1] as vec4, this._globeViewProjMatrixNoCorrection);
856
+ vec4.transformMat4(projected, [...vec, 1] as vec4, this._globeViewProjMatrixF64);
864
857
  projected[0] /= projected[3];
865
858
  projected[1] /= projected[3];
866
859
  projected[2] /= projected[3];
@@ -232,9 +232,8 @@ interface ITransformMutators {
232
232
  * @internal
233
233
  * Sets the transform's transition state from one projection to another.
234
234
  * @param value - The transition state value.
235
- * @param error - The error value.
236
235
  */
237
- setTransitionState(value: number, error: number): void;
236
+ setTransitionState(value: number): void;
238
237
  }
239
238
 
240
239
  /**
package/src/index.test.ts CHANGED
@@ -3,7 +3,6 @@ import {config} from './util/config.ts';
3
3
  import {addProtocol, getWorkerCount, removeProtocol, getVersion} from './index.ts';
4
4
  import {getJSON, getArrayBuffer} from './util/ajax.ts';
5
5
  import {ImageRequest} from './util/image_request.ts';
6
- import {isAbortError} from './util/abort_error.ts';
7
6
 
8
7
  describe('maplibre', () => {
9
8
  beforeEach(() => {
@@ -37,7 +36,7 @@ describe('maplibre', () => {
37
36
  });
38
37
 
39
38
  test('addProtocol - getJSON', async () => {
40
- const mockProtocol = vi.fn().mockReturnValue(Promise.resolve({data: {'foo': 'bar'}}));
39
+ const mockProtocol = vi.fn().mockResolvedValue({data: {'foo': 'bar'}});
41
40
  addProtocol('custom', mockProtocol);
42
41
 
43
42
  const response = await getJSON({url: 'custom://test/url/json'}, new AbortController());
@@ -46,7 +45,7 @@ describe('maplibre', () => {
46
45
  });
47
46
 
48
47
  test('addProtocol - getArrayBuffer', async () => {
49
- const mockProtocol = vi.fn().mockReturnValue(Promise.resolve({data: new ArrayBuffer(1), cacheControl: 'cache-control', expires: 'expires'}));
48
+ const mockProtocol = vi.fn().mockResolvedValue({data: new ArrayBuffer(1), cacheControl: 'cache-control', expires: 'expires'});
50
49
  addProtocol('custom', mockProtocol);
51
50
 
52
51
  const response = await getArrayBuffer({url: 'custom://test/url/getArrayBuffer'}, new AbortController());
@@ -57,7 +56,7 @@ describe('maplibre', () => {
57
56
  });
58
57
 
59
58
  test('addProtocol - null response for getArrayBuffer results in empty array buffer', async () => {
60
- const mockProtocol = vi.fn().mockReturnValue(Promise.resolve({data: null, cacheControl: 'cache-control', expires: 'expires'}));
59
+ const mockProtocol = vi.fn().mockResolvedValue({data: null, cacheControl: 'cache-control', expires: 'expires'});
61
60
  addProtocol('custom', mockProtocol);
62
61
 
63
62
  const response = await getArrayBuffer({url: 'custom://test/url/getArrayBuffer'}, new AbortController());
@@ -69,7 +68,7 @@ describe('maplibre', () => {
69
68
  });
70
69
 
71
70
  test('addProtocol - returning ImageBitmap for getImage', async () => {
72
- const mockProtocol = vi.fn().mockReturnValue(Promise.resolve({data: new ImageBitmap()}));
71
+ const mockProtocol = vi.fn().mockResolvedValue({data: new ImageBitmap()});
73
72
  addProtocol('custom', mockProtocol);
74
73
 
75
74
  const img = await ImageRequest.getImage({url: 'custom://test/url/getImage'}, new AbortController());
@@ -78,7 +77,7 @@ describe('maplibre', () => {
78
77
  });
79
78
 
80
79
  test('addProtocol - returning HTMLImageElement for getImage', async () => {
81
- const mockProtocol = vi.fn().mockReturnValue(Promise.resolve({data: new Image()}));
80
+ const mockProtocol = vi.fn().mockResolvedValue({data: new Image()});
82
81
  addProtocol('custom', mockProtocol);
83
82
 
84
83
  const img = await ImageRequest.getImage({url: 'custom://test/url/getImage'}, new AbortController());
@@ -88,7 +87,7 @@ describe('maplibre', () => {
88
87
 
89
88
  test('addProtocol - error', async () => {
90
89
  const mockError = new Error('test error');
91
- const mockProtocol = vi.fn().mockReturnValue(Promise.reject(mockError));
90
+ const mockProtocol = vi.fn().mockRejectedValue(mockError);
92
91
  addProtocol('custom', mockProtocol);
93
92
 
94
93
  const successCallback = vi.fn();
@@ -110,11 +109,7 @@ describe('maplibre', () => {
110
109
  const abortController = new AbortController();
111
110
  const promise = getJSON({url: 'custom://test/url/json'}, abortController);
112
111
  abortController.abort();
113
- try {
114
- await promise;
115
- } catch (err) {
116
- expect(isAbortError(err)).toBeTruthy();
117
- }
112
+ await promise;
118
113
 
119
114
  expect(cancelCalled).toBeTruthy();
120
115
  });
package/src/index.ts CHANGED
@@ -22,9 +22,9 @@ import {now, setNow, restoreNow, isTimeFrozen} from './util/time_control.ts';
22
22
  import {WorkerPool} from './util/worker_pool.ts';
23
23
  import {prewarm, clearPrewarmedResources} from './util/global_worker_pool.ts';
24
24
  import {AJAXError, type ExpiryData, type GetResourceResponse, type RequestParameters} from './util/ajax.ts';
25
- import {GeoJSONSource, type SetClusterOptions} from './source/geojson_source.ts';
25
+ import {GeoJSONSource, type GetClusterOptions, type SetClusterOptions} from './source/geojson_source.ts';
26
26
  import {CanvasSource, type CanvasSourceSpecification} from './source/canvas_source.ts';
27
- import {type CanonicalTileRange, type Coordinates, ImageSource, type UpdateImageOptions} from './source/image_source.ts';
27
+ import {type CanonicalTileRange, type Coordinates, type ImageSourceImage, ImageSource, type UpdateImageOptions} from './source/image_source.ts';
28
28
  import {RasterDEMTileSource} from './source/raster_dem_tile_source.ts';
29
29
  import {RasterTileSource} from './source/raster_tile_source.ts';
30
30
  import {VectorTileSource, type LoadTileResult} from './source/vector_tile_source.ts';
@@ -298,9 +298,11 @@ export {
298
298
  type Tile,
299
299
  type Listener,
300
300
  type Coordinates,
301
+ type ImageSourceImage,
301
302
  type UpdateImageOptions,
302
303
  type DragPanOptions,
303
304
  type FullscreenControlOptions,
305
+ type GetClusterOptions,
304
306
  type SetClusterOptions,
305
307
  type GeoJSONSourceDiff,
306
308
  type GeolocateControlOptions,
@@ -208,9 +208,7 @@ describe('GlyphManager', () => {
208
208
  test('GlyphManager caches locally generated glyphs', async () => {
209
209
 
210
210
  const manager = createGlyphManager(true, 'sans-serif');
211
- const drawSpy = GlyphManager.TinySDF.prototype.draw = vi.fn().mockImplementation(() => {
212
- return {data: new Uint8ClampedArray(60 * 60)} as any;
213
- });
211
+ const drawSpy = vi.spyOn(GlyphManager.TinySDF.prototype, 'draw').mockReturnValue({data: new Uint8ClampedArray(60 * 60)} as any);
214
212
 
215
213
  // Katakana letter te
216
214
  const returnedGlyphs = await manager.getGlyphs({'Arial Unicode MS': [0x30c6]});
@@ -220,22 +218,14 @@ describe('GlyphManager', () => {
220
218
  });
221
219
 
222
220
  test('GlyphManager passes no language to TinySDF by default', async () => {
223
- const langSpy = GlyphManager.TinySDF = vi.fn().mockImplementation(function () {
224
- return {
225
- draw: () => GLYPHS[0]
226
- };
227
- });
221
+ const langSpy = vi.spyOn(GlyphManager, 'TinySDF').mockImplementation(class { draw = () => GLYPHS[0]; });
228
222
  const manager = createGlyphManager(true, 'sans-serif');
229
223
  await manager.getGlyphs({'Arial Unicode MS': [0x30c6]});
230
224
  expect(langSpy).toHaveBeenCalledWith(expect.not.objectContaining({lang: expect.anything()}));
231
225
  });
232
226
 
233
227
  test('GlyphManager sets the language on TinySDF', async () => {
234
- const langSpy = GlyphManager.TinySDF = vi.fn().mockImplementation(function () {
235
- return {
236
- draw: () => GLYPHS[0]
237
- };
238
- });
228
+ const langSpy = vi.spyOn(GlyphManager, 'TinySDF').mockImplementation(class { draw = () => GLYPHS[0]; });
239
229
  const manager = createGlyphManager(true, 'sans-serif', 'zh');
240
230
  await manager.getGlyphs({'Arial Unicode MS': [0x30c6]});
241
231
  expect(langSpy).toHaveBeenCalledWith(expect.objectContaining({lang: 'zh'}));
@@ -244,9 +234,7 @@ describe('GlyphManager', () => {
244
234
  test('awaits document.fonts.load before instantiating TinySDF', async () => {
245
235
  const loadSpy = vi.fn(() => Promise.resolve([]));
246
236
  Object.defineProperty(document, 'fonts', {configurable: true, value: {load: loadSpy}});
247
- const tinySdfSpy = GlyphManager.TinySDF = vi.fn().mockImplementation(function () {
248
- return {draw: () => GLYPHS[0]};
249
- });
237
+ const tinySdfSpy = vi.spyOn(GlyphManager, 'TinySDF').mockImplementation(class { draw = () => GLYPHS[0]; });
250
238
 
251
239
  const manager = createGlyphManager(false, 'sans-serif');
252
240
  await manager.getGlyphs({'Arial Unicode MS': [0x41]});
@@ -257,11 +245,10 @@ describe('GlyphManager', () => {
257
245
  });
258
246
 
259
247
  test('still instantiates TinySDF when document.fonts.load rejects', async () => {
248
+ vi.spyOn(console, 'warn').mockImplementation(() => {});
260
249
  const loadSpy = vi.fn(() => Promise.reject(new Error('font not found')));
261
250
  Object.defineProperty(document, 'fonts', {configurable: true, value: {load: loadSpy}});
262
- const tinySdfSpy = GlyphManager.TinySDF = vi.fn().mockImplementation(function () {
263
- return {draw: () => GLYPHS[0]};
264
- });
251
+ const tinySdfSpy = vi.spyOn(GlyphManager, 'TinySDF').mockImplementation(class { draw = () => GLYPHS[0]; });
265
252
 
266
253
  const manager = createGlyphManager(false, 'sans-serif');
267
254
  const result = await manager.getGlyphs({'Arial Unicode MS': [0x41]});
@@ -274,9 +261,7 @@ describe('GlyphManager', () => {
274
261
  test('memoizes document.fonts.load per fontstack', async () => {
275
262
  const loadSpy = vi.fn(() => Promise.resolve([]));
276
263
  Object.defineProperty(document, 'fonts', {configurable: true, value: {load: loadSpy}});
277
- GlyphManager.TinySDF = vi.fn().mockImplementation(function () {
278
- return {draw: () => GLYPHS[0]};
279
- });
264
+ vi.spyOn(GlyphManager, 'TinySDF').mockImplementation(class { draw = () => GLYPHS[0]; });
280
265
 
281
266
  const manager = createGlyphManager(false, 'sans-serif');
282
267
  await manager.getGlyphs({'Arial Unicode MS': [0x41]});
@@ -46,6 +46,8 @@ describe('render', () => {
46
46
 
47
47
  test('must not fail with incompletely loaded style', () => {
48
48
  painter.render(style, renderOptions);
49
+
50
+ expect(painter.renderPass).toBe('translucent');
49
51
  });
50
52
 
51
53
  test('calls terrainDepth but not terrainCoords', () => {
@@ -284,6 +284,7 @@ export class Painter {
284
284
  clippingPlane: [0, 0, 0, 0],
285
285
  projectionTransition: 0.0,
286
286
  fallbackMatrix: matrix,
287
+ clipAntimeridian: false,
287
288
  };
288
289
 
289
290
  // Note: we force a simple mercator projection for the shader, since we want to draw a fullscreen quad.
@@ -317,12 +318,14 @@ export class Painter {
317
318
  stencilRefs[tileID.key] = this.nextStencilID++;
318
319
  }
319
320
 
320
- // A two-pass approach is needed. See comment in draw_raster.ts for more details.
321
- // However, we use a simpler approach because we don't care about overdraw here.
321
+ // A two-pass approach is needed for subdivided projections. See comment in draw_raster.ts
322
+ // for more details. In non-subdivided projections the border flag does not change the mesh,
323
+ // so one pass produces the same stencil mask.
324
+ if (this.style.projection.useSubdivision) {
325
+ this._renderTileMasks(stencilRefs, tileIDs, renderToTexture, true);
326
+ }
322
327
 
323
- // First pass - draw tiles with borders and with GL_ALWAYS
324
- this._renderTileMasks(stencilRefs, tileIDs, renderToTexture, true);
325
- // Second pass - draw borderless tiles with GL_ALWAYS
328
+ // Final pass - draw borderless tiles with GL_ALWAYS
326
329
  this._renderTileMasks(stencilRefs, tileIDs, renderToTexture, false);
327
330
 
328
331
  this._tileClippingMaskIDs = stencilRefs;
@@ -573,12 +576,6 @@ export class Painter {
573
576
  this.renderLayer(this, tileManagers[layer.source], layer, coords, renderOptions);
574
577
  }
575
578
 
576
- // Execute offscreen GPU tasks of the projection manager
577
- this.style.projection?.updateGPUdependent({
578
- context: this.context,
579
- useProgram: (name: string) => this.useProgram(name)
580
- });
581
-
582
579
  // Rebind the main framebuffer now that all offscreen layers have been rendered:
583
580
  this.context.viewport.set([0, 0, this.width, this.height]);
584
581
  this.context.bindFramebuffer.set(null);