Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Underwater Rendering (Do not merge) #6047

Closed
wants to merge 13 commits into from

Conversation

jasonbeverage
Copy link
Contributor

Hi all!

This PR is just to open up discussion on some work that I've been sitting on lately. The general goal is being able to use Cesium to render underwater scenes. I think for the most part we'll be able to get this done with a few minor general purpose changes to Cesium. This isn't ready to merge yet, but I wanted to open it up to discussion and then I can prepare some PRs with the changes later.

First, a fun picture 😄

redoctober

You can play with a live demo here and the code lives in a branch here

What is this demo?

This demo renders two globes. The first is the normal cesium terrain. This takes care of the above ground terrain and the ocean mask. The second globe is a globe that only contains bathymetry data from the SRTM 15 Plus dataset which is being generated by our ReadyMap server. ReadyMap is a server product we've developed here at Pelican Mapping and it has support for Cesium's quantized mesh format. There is a submarine that is under the water and an airplane that is above the water. Select "Under the sea" from the drop down menu to fly near the submarine under the water.

What changes did I make?

Multiple globes

The first major change I did was to add support to Cesium for the multiple globes. This originally came about because I was trying to add the same "split" rendering I did for imagery to terrain as well. I've got a branch here that has the multiple globe changes and a demo you can play with here. The gist is that Scene now has a list of globes that it renders in addition to the primary globe. Those globes can optionally have a splitDirection setting just like ImageryLayers can. This branch realy stands on it's own and I can submit a separate PR for it once we discuss things a bit here.

terrainslider

Disable the EllipsoidalOccluder for underwater scenes

I'm not entirely sure why, but the EllipsoidalOccluder breaks down when you're underwater and dealing with bathymetric tiles. I've put a hack in the EllipsoidalOccluder to just always return true when the camera eye point is at or below 0. If you have any ideas on ways to get around this that would be awesome.

Hack to SingleTileImageryProvider to return the same image at every level

You'll notice that when you go under water in the demo the bathymetry has a repeating sand texture. I accomplished this by just setting the maximumLevel of the SingleTileImageryProvider to 20 instead of 0. Simple but effective :) This looks much better than just displaying thing Bing imagery (or any aerial imagery for that matter) because you end up with the ocean surface being rendered on the ocean floor which looks wrong. We could make this an option or find a fancier way to render the terrain under the water.

Option for backface culling of terrain

I added a boolean on the GlobeSurfaceTileProvider (_cullingEnabled) to control whether backface culling is enabled on the globe or not. I did this so when you are underwater you stil see the backfaces of the ocean surface, giving you a sense that you're under the water.

skirtRatio option for CesiumTerrainProvider

I added an option called skirtRatio to the CesiumTerrainProvider to control how large the skirts are. Normally they are multipled by a factor of 5.0, but this lets you make them really small (or even disable them with a setting of 0.0). This is useful for the ocean surface so you don't see the skirts as bad when you're under water looking at the surface.

Enabling blending on the first pass of the globe

I enabled alpha blending on the first pass of the globe as discussed here. This is just neat b/c it allows you set the terrain base color to transparent if you want to see through the ocean surface to the terrain underneath.

Underwater fog color

You'll notice in the demo that when you go under water you see blue fog in the distance. Cesium's current fog color computation uses fancy smarts to match the atmosphere color. I just hardcoded it ocean blue in the shader 😄 I think it would be useful to set an option for the fog color so users could control it. I'm sure there are other use cases for that besides underwater rendering.

"Fix" bug in ScreenSpaceCameraController

I'll try to get a stack trace, but when the eye point is under the water sometimes the ScreenSpaceCameraController ends up with a camera position of 0,0,0 which then is normalized. This call to Cartesian3.normalize fails b/c it's a 0 magnitude vector. I've just changed Cartesian3.normalize to handle normalizing zero length vectors and I haven't seen a crash since. It's highly possible this is masking another issue, but in general I think it makes sense to be able to normalize a Cartesian3 that is at the origin without throwing an error.

Option for which globe to intersect against

This is a neat feature but can probably have a better API. Once difficutly I've had with this is the ScreenSpaceCameraController wanting to intersect against the globe when I'm underwater. So sometimes I could get under the surface of the ocean but then the collision detection would kick in and bring me back up to the surface. I added a new Scene.intersectionGlobe variable that tells the ScreenSpaceCameraController (and Camera) what globe we actually want to intersect against. I've got a _postRender callback in the demo that just checks the height of the camera and switches to the bathymetry data if you're getting close to the ocean. So far this seems to work really well and I can navigate from being above the ocean to below with no issue.

