deck.gl icon indicating copy to clipboard operation
deck.gl copied to clipboard

[Bug] MapLibre Globe Integration

Open brandonjpierce opened this issue 7 months ago • 6 comments

Description

ℹ Caveat up front: I know Globe integration is technically experimental still, this is mostly to document some findings I am seeing in the wild.

When utilizing the @deck.gl/mapbox-overlay extension there appears to be an issue with the canvas interleaving (and technically when not interleaving per example 3 below). I have tried adjusting the parameters prop at the Deck level and layer level but cannot find a combination that draws things correctly. Notably depthCompare: 'always' kind of gives the result I am looking for but effectively removes culling so layers are drawn behind the globe still.

Video of issue:

https://github.com/user-attachments/assets/1472debe-a957-472a-b14d-4c6cda24a57e

Additional oddities:

Text is rendered upside down and has a similar culling/depth type issue:

Image

Image

Flavors

  • [x] React
  • [x] MapboxOverlay

Steps to Reproduce

https://github.com/brandonjpierce/deckgl-maplibre-bug

pnpm i
pnpm run example1
pnpm run example2
pnpm run example3
pnpm run example4
  • Example 1: @deckg-fiber-renderer/dom + maplibre-gl w/ interleaving
  • Example 2: react-map-gl/maplibre + @deck.gl/mapbox-overlay w/ interleaving
  • Example 3: react-map-gl/maplibre + @deck.gl/mapbox-overlay w/ no interleaving
  • Example 4: react-map-gl/maplibre only, no Deck

Examples 1, 2, and 3 each have a different setup just to sanity check things. Examples 2 and 3 in particular are effectively taken directly from the website example. Example 4 is just Maplibre in isolation to ensure there was nothing wrong with the underlying basemap renderer.

I also tried the beforeId and parameters: { cullMode: 'none' } tricks.

Environment

  • Framework version: 9.1.10
  • Browser: Chrome
  • OS: MacOS

brandonjpierce avatar Apr 18 '25 03:04 brandonjpierce

I identified that the TextLayer issue only occurs if you have billboard: false applied. If billboarding is enabled the text is in the correct orientation.

brandonjpierce avatar May 07 '25 13:05 brandonjpierce

Another interesting find:

If you set depthCompare: "always" on the Deckgl parameters prop it does fix the depth fighting issue but culling does not seem to work appropriately. Adding in parameters: { cullMode: 'back' } or a getPolygonOffset accessor does not change anything. This code was added to the reproduction repo under example1 https://github.com/brandonjpierce/deckgl-maplibre-bug/tree/main/example1

https://github.com/user-attachments/assets/af5ce840-9b7b-4151-9cf6-586d86ef1685

brandonjpierce avatar May 07 '25 13:05 brandonjpierce

Interestingly with no MapLibre at all and just a _GlobeView there appears to be some culling issues at play (notice the PathLayer bleeding through when I turn the globe):

https://github.com/user-attachments/assets/e8055eae-8d5a-4ebc-a05b-a697f4dcbcc9

In this example I have cullMode: 'back' and depthCompare: 'always' on.

brandonjpierce avatar May 08 '25 02:05 brandonjpierce

@brandonjpierce I investigated this a bit, and while I don't have a fix I found that making the following change will correct the label orientation for billboard: false

Image

It is in line with my hunch that the Maplibre globe view has a different coordinate system (perhaps right-handed rather than left-handed) which is causing confusing with the vector algebra. It would also explain would cullMode: 'front' is often needed when typically one would want cullMode: 'back'

felixpalmer avatar May 13 '25 09:05 felixpalmer

Good catch @felixpalmer appreciate you investigating this!

brandonjpierce avatar May 14 '25 15:05 brandonjpierce

@felixpalmer an additional update: that incorrect rotation on the text issue is actually present without Maplibre in the picture at all. You can reproduce it on deck v9.1.12 by adding a TextLayer with a _GlobeView.

brandonjpierce avatar May 29 '25 03:05 brandonjpierce

@brandonjpierce @felixpalmer I confirm:

  • cullMode: 'front' is needed where I'd expect cullMode: 'back' instead. At least by the orientation how we're looking at the back or the front of the rendered deck layer. I have tried to override it with frontFace: 'cw' (default is ccw). This used to throw "GL_INVALID_ENUM: Enum 0x0000 is currently not supported." in the past, but seems to work now. Which one is expected?
  • TextLayer is rotated by 180deg in GlobeView.

My workaround is using these helper functions:

export function getViewportPixelOffset(viewport: Viewport, offset: number): number {
  return offset * (isViewportGlobe(viewport) ? -1 : 1);
}

export function getViewportAngle(viewport: Viewport, angle: number): number {
  return angle + (isViewportGlobe(viewport) ? 180 : 0);
}

zakjan avatar Aug 13 '25 15:08 zakjan

@brandonjpierce - The issue with the pathlayer is that the mitering has a bug and is not allowing the triangles to face upwards. I plan on submitting a pull request with the fix on Monday.

Essentially the following code in path-layer-vertex.glsl.ts

  // extend out a triangle to envelope the round cap
  if (isCap) {
    offsetVec = mix(perp * sideOfPath, dir * path.capType * 4.0 * flipIfTrue(isStartCap), isJoint);
    vJointType = path.capType;
  } else {
    vJointType = path.jointType;
  }

should be changed to

  vec2 offsetVec;
  // extend out a triangle to envelope the round cap
  if (isCap) {
    offsetVec = mix(perp * sideOfPath, dir * path.capType * 4.0 * flipIfTrue(isStartCap), isJoint);
    vJointType = path.capType;
  } else {
    vJointType = path.jointType;
    if (isJoint > 0.5) {
      offsetVec = miterVec * miterSize * turnDirection;
    } else {
      offsetVec = perp * sideOfPath;
    }
  }

In the video I have cullMode: 'back' and depthCompare: 'always' with the fix I pasted above.

https://github.com/user-attachments/assets/141ff14f-d0c0-402f-8cce-a90879c3a9ac

wilson0028 avatar Aug 22 '25 23:08 wilson0028