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

Investigate image quality degradation #3279

Closed
mramato opened this issue Dec 2, 2015 · 19 comments
Closed

Investigate image quality degradation #3279

mramato opened this issue Dec 2, 2015 · 19 comments

Comments

@mramato
Copy link
Contributor

mramato commented Dec 2, 2015

Reported on the forum

Check out the below image. You'll notice the Cesium version is washed out and slightly blurry compared to the same image in Bing Maps (click it for full resolution). At some point in the rendering pipeline (texture filtering, AA, lighting, etc..) Cesium processing is reducing imagery quality.

I looked at the source files in the network debugger and confirmed that both engines are using the same exact imagery and the rendered Bing map version is identical to the source (since it's just doing img elements like traditional webmaps). This means that Cesium is definitely the culprit here.

image

@pjcozzi
Copy link
Contributor

pjcozzi commented Dec 2, 2015

Just a hunch: see if disabling anisotropic filtering helps this view. I doubt it.

@kring any chance you want to look at this?

@mramato
Copy link
Contributor Author

mramato commented Dec 3, 2015

Just a hunch: see if disabling anisotropic filtering helps this view. I doubt it.

Setting allowTextureFilterAnisotropic to false had no discernible effect.

@kring
Copy link
Member

kring commented Dec 3, 2015

I have looked at this, because it's very obvious in an app like ours where you can toggle between Cesium and Leaflet. Here's what I know:

  1. Cesium applies a gamma of 1.3 to Bing Maps satellite layers. It probably made sense at one point, but IMO it doesn't anymore and we've disabled it in TerriaJS. Perhaps it should be disabled in Cesium in general. That's the cause of most of the "washed out" effect.
  2. Cesium reprojects imagery from Web Mercator to Geographic, and then it unprojects it onto the globe. This extra step probably introduces some blurring compared to simply unprojecting the Web Mercator maps directly. But to do that, we need Web Mercator texture coordinates, and it gets hairy for tiles near the poles.
  3. 2D maps like Bing only allow fixed zoom levels, so image texels always map 1:1 to screen pixels. Cesium allows continuous zoom, which necessitates resampling, which is inevitably going to introduce some blurring.
  4. Cesium's default maximum SSE of 2 means that image texels map to between 1 and 2 screen pixels, so there's actually less detail on the screen compared to a 2D map where the SSE is effectively always exactly 1.

@pjcozzi
Copy link
Contributor

pjcozzi commented Dec 3, 2015

For (1), this was because the imagery was so dark. Is this no longer a problem? Or the lesser of two evils?

@denverpierce
Copy link
Contributor

Fxaa hits tiled layers pretty hard as well, especially labels rendered onto tiles and road/stylized tiles. Mildly related to #2752.

@hpinkos
Copy link
Contributor

hpinkos commented Oct 31, 2016

@hpinkos
Copy link
Contributor

hpinkos commented Dec 19, 2016

@duvifn
Copy link
Contributor

duvifn commented Jan 9, 2017

I encountered this in #4304 and I later realized it's a general problem and not only GoogleEarthImageryProvider's issue (It looks much worse with Geographic Projection-'flat' in Google terminology- than with Mercator projection).

When I compare the same DB in Cesium and in Google Earth- the GE version looks much better.

In Cesium (with gamma fixed to 1.0):
cesium_sf_gamma1 0_ratio_1 0_fxaa_false

In GE (latest version):

ge_plugin_sf

At least in my case, the main reasons for this behavior are points 3 and 4 in @kring comment:

Cesium's default maximum SSE of 2 means that image texels map to between 1 and 2 screen pixels, so there's actually less detail on the screen compared to a 2D map where the SSE is effectively always exactly 1.

When I change the pixel ratio to, say, 0.5 (one level above), the image looks pretty much like in Google earth, and this is preserved while zooming.

After:
cesium_sf_gamma1 0_ratio_0 5_fxaa_false

I believe that this is exactly what Google Earth does, too. I found this when I implemented KML Region for cesium, by sniffing the network output and checking the tile's rectangle dimensions when the appropriate request is sent.
Here is an image of the tile's rectangle when its request was sent- you can see that it's about 128 pixels at the bigger edge.

tiles_rectangle_when_request_sent_ge

(you can read about GE tiling scheme and how to compute tile's rectangle here).

This has some impact on performances, impact that directly related to the ratio value, because more textures are rendered. But for my case this is the best solution and the impact is reasonable.

Of course, this is good only for Imagery, not for rasterized vector, because labels and other vector data would look much smaller than they have to. So we have to let the user choose if to apply such effect.

I think the best way to achieve this is to implement the errorRatio that's mentioned in this comment in the code,:

// The errorRatio should really be imagerySSE / terrainSSE rather than this hard-coded value.
// But first we need configurable imagery SSE and we need the rendering to be able to handle more
// images attached to a terrain tile than there are available texture units. So that's for the future.

From reading GlobeSurfaceTileProvider, it seems that handling more images than available texture units is supported now (correct me if I'm wrong), so only configurable imagerySSE per layer is needed.

I think that for most of the users, ImagerySSE says nothing - so I thought of 'pixelRatio' option in ImageryProvider constructing options (default to 1.0, lower value gives better quality).
@pjcozzi, @kring , @mramato , @hpinkos, @denverpierce, Does it seem to you? Any other suggestions?

@kring
Copy link
Member

kring commented Jan 10, 2017

@duvifn your analysis all sounds correct for me.

One thing I'd suggest is that you use a maximumScreenSpaceError of 1.33 instead of 0.5. That will make between 0.66 and 1.33 imagery texels map to a single pixel on the screen, with a slight tendency toward the smaller value because the estimate of the distance to the tile is conservative.

I'd definitely support adding a separate max SSE value for imagery. You're right that Cesium can now support any number of imagery tiles attached to a terrain tile, so the major roadblock in that comment no longer applies. I think a property called maximumScreenSpaceError on ImageryLayer would be appropriate. pixelRatio sounds less technical, perhaps, but it's less precise and also less consistent with the existing maximumScreenSpaceError property on Globe.

Ideally selection of imagery level would be decoupled from selection of terrain level. Currently we compute the appropriate imagery level for a given terrain tile and use that level for all imagery in that tile from then on. But that ignores the fact that some imagery tiles are closer to the viewer than others. It would be nice to render a high imagery level for the part of a terrain tile close to the viewer, and a lower imagery level for the parts farther away. This is a pretty big change, though.

@duvifn
Copy link
Contributor

duvifn commented Jan 11, 2017

Thanks @kring!

One thing I'd suggest is that you use a maximumScreenSpaceError of 1.33

Great suggestion. 0.66 - 1.33 is indeed more efficient than 0.5-1.0 while it preserves a reasonable image quality.

I think a property called maximumScreenSpaceError on ImageryLayer

OK.

Ideally selection of imagery level would be decoupled from selection of terrain level.

You're right but as you wrote this is a big change and I prefer not to get into it currently.

@hpinkos
Copy link
Contributor

hpinkos commented Mar 13, 2019

Also reported by @giantss in #7644

@giantss
Copy link

giantss commented Mar 14, 2019

After reading the above description, this problem seems to have not been resolved yet?
I am using the last version of cesium

@laurensdijkstra
Copy link

Any ETA on the maximumScreenSpaceError property for ImageryProviders?

@hpinkos
Copy link
Contributor

hpinkos commented Apr 4, 2019

@laurensdijkstra I don't know that this will be a priority for us in the near future, but if you have time to submit a pull request we would be happy to review it! Thanks =)

@mramato
Copy link
Contributor Author

mramato commented Apr 4, 2019

I'm not sure this issue is worth keeping around. The original issue is not what most of the conversation in this thread is about and FXAA support has been rewritten since the initial issue.

There are two different things that were discussed.

First, if you are concerned that you are not getting enough detail in the tiles be loaded (i.e. you expect a higher LOD and Cesium is loading another one, this is do to the maximum screen space error setting, which defaults to 2.0. You can instruct Cesium to load more detailed LODs sooner by lowering this value, the recommended level would be 1.5. I'm going to open a separate issue to discuss making this a new default since Cesium's terrain and imagery rendering has improved greatly since this issue was written.

viewer.scene.globe.maximumScreenSpaceError = 1.5;

The second issue is fxaa being applied to imagery layers which causes "fuzziness" in imagery, especially imagery with crisp labels. This can be fixed by disabling FXAA:

viewer.scene.postProcessStages.fxaa.enabled = false;

In the long term, we want to make sure FXAA does not get applied to imagery and some other object types (labels) so I'll find or write up a specific issue for that.

If anyone still has questions or a different problem, please let us know; but I think keeping this issue open as-is a point of confusion.

@mramato mramato closed this as completed Apr 4, 2019
@cesium-concierge
Copy link

Congratulations on closing the issue! I found these Cesium forum links in the comments above:

https://groups.google.com/forum/#!topic/cesium-dev/xWcXPYkh3c8
https://groups.google.com/d/msg/cesium-dev/6iH8YLXLEgQ/XvWuxTdFCQAJ
https://groups.google.com/forum/?hl=en#!topic/cesium-dev/QTSlECbZmG8

If this issue affects any of these threads, please post a comment like the following:

The issue at #3279 has just been closed and may resolve your issue. Look for the change in the next stable release of Cesium or get it now in the master branch on GitHub https://github.com/AnalyticalGraphicsInc/cesium.

@mramato
Copy link
Contributor Author

mramato commented Apr 4, 2019

Wrote up #7714 and #7715 so that we have clear actionable issues for the items discussed here

@laurensdijkstra
Copy link

viewer.scene.globe.maximumScreenSpaceError = 1.5; does the trick for us, thanks

@glennstowe
Copy link

Does all of this apply only in 3D mode? We are having similar problems with the latest release in 2D mode

godsic added a commit to godsic/df-aggregator that referenced this issue Jul 14, 2022
by making Cesium fetch higher resolution tiles more aggressively as
suggested in
CesiumGS/cesium#3279 (comment)
godsic added a commit to godsic/df-aggregator that referenced this issue Jul 16, 2022
by making Cesium fetch higher resolution tiles more aggressively as
suggested in
CesiumGS/cesium#3279 (comment)
godsic added a commit to godsic/df-aggregator that referenced this issue Apr 15, 2023
by making Cesium fetch higher resolution tiles more aggressively as
suggested in
CesiumGS/cesium#3279 (comment)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests