Layered Tile providers?


We’re prototyping Cesium for a new project and I was wondering if it is possible to layer tile providers on top of each other? For example, use the Bing tile provider as a base and layer a WMS clouds layer (or any other layer) on top of it at the same altitude. I believe this is different than the CompositeTileProvider in the sandbox, which if I understand correctly, switches providers based upon the altitude of the camera. I saw some traffic (and branches) on layers but I have to confess, a lot of the conversations were over my head. :slight_smile:

Thanks in advance,

Hi Mike,

That capability is currently being implemented in the ‘imagery_layers’ branch, but is not yet available in master. It will be awhile longer before the functionality is stable enough to be merged into master. In the meantime, you may find the version in imagery_layers to be usable for your prototyping. If you try it out, let me know how it goes. There may be some initial stumbling blocks but I can help you work through them.



Thanks for the quick response! We’ll check it out and let you know.


Hi Kevin, I am trying to get the imagery_layers branch of code working outside of the sandbox running under our own server configuration. It seems like the image layers are now coupled to the terrain provider and when you have no terrain, you have no imagery either. The central body now has to take a terrain provider in the constructor. I thought I could switch to 2D mode and maybe this would bypass the terrain problems, but no such luck. Is there any way that I can bypass the terrain provider for now?

Hi Jonah,

You’re right - you always need a terrain provider. However, you can use the “EllipsoidTerrainProvider” if you just want to use the ellipsoid surface rather than actual terrain. Think of it this way: a globe always needs some geometry to hang the imagery on, and the terrain provider is the source of that geometry. There’s commented-out code in Skeleton.js that shows how to construct an EllipsoidTerrainProvider.

You reminded me of an important caveat about the imagery_layers branch: At the moment, the only demo application that works is the 3D skeleton. The sandbox and all forms of 2D and Columbus View are currently broken. We’ll get this fixed up before too long.


Thanks for the quick response Kevin. Skeleton is what I meant to say, not sandbox. That gets me a little farther. The globe is very grainy in the skeleton when I switch to this terrain provider.

I am still having trouble getting it to work outside of the cesium development world because of this webworker inside of TaskProcessor. It uses require js to read in another source file, and getting that to work, would require me to bring in the entire raw source code tree into my app, instead of the combined Cesium javascript file. I tried to take out the requirejs and use that importScripts function to import the single Cesium library file, but I get a window is not defined. I am still trying to find a way around it.

Yes, you are right that currently the web worker system assumes a development layout. My plan is to add to our build system, to produce additional “all-in-one” JS files for each of the web workers, inlining all of the dependencies just like we do for the main Cesium.js file. There will be duplication in the resulting files, but I haven’t thought of a better way to do it.

When you get a “window not defined error”, do you have the file that causes that? We’ve been trying to make sure that Cesium should at least load without a browser window, even though some features may not work without a browser.

That seems like the only way that makes sense to me too Scott. The “window is not defined” error comes from the importScript line of createVerticesFromExtent.js

I get the same error if I import a javascript file with a simple expression like var i = 0, so I do not know what is going on. I don’t have much experience with webworkers.

Looks like a browser restart cleared away the window is not defined for the simple js file. There does not seem to be a way to step into and debug web workers, so I am unable to figure out where the error comes from.

Hey Jonah,

If you’re using Chrome, debugging workers is easy, even if it’s not very intuitive. Open the Developer Tools and then expand the pane on the right labeled “Workers”. Then, check “Pause on Start”. Now, when you refresh the page, a new debugger instance will open. Use that to set breakpoints, step through the code in the worker, etc.

Regarding the grainy globe, I’m not sure what that’s about. Can you share a screenshot?


Hey Kevin, the grainyness allso cleared up when I restarted my browser. Is it possible that the angle driver in chrome can get in a bad state? It almost seems like the pixel size was getting larger and larger on each refresh, and I was looking at a what a globe would look like if you shrink it down into a 10 by 10 pixel grid. I’ll grab a screenshot if I see it again.

On the plus side, thanks for the webworker debugging tip! I was able to get the combined Cesium.js imported after figuring out the window is not defined problem.

In main.js there is this…

require([‘Cesium’], function(Cesium) {

“use strict”;

window.Cesium = Cesium;

}, undefined, true);

I had to change it to this to get the webworkers working…

require([‘Cesium’], function(Cesium) {

if (typeof window !==‘undefined’){

window.Cesium = Cesium;

} else {

self.Cesium = Cesium;


}, undefined, true);

Oh ok, I have seen that grainyness before. I don’t know exactly what causes it, but I suspect it has something to do with running out of memory on the GPU. I’ve usually found that I can fix it just by closing and reopening the tab.

Glad to hear you were able to get the combined Cesium.js working in the web worker!


I have a question about the state of the GeographicTilingScheme. It seems that when I use the GeographicTilingScheme instead of WebMercatorTilingScheme, the level that is passed into buildImageUrl of an ImageryProvider is always zero.

ImageryProvider.prototype.buildImageUrl = function(x, y, level)

I am trying to create a tileprovider that can use an openlayers layer object to generate tile urls. I had this working in the WMS branch using the openlayers wms provider, but now I only see level zero being requested no matter what my zoom is. The only tile provider it seems that uses GeographicTilingScheme is the WMS provider, and it does the same thing. I am trying to follow the code to figure out what’s happening, but I thought I would ask here and see if maybe that class is not finished yet. Thanks.

is always zero.

Hey Jonathan,
I’m away from my computer right now, but one easy thing to check: make sure you’re setting the maxLevel property in the imagery provider. See the ArcGis one for an example. GeographicTilingScheme should work, but it’s not as well tested so it’s possible it’s broken right now.


Another thing to verify is that the level zero tiles are actually loaded successfully. If not, the system will not attempt to load their level one children.

Sorry about the wrong name in my last email, by the way. Autocorrect strikes again!

No problem, thanks for getting back to me. I think autocorrect causes more problems than it helps. I do have maxLevel = 18. The level zero tiles seem to be loading fine because I don’t see anything missing. I will look at it more tomorrow.

There are no errors about missing imagery. I can easily reproduce the problem in the Sandbox by using WebMapServiceImageryProvider

var wmsImagery = new Cesium.WebMapServiceImageryProvider({

url : ‘’,

layerName : ‘basic’,

proxy : new Cesium.DefaultProxy(’/proxy/’)


var wmsLayer = imageryLayerCollection.addImageryProvider(wmsImagery);

And add * to the allowed hosts.

I get the level 0 tiles just fine, and buildImageUrl = function(x, y, level) only ever requests level 0.

The Skeleton example I mean, not the sandbox.

Hi Jonah,

I just tried it out and I see the problem. The WebMapServiceImageryProvider is not setting that tileWidth and tileHeight properties. Previously (the last time we actually tried to use that imagery provider) these properties were not required, but now they are. Once I set them both to 256, everything started working. I pushed my change to the WMS provider to the imagery_layers branch.


Hey Kevin,
It works if I use the ArcGisImageServerTerrainProvider, but I still only see level zero tiles when using the