Is there a way to have a transparent polygon 'occlude' another non-transparent polygon behind it such that you are able to see through them both to the map layer below?
Basically like that. Doesn't have to be two transparent polygons either, one is okay.
Creating a mask in 3D like that is a bit tricky. There isn’t a quick built-in way to do it but you might be able to accomplish this with a custom blending mode. You can define a custom Appearance (https://cesiumjs.org/Cesium/Build/Documentation/Appearance.html?classFilter=Appea) and that will allow you to define a blend mode. The documentation on this is a bit sparse right now (I opened a GitHub issue to improve this https://github.com/AnalyticalGraphicsInc/cesium/issues/7203) but these two threads have some code examples of custom blend modes:
If you figure out a good way to do accomplish this, please post back here!
Thanks Omar, I was able to get something! I don't quite understand all the different parts of what the blending options do, but I was able to do pretty much exactly what I wanted.
There are a few downsides, the main one being that the mask polygon affects ALL primitives underneath it; while I would prefer for it to only affect the one directly underneath, or by some other association, I suspect this is asking too much. That is part of why I did the experiment separating the triangle and it's mask into a separate PrimitiveCollection.
The other downside is that when the polygons are put close together (by manipulating the height), the lower ones can 'poke through' the invisible wall and re-appear. That being said, it is solvable by simply increasing the separation, or using 2D mode (which is the context I'm working in, so everything is fine)
I might play around a bit more with the BlendingFunction/Equation and the mask color/alpha but I need to brush up on what exactly is happening first.
This is awesome Jay. Thanks for contributing this! I’m not sure if that was intentional but I appreciate the triforce.
I think having it only affect certain polygons is definitely possible, but will be a bit more work. There are two ways I can imagine doing this: the first is just to use a separate render pass for the mask and its masked primitives. CesiumJS does have a post process system (https://cesiumjs.org/Cesium/Build/Documentation/PostProcessStage.html?classFilter=post) but I’m not sure how easy it would be to render primitives in that pass. You might have to dig a bit into how a scene is rendered (https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Source/Scene/Scene.js#L1964).
The second way has to do with render order. I don’t think Cesium lets you guarantee a particular render order, but if you add the underlying circle first, and give it a separate Appearance, it will render as a solid and the mask will only apply to the triangle. I modified your example to try this out:
I’m really curious, what kind of application are you doing this for?
It's for NOAA's GNOME oil modeling tools, specifically the web frontend. https://gnome.orr.noaa.gov/
Here's an example of the map view so you don't have to figure out how to get the data and set up a simulation. The yellow polygons are what the simulation sees as 'land'. However, these land polygons do not have the lakes integrated, those are separate polygons with a different classification.
Basically, we wanted the lakes to 'look like' the sea, where they would be transparent to whatever base layer put below. In the past, the best we could do was color them differently or not draw them at all.
There's actually quite a bit of low level Cesium work in the various bits of that frontend, mainly in the pursuit of speed with huge datasets and rendering the simulation output close to real time. Now that the Map is converted to use Primitives I think we aren't using Entity level abstraction anywhere.
By the way, I made a further modification to the Sandcastle, where I added another separate blending object to the circle's RenderState so I could experiment a little. It appears that if the'translucent' appearance option is false, it does not get a blending option and becomes unaffected by the mask. However, I found you can still add a custom blending object and leave it disabled, which makes sense. The question now is whether I can enable the blending object and set some combination of settings to evade the mask. Again, I think I need to do some learning and truly understand what's going on in the graphics stack before I spend a lot of time guessing.