Like I said, this is just to open things up to discussion and I'm hoping to make a few PR's for any changes necessary to get this done.

Thanks!

Jason

…Occluder if it's below the surface of the ellipsoid
Planes.html
Planes.jpg
Manipulation.html
Planes.html
with Time.html
Primitive.html
Tools/jsdoc/cesium_template/static/images/CesiumLogo.png ->
Documentation/Images/CesiumLogo.png
Source/Scene/GoogleEarthEnterpriseImageryProvider.js
Source/Shaders/Builtin/Constants/maxClippingPlanes.glsl
Source/Shaders/Builtin/Functions/discardIfClipped.glsl
Source/Shaders/Builtin/Functions/discardIfClippedCombineRegions.glsl
Source/Shaders/Materials/ElevationContourMaterial.glsl
Source/ThirdParty/GltfPipeline/processPbrMetallicRoughness.js
Specs/Core/GoogleEarthEnterpriseTerrainProviderSpec.js
Specs/Scene/createTileMapServiceImageryProviderSpec.js
Specs/Widgets/Cesium3DTilesInspector/Cesium3DTilesInspectorViewModelSpec.js
Tools/jsdoc/cesium_template/static/styles/jsdoc-default.css
@cesium-concierge
Copy link

Signed CLA is on file.

@jasonbeverage, thanks for the pull request! Maintainers, we have a signed CLA from @jasonbeverage, so you can review this at any time.

⚠️ I noticed that CHANGES.md has not been updated. If this change updates the public API in any way, fixes a bug, or makes any non-trivial update, please add a bullet point to CHANGES.md and comment on this pull request so we know it was updated. For more info, see the Pull Request Guidelines.


I am a bot who helps you make Cesium awesome! Contributions to my configuration are welcome.

🌍 🌎 🌏

@jasonbeverage jasonbeverage changed the title Underwater Rendering (Do no merge) Underwater Rendering (Do not merge) Dec 12, 2017
@smills2929
Copy link

This seems extremely related to underground rendering, which is a frequently requested feature as well. Is it something that could easily be adapted for this purpose?

@pjcozzi
Copy link
Contributor

pjcozzi commented Jan 20, 2018

@smills2929 for sure - this is a similar feature - watch this space!

@pjcozzi
Copy link
Contributor

pjcozzi commented Jan 20, 2018

@jasonbeverage are you the author of submarine.gltf and sand.jpg? Or is there another source we should credit?

result.z /= magnitude;
}
else {
debugger;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol, we will not want this change.

@pjcozzi
Copy link
Contributor

pjcozzi commented Jan 20, 2018

@jasonbeverage we'll find someone to do a detailed review but it may take us a month or two.

In the meantime, for the rendering architecture, does something like this make sense:

  1. Render terrain - based on the watermask, allow the fragment shader to read from a separate undersea imagery layer (maybe start with the repeating sand, then we can add support for full tiled imagery layers)
    • Undersea fog could still happen here until we can move all fog to a post-process, Post processing #5615
    • The terrain dataset would have both above and undersea terrain
  2. Add a render pass for undersea primitives, and render them. To start this could just be glTF models, but we can help flush it out to support vector data, etc.
  3. Add an explicit water surface render pass (in this order so the blending is correct) that renders the WGS84 ellipsoid. This could just be a box enclosing the WGS84 ellipsoid that is ray casted so there are no tiles and no cracks, https://pdfs.semanticscholar.org/ba74/03ae3ae87b4aed043ab29c2f2d2c8f48fcd1.pdf

@jasonbeverage
Copy link
Contributor Author

Hey @pjcozzi !

Sorry it took me so long to get back to you on this :)

I think your architecture sounds good to me. Just so I make sure I'm understanding, the changes you're proposing vs what I've done are:

  • We would have a single terrain provider that includes both the terrain and the bathymetry (like our ReadyMap dataset)
  • Instead of using a separate globe to render the water, use the explicit water pass using your paper to render a separate ellipsoid for the water to avoid any cracks. I like this idea and I suppose it could just be another primitive.
  • Adding an explicit Pass in Pass.js for the underwater objects and the water surface. These would render before the water surface is rendered. I suppose the logic for determining if a model is under the water to determine which pass it should be rendered in should be in ModelVisualizer and not something that requires user intervention, right?

The repeating sand texture was just an interesting little effect for the demo, I'm not sure if it warrants actually building anything directly into Cesium just yet. Eventually it would be really cool to render procedural imagery like coral and rocks underwater, but that's a whole thing :)

The support I added for multiple globes in this PR is really useful for us to provide splitter support terrain in addition to imagery. If I broke that out into it's own standalone PR would that be something that you'd accept or is there another way you would suggest going about that?

@pjcozzi
Copy link
Contributor

pjcozzi commented Mar 12, 2018

@jasonbeverage welcome back 😁

Generally, everything sounds good.

The support I added for multiple globes in this PR is really useful for us to provide splitter support terrain in addition to imagery. If I broke that out into it's own standalone PR would that be something that you'd accept or is there another way you would suggest going about that?

Most likely. I would suggest to just open up the standalone PR and we'll double check that everything fits in well. As long as it isn't a maintenance problem - which I don't recall it likely being one - it should be good.

I suppose the logic for determining if a model is under the water to determine which pass it should be rendered in should be in ModelVisualizer and not something that requires user intervention, right?

Ideally even the scene renderer could determine this, but if that gets hairy, I don't think it is impossible for the user to have to flag it. Some objects will also be both under and above water, but I don't think that we need to handle that right away.

Regardless, one approach could be to let the user flag it, and then we determine the best way to automate it.

@cesium-concierge
Copy link

Thanks again for the pull request!

Looks like this pull request hasn't been updated in 30 days since I last commented.

To keep things tidy should this be closed? Perhaps keep the branch and submit an issue?

I am a bot who helps you make Cesium awesome! Contributions to my configuration are welcome.

🌍 🌎 🌏

@jodyford
Copy link

jodyford commented Sep 1, 2018

I'm interested in having this merged in, please.

@hpinkos
Copy link
Contributor

hpinkos commented Sep 4, 2018

@jodyford this is still a work in progress. Adding underwater support is something that gets requested very frequently and is high on our priority list, but I'm not sure how soon we'll be able to finish it up and add full support.

@wakecoder
Copy link

Any updates on this? This is something we're interested in as well. Is it still being worked? I looked at the fork and didn't see any recent activity.

@jasonbeverage
Copy link
Contributor Author

I'd say this isn't going to be merged as is. There are still some issues to sort out and this branch needs some updating since it's so far out of sync from the original. @pjcozzi do you want to close this PR in favor of an issue or is it useful to keep it open?

@cesium-concierge
Copy link

Thanks again for your contribution @jasonbeverage!

No one has commented on this pull request in 30 days. Maintainers, can you review, merge or close to keep things tidy?

I'm going to re-bump this in 30 days. If you'd like me to stop, just comment with @cesium-concierge stop. If you want me to start again, just delete the comment.


I am a bot who helps you make Cesium awesome! Contributions to my configuration are welcome.

🌍 🌎 🌏

@hpinkos
Copy link
Contributor

hpinkos commented Dec 12, 2018

@cesium-concierge stop

@ALPSMAC
Copy link

ALPSMAC commented Feb 13, 2019

Hi there. I was just wondering what the current status of this work is?

In my office not having this capability is a real limitation for us. It means we currently rely on Cesium for much of our geo-spatial awareness, but then pivot to other custom solutions for the things we need to render under the ocean (which is a good deal of our problem domain). From a usability perspective this means presenting the user with two different "windows" and forcing them to fuse information between them to connect the dots. That's considerably less than optimal.

We spoke on the phone with @pjcozzi a few months back (sometime in late November if memory serves) and at the time it seemed that there was some optimism around getting these changes merged. Since then momentum seems to have slowed on this PR.

If it's a relatively small lift to get this to "good" we might be willing to help a bit, although I can't commit to anything specifically. We've got a few folks on our team with some experience with Cesium, but I don't know that we understand the technical underpinnings enough yet to understand how best to make this go.

@jasonbeverage
Copy link
Contributor Author

Hi @ALPSMAC, you are correct that momentum on this PR got stopped. Basically the functionality was good enough for a stopping point for my customer that funded it so they were just using my Cesium branch. This branch is pretty far removed from the current Cesium, so it's probably worth taking another stab at this to make it better. Right now I'm honestly pretty swamped with work (which is a good thing 😄 ) but later in the year I'd have more time to look at revamping this with a fresh take. Shoot me an email at jasonbeverage@pelicanmapping.com and maybe we can setup a time to chat.

@ebogo1
Copy link
Contributor

ebogo1 commented Sep 23, 2021

This feature would be nice to support but the implementation needs more work to merge at this point.

@ebogo1 ebogo1 closed this Sep 23, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

None yet

9 participants