CesiumGS / cesium

An open-source JavaScript library for world-class 3D globes and maps :earth_americas:
https://cesium.com/cesiumjs/
Apache License 2.0
12.98k stars 3.5k forks source link

line incorrectly obscures billboard in some cases #12147

Open BlockCnFuture opened 2 months ago

BlockCnFuture commented 2 months ago

What happened?

I'm creating a linePrimitive on a 3D terrain and want the line to appear semi-transparent when obscured by the terrain. Then, I added a billboard and set disableDepthTestDistance: Number.POSITIVE_INFINITY. Logically speaking, the final rendering effect should be: When the line is blocked by the terrain, it will be displayed as translucent, and when it is blocked by the billboard, it will not be displayed. However, in fact, a translucent line appears on the billboard.

Reproduction steps

1.create a linePrimitive and set depthFailAppearance translucent 2.create a billboard and set disableDepthTestDistance: Number.POSITIVE_INFINITY 3.then a translucent linePrimitive appeared on billboard ...

Sandcastle example

No response

Environment

Browser: CesiumJS Version: Operating System:

ggetz commented 2 months ago

@BlockCnFuture Would you be able to include a Sandcastle example that replicates the issue? That would help us give us more context to determine the issue. Thanks!

BlockCnFuture commented 2 months ago

Thanks, the example:Sandcastle U can see that: image billboard should cover the line, but it doesn't

BlockCnFuture commented 2 months ago

@BlockCnFuture Would you be able to include a Sandcastle example that replicates the issue? That would help us give us more context to determine the issue. Thanks!

this example might be more appropriate: example

If I draw line first, then billboard, billboard won't be obscured by line, but its difficult to ensure draw line first every time. example: I draw line1 first, then billboard1, then user add one line2 and add billboard2, as billboard1 draw before line2, all billboard will be obscured by line example

BlockCnFuture commented 1 month ago

@BlockCnFuture Would you be able to include a Sandcastle example that replicates the issue? That would help us give us more context to determine the issue. Thanks!

I solved the problem by forcing billboard and point to be rendered last, but they are still obscured by the polygon, which is weird

    const originalPrimitiveUpdate = this.viewer.scene.primitives.update
    this.viewer.scene.primitives.update = function (frameState) {
      let lengthO = frameState.commandList.length
      originalPrimitiveUpdate.call(this, frameState)
      let lengthE = frameState.commandList.length
      let othercmds = []
      let billboardcmds = []
      let pointcmds = []
      for (let i = lengthO; i < lengthE; ++i) {
        let command = frameState.commandList[i]
        if (command.owner instanceof Cesium.BillboardCollection) { // include label
          billboardcmds.push(command)
        } else if (command.owner instanceof Cesium.PointPrimitiveCollection) {
          pointcmds.push(command)
        } else {
          othercmds.push(command)
        }
      }
      let cmds = []
      frameState.commandList.length = 0
      othercmds.forEach(c => cmds.push(c)) // ...
      othercmds.length = 0
      billboardcmds.forEach(c => cmds.push(c))
      billboardcmds.length = 0
      pointcmds.forEach(c => cmds.push(c))
      pointcmds.length = 0
      frameState.commandList = cmds 
    }

image