maplibre-gl-layers 0.4.0 → 0.6.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.
package/dist/index.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  /*!
2
2
  * name: maplibre-gl-layers
3
- * version: 0.4.0
3
+ * version: 0.6.0
4
4
  * description: MapLibre's layer extension library enabling the display, movement, and modification of large numbers of dynamic sprite images
5
5
  * author: Kouji Matsui (@kekyo@mi.kekyo.net)
6
6
  * license: MIT
7
7
  * repository.url: https://github.com/kekyo/maplibre-gl-layers.git
8
- * git.commit.hash: 366a9e1190bfe770b4002a06284ff627188b5c76
8
+ * git.commit.hash: 481f544de02fd3e71a2ba6c28bbb7eeb98b49eff
9
9
  */
10
10
 
11
11
  export * from './types.ts';
package/dist/index.mjs CHANGED
@@ -1,11 +1,11 @@
1
1
  /*!
2
2
  * name: maplibre-gl-layers
3
- * version: 0.4.0
3
+ * version: 0.6.0
4
4
  * description: MapLibre's layer extension library enabling the display, movement, and modification of large numbers of dynamic sprite images
5
5
  * author: Kouji Matsui (@kekyo@mi.kekyo.net)
6
6
  * license: MIT
7
7
  * repository.url: https://github.com/kekyo/maplibre-gl-layers.git
8
- * git.commit.hash: 366a9e1190bfe770b4002a06284ff627188b5c76
8
+ * git.commit.hash: 481f544de02fd3e71a2ba6c28bbb7eeb98b49eff
9
9
  */
10
10
  const UNLIMITED_SPRITE_SCALING_OPTIONS = {
11
11
  metersPerPixel: 1,
@@ -25,6 +25,18 @@ const STANDARD_SPRITE_SCALING_OPTIONS = {
25
25
  spriteMinPixel: 24,
26
26
  spriteMaxPixel: 100
27
27
  };
28
+ const DEFAULT_TEXTURE_FILTERING_OPTIONS = {
29
+ minFilter: "linear",
30
+ magFilter: "linear",
31
+ generateMipmaps: false,
32
+ maxAnisotropy: 1
33
+ };
34
+ const BETTER_TEXTURE_FILTERING_OPTIONS = {
35
+ minFilter: "linear-mipmap-linear",
36
+ magFilter: "linear",
37
+ generateMipmaps: true,
38
+ maxAnisotropy: 8
39
+ };
28
40
  var maplibreGl$1 = { exports: {} };
29
41
  /**
30
42
  * MapLibre GL JS
@@ -21517,25 +21529,30 @@ const calculateDistanceAndBearingMeters = (from, to) => {
21517
21529
  const clampSpritePixelSize = (width, height, spriteMinPixel, spriteMaxPixel) => {
21518
21530
  const largest = Math.max(width, height);
21519
21531
  if (!Number.isFinite(largest) || largest <= 0) {
21520
- return { width, height };
21532
+ return { width, height, scaleAdjustment: 1 };
21521
21533
  }
21522
21534
  let nextWidth = width;
21523
21535
  let nextHeight = height;
21536
+ let scaleAdjustment = 1;
21537
+ let adjustedLargest = largest;
21524
21538
  if (spriteMinPixel > 0 && largest < spriteMinPixel) {
21525
21539
  const factor = spriteMinPixel / largest;
21526
21540
  nextWidth *= factor;
21527
21541
  nextHeight *= factor;
21542
+ scaleAdjustment *= factor;
21543
+ adjustedLargest *= factor;
21528
21544
  }
21529
- if (spriteMaxPixel > 0 && largest > spriteMaxPixel) {
21530
- const factor = spriteMaxPixel / largest;
21545
+ if (spriteMaxPixel > 0 && adjustedLargest > spriteMaxPixel) {
21546
+ const factor = spriteMaxPixel / adjustedLargest;
21531
21547
  nextWidth *= factor;
21532
21548
  nextHeight *= factor;
21549
+ scaleAdjustment *= factor;
21533
21550
  }
21534
- return { width: nextWidth, height: nextHeight };
21551
+ return { width: nextWidth, height: nextHeight, scaleAdjustment };
21535
21552
  };
21536
21553
  const calculateBillboardPixelDimensions = (imageWidth, imageHeight, baseMetersPerPixel, imageScale, zoomScaleFactor, effectivePixelsPerMeter, spriteMinPixel, spriteMaxPixel) => {
21537
21554
  if (!imageWidth || !imageHeight || imageWidth <= 0 || imageHeight <= 0 || baseMetersPerPixel <= 0 || effectivePixelsPerMeter <= 0) {
21538
- return { width: 0, height: 0 };
21555
+ return { width: 0, height: 0, scaleAdjustment: 1 };
21539
21556
  }
21540
21557
  const scaleFactor = baseMetersPerPixel * imageScale * zoomScaleFactor * effectivePixelsPerMeter;
21541
21558
  const rawWidth = ensureFinite(imageWidth * scaleFactor);
@@ -21547,10 +21564,10 @@ const calculateBillboardPixelDimensions = (imageWidth, imageHeight, baseMetersPe
21547
21564
  spriteMaxPixel
21548
21565
  );
21549
21566
  };
21550
- const calculateBillboardOffsetPixels = (offset, imageScale, zoomScaleFactor, effectivePixelsPerMeter) => {
21567
+ const calculateBillboardOffsetPixels = (offset, imageScale, zoomScaleFactor, effectivePixelsPerMeter, sizeScaleAdjustment = 1) => {
21551
21568
  var _a, _b;
21552
21569
  const offsetMeters = ((_a = offset == null ? void 0 : offset.offsetMeters) != null ? _a : 0) * imageScale * zoomScaleFactor;
21553
- const offsetPixels = offsetMeters * effectivePixelsPerMeter;
21570
+ const offsetPixels = offsetMeters * effectivePixelsPerMeter * sizeScaleAdjustment;
21554
21571
  const offsetRad = ((_b = offset == null ? void 0 : offset.offsetDeg) != null ? _b : 0) * DEG2RAD;
21555
21572
  return {
21556
21573
  x: offsetPixels * Math.sin(offsetRad),
@@ -21577,11 +21594,12 @@ const calculateBillboardAnchorShiftPixels = (halfWidth, halfHeight, anchor, tota
21577
21594
  const calculateSurfaceWorldDimensions = (imageWidth, imageHeight, baseMetersPerPixel, imageScale, zoomScaleFactor, options) => {
21578
21595
  var _a, _b;
21579
21596
  if (!imageWidth || !imageHeight || imageWidth <= 0 || imageHeight <= 0 || baseMetersPerPixel <= 0) {
21580
- return { width: 0, height: 0 };
21597
+ return { width: 0, height: 0, scaleAdjustment: 1 };
21581
21598
  }
21582
21599
  const scaleFactor = baseMetersPerPixel * imageScale * zoomScaleFactor;
21583
21600
  let width = ensureFinite(imageWidth * scaleFactor);
21584
21601
  let height = ensureFinite(imageHeight * scaleFactor);
21602
+ let scaleAdjustment = 1;
21585
21603
  const effectivePixelsPerMeter = (options == null ? void 0 : options.effectivePixelsPerMeter) !== void 0 ? options.effectivePixelsPerMeter : 0;
21586
21604
  const spriteMinPixel = (_a = options == null ? void 0 : options.spriteMinPixel) != null ? _a : 0;
21587
21605
  const spriteMaxPixel = (_b = options == null ? void 0 : options.spriteMaxPixel) != null ? _b : 0;
@@ -21601,11 +21619,12 @@ const calculateSurfaceWorldDimensions = (imageWidth, imageHeight, baseMetersPerP
21601
21619
  if (scale !== 1) {
21602
21620
  width *= scale;
21603
21621
  height *= scale;
21622
+ scaleAdjustment *= scale;
21604
21623
  }
21605
21624
  }
21606
21625
  }
21607
21626
  }
21608
- return { width, height };
21627
+ return { width, height, scaleAdjustment };
21609
21628
  };
21610
21629
  const calculateSurfaceAnchorShiftMeters = (halfWidthMeters, halfHeightMeters, anchor, totalRotateDeg) => {
21611
21630
  var _a, _b;
@@ -21624,7 +21643,7 @@ const calculateSurfaceAnchorShiftMeters = (halfWidthMeters, halfHeightMeters, an
21624
21643
  const north = -anchorEast * sinR - anchorNorth * cosR;
21625
21644
  return { east, north };
21626
21645
  };
21627
- const calculateSurfaceOffsetMeters = (offset, imageScale, zoomScaleFactor) => {
21646
+ const calculateSurfaceOffsetMeters = (offset, imageScale, zoomScaleFactor, sizeScaleAdjustment = 1) => {
21628
21647
  var _a, _b;
21629
21648
  const offsetMeters = ((_a = offset == null ? void 0 : offset.offsetMeters) != null ? _a : 0) * imageScale * zoomScaleFactor;
21630
21649
  if (offsetMeters === 0) {
@@ -21632,8 +21651,8 @@ const calculateSurfaceOffsetMeters = (offset, imageScale, zoomScaleFactor) => {
21632
21651
  }
21633
21652
  const rad = ((_b = offset == null ? void 0 : offset.offsetDeg) != null ? _b : 0) * DEG2RAD;
21634
21653
  return {
21635
- east: offsetMeters * Math.sin(rad),
21636
- north: offsetMeters * Math.cos(rad)
21654
+ east: offsetMeters * Math.sin(rad) * sizeScaleAdjustment,
21655
+ north: offsetMeters * Math.cos(rad) * sizeScaleAdjustment
21637
21656
  };
21638
21657
  };
21639
21658
  const MIN_COS_LAT = 1e-6;
@@ -21781,7 +21800,8 @@ const calculateBillboardCenterPosition = (params) => {
21781
21800
  offset,
21782
21801
  imageScale,
21783
21802
  zoomScaleFactor,
21784
- effectivePixelsPerMeter
21803
+ effectivePixelsPerMeter,
21804
+ pixelDims.scaleAdjustment
21785
21805
  );
21786
21806
  const centerX = base.x + offsetShift.x;
21787
21807
  const centerY = base.y - offsetShift.y;
@@ -21902,7 +21922,8 @@ const calculateSurfaceCenterPosition = (params) => {
21902
21922
  const offsetMeters = calculateSurfaceOffsetMeters(
21903
21923
  offset,
21904
21924
  imageScale,
21905
- zoomScaleFactor
21925
+ zoomScaleFactor,
21926
+ worldDims.scaleAdjustment
21906
21927
  );
21907
21928
  const totalEast = anchorShiftMeters.east + offsetMeters.east;
21908
21929
  const totalNorth = anchorShiftMeters.north + offsetMeters.north;
@@ -21993,6 +22014,91 @@ const MIN_CLIP_Z_EPSILON = 1e-7;
21993
22014
  const EPS_NDC = 1e-6;
21994
22015
  const ORDER_MAX = 16;
21995
22016
  const ORDER_BUCKET = 16;
22017
+ const MIN_FILTER_VALUES = [
22018
+ "nearest",
22019
+ "linear",
22020
+ "nearest-mipmap-nearest",
22021
+ "nearest-mipmap-linear",
22022
+ "linear-mipmap-nearest",
22023
+ "linear-mipmap-linear"
22024
+ ];
22025
+ const MAG_FILTER_VALUES = [
22026
+ "nearest",
22027
+ "linear"
22028
+ ];
22029
+ const MIPMAP_MIN_FILTERS = /* @__PURE__ */ new Set([
22030
+ "nearest-mipmap-nearest",
22031
+ "nearest-mipmap-linear",
22032
+ "linear-mipmap-nearest",
22033
+ "linear-mipmap-linear"
22034
+ ]);
22035
+ const filterRequiresMipmaps = (filter) => MIPMAP_MIN_FILTERS.has(filter);
22036
+ const resolveTextureFilteringOptions = (options) => {
22037
+ var _a, _b;
22038
+ const minCandidate = options == null ? void 0 : options.minFilter;
22039
+ const minFilter = MIN_FILTER_VALUES.includes(
22040
+ minCandidate
22041
+ ) ? minCandidate : DEFAULT_TEXTURE_FILTERING_OPTIONS.minFilter;
22042
+ const magCandidate = options == null ? void 0 : options.magFilter;
22043
+ const magFilter = MAG_FILTER_VALUES.includes(
22044
+ magCandidate
22045
+ ) ? magCandidate : DEFAULT_TEXTURE_FILTERING_OPTIONS.magFilter;
22046
+ let generateMipmaps = (_a = options == null ? void 0 : options.generateMipmaps) != null ? _a : DEFAULT_TEXTURE_FILTERING_OPTIONS.generateMipmaps;
22047
+ if (filterRequiresMipmaps(minFilter)) {
22048
+ generateMipmaps = true;
22049
+ }
22050
+ let maxAnisotropy = (_b = options == null ? void 0 : options.maxAnisotropy) != null ? _b : DEFAULT_TEXTURE_FILTERING_OPTIONS.maxAnisotropy;
22051
+ if (!Number.isFinite(maxAnisotropy) || maxAnisotropy < 1) {
22052
+ maxAnisotropy = 1;
22053
+ }
22054
+ return {
22055
+ minFilter,
22056
+ magFilter,
22057
+ generateMipmaps,
22058
+ maxAnisotropy
22059
+ };
22060
+ };
22061
+ const ANISOTROPY_EXTENSION_NAMES = [
22062
+ "EXT_texture_filter_anisotropic",
22063
+ "WEBKIT_EXT_texture_filter_anisotropic",
22064
+ "MOZ_EXT_texture_filter_anisotropic"
22065
+ ];
22066
+ const resolveAnisotropyExtension = (glContext) => {
22067
+ for (const name of ANISOTROPY_EXTENSION_NAMES) {
22068
+ const extension = glContext.getExtension(name);
22069
+ if (extension) {
22070
+ return extension;
22071
+ }
22072
+ }
22073
+ return null;
22074
+ };
22075
+ const isPowerOfTwo = (value) => value > 0 && (value & value - 1) === 0;
22076
+ const resolveGlMinFilter = (glContext, filter) => {
22077
+ switch (filter) {
22078
+ case "nearest":
22079
+ return glContext.NEAREST;
22080
+ case "nearest-mipmap-nearest":
22081
+ return glContext.NEAREST_MIPMAP_NEAREST;
22082
+ case "nearest-mipmap-linear":
22083
+ return glContext.NEAREST_MIPMAP_LINEAR;
22084
+ case "linear-mipmap-nearest":
22085
+ return glContext.LINEAR_MIPMAP_NEAREST;
22086
+ case "linear-mipmap-linear":
22087
+ return glContext.LINEAR_MIPMAP_LINEAR;
22088
+ case "linear":
22089
+ default:
22090
+ return glContext.LINEAR;
22091
+ }
22092
+ };
22093
+ const resolveGlMagFilter = (glContext, filter) => {
22094
+ switch (filter) {
22095
+ case "nearest":
22096
+ return glContext.NEAREST;
22097
+ case "linear":
22098
+ default:
22099
+ return glContext.LINEAR;
22100
+ }
22101
+ };
21996
22102
  const calculatePerspectiveRatio = (mapInstance, location2) => {
21997
22103
  var _a, _b, _c;
21998
22104
  const transform = mapInstance.transform;
@@ -22621,6 +22727,9 @@ const createSpriteLayer = (options) => {
22621
22727
  var _a;
22622
22728
  const id = (_a = options == null ? void 0 : options.id) != null ? _a : "sprite-layer";
22623
22729
  const resolvedScaling = resolveScalingOptions(options == null ? void 0 : options.spriteScaling);
22730
+ const resolvedTextureFiltering = resolveTextureFilteringOptions(
22731
+ options == null ? void 0 : options.textureFiltering
22732
+ );
22624
22733
  let gl = null;
22625
22734
  let map = null;
22626
22735
  let program = null;
@@ -22629,6 +22738,8 @@ const createSpriteLayer = (options) => {
22629
22738
  let attribUvLocation = -1;
22630
22739
  let uniformTextureLocation = null;
22631
22740
  let uniformOpacityLocation = null;
22741
+ let anisotropyExtension = null;
22742
+ let maxSupportedAnisotropy = 1;
22632
22743
  const images = /* @__PURE__ */ new Map();
22633
22744
  const queuedTextureIds = /* @__PURE__ */ new Set();
22634
22745
  const queueTextureUpload = (image) => {
@@ -23011,16 +23122,6 @@ const createSpriteLayer = (options) => {
23011
23122
  glContext.TEXTURE_WRAP_T,
23012
23123
  glContext.CLAMP_TO_EDGE
23013
23124
  );
23014
- glContext.texParameteri(
23015
- glContext.TEXTURE_2D,
23016
- glContext.TEXTURE_MIN_FILTER,
23017
- glContext.LINEAR
23018
- );
23019
- glContext.texParameteri(
23020
- glContext.TEXTURE_2D,
23021
- glContext.TEXTURE_MAG_FILTER,
23022
- glContext.LINEAR
23023
- );
23024
23125
  glContext.pixelStorei(glContext.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1);
23025
23126
  glContext.texImage2D(
23026
23127
  glContext.TEXTURE_2D,
@@ -23030,6 +23131,52 @@ const createSpriteLayer = (options) => {
23030
23131
  glContext.UNSIGNED_BYTE,
23031
23132
  image.bitmap
23032
23133
  );
23134
+ let minFilterEnum = resolveGlMinFilter(
23135
+ glContext,
23136
+ resolvedTextureFiltering.minFilter
23137
+ );
23138
+ const magFilterEnum = resolveGlMagFilter(
23139
+ glContext,
23140
+ resolvedTextureFiltering.magFilter
23141
+ );
23142
+ let usedMipmaps = false;
23143
+ if (resolvedTextureFiltering.generateMipmaps) {
23144
+ const isWebGL2 = typeof WebGL2RenderingContext !== "undefined" && glContext instanceof WebGL2RenderingContext;
23145
+ const canUseMipmaps = isWebGL2 || isPowerOfTwo(image.width) && isPowerOfTwo(image.height);
23146
+ if (canUseMipmaps) {
23147
+ glContext.generateMipmap(glContext.TEXTURE_2D);
23148
+ usedMipmaps = true;
23149
+ } else {
23150
+ minFilterEnum = glContext.LINEAR;
23151
+ }
23152
+ }
23153
+ if (!usedMipmaps && filterRequiresMipmaps(resolvedTextureFiltering.minFilter)) {
23154
+ minFilterEnum = glContext.LINEAR;
23155
+ }
23156
+ glContext.texParameteri(
23157
+ glContext.TEXTURE_2D,
23158
+ glContext.TEXTURE_MIN_FILTER,
23159
+ minFilterEnum
23160
+ );
23161
+ glContext.texParameteri(
23162
+ glContext.TEXTURE_2D,
23163
+ glContext.TEXTURE_MAG_FILTER,
23164
+ magFilterEnum
23165
+ );
23166
+ if (usedMipmaps && anisotropyExtension && resolvedTextureFiltering.maxAnisotropy > 1) {
23167
+ const ext = anisotropyExtension;
23168
+ const targetAnisotropy = Math.min(
23169
+ resolvedTextureFiltering.maxAnisotropy,
23170
+ maxSupportedAnisotropy
23171
+ );
23172
+ if (targetAnisotropy > 1) {
23173
+ glContext.texParameterf(
23174
+ glContext.TEXTURE_2D,
23175
+ ext.TEXTURE_MAX_ANISOTROPY_EXT,
23176
+ targetAnisotropy
23177
+ );
23178
+ }
23179
+ }
23033
23180
  image.texture = texture;
23034
23181
  });
23035
23182
  };
@@ -23072,6 +23219,20 @@ const createSpriteLayer = (options) => {
23072
23219
  const onAdd = (mapInstance, glContext) => {
23073
23220
  map = mapInstance;
23074
23221
  gl = glContext;
23222
+ anisotropyExtension = resolveAnisotropyExtension(glContext);
23223
+ if (anisotropyExtension) {
23224
+ const ext = anisotropyExtension;
23225
+ const supported = glContext.getParameter(
23226
+ ext.MAX_TEXTURE_MAX_ANISOTROPY_EXT
23227
+ );
23228
+ if (typeof supported === "number" && Number.isFinite(supported) && supported >= 1) {
23229
+ maxSupportedAnisotropy = supported;
23230
+ } else {
23231
+ maxSupportedAnisotropy = 1;
23232
+ }
23233
+ } else {
23234
+ maxSupportedAnisotropy = 1;
23235
+ }
23075
23236
  canvasElement = mapInstance.getCanvas();
23076
23237
  const registerDisposer = (disposer) => {
23077
23238
  inputListenerDisposers.push(disposer);
@@ -23206,6 +23367,8 @@ const createSpriteLayer = (options) => {
23206
23367
  attribUvLocation = -1;
23207
23368
  uniformTextureLocation = null;
23208
23369
  uniformOpacityLocation = null;
23370
+ anisotropyExtension = null;
23371
+ maxSupportedAnisotropy = 1;
23209
23372
  };
23210
23373
  const render = (glContext, _options) => {
23211
23374
  hitTestEntries.length = 0;
@@ -23433,7 +23596,8 @@ const createSpriteLayer = (options) => {
23433
23596
  const offsetMeters = calculateSurfaceOffsetMeters(
23434
23597
  offsetDef,
23435
23598
  imageScale,
23436
- zoomScaleFactor
23599
+ zoomScaleFactor,
23600
+ surfaceCenter.worldDimensions.scaleAdjustment
23437
23601
  );
23438
23602
  const cornerDisplacements = calculateSurfaceCornerDisplacements({
23439
23603
  worldWidthMeters: surfaceCenter.worldDimensions.width,
@@ -23641,7 +23805,8 @@ const createSpriteLayer = (options) => {
23641
23805
  const offsetMeters = calculateSurfaceOffsetMeters(
23642
23806
  offsetResolved,
23643
23807
  imageScale,
23644
- zoomScaleFactor
23808
+ zoomScaleFactor,
23809
+ worldDims.scaleAdjustment
23645
23810
  );
23646
23811
  const cornerDisplacements = calculateSurfaceCornerDisplacements({
23647
23812
  worldWidthMeters: worldDims.width,
@@ -24728,6 +24893,8 @@ const createSpriteLayer = (options) => {
24728
24893
  return spriteLayout;
24729
24894
  };
24730
24895
  export {
24896
+ BETTER_TEXTURE_FILTERING_OPTIONS,
24897
+ DEFAULT_TEXTURE_FILTERING_OPTIONS,
24731
24898
  STANDARD_SPRITE_SCALING_OPTIONS,
24732
24899
  UNLIMITED_SPRITE_SCALING_OPTIONS,
24733
24900
  applyAutoRotation,