Sharper text

Gents,

My text labels are somewhat blurry and thus unreadable at 10pt. They are bigger than expected, though.

My lines are rather thick at 1px.

I guess Cesium actually renders at lower resolution (for performance reasons) and then scales.

But the end result is not satisfactory and I’d like to experiment with higher resolution rendering.

I believe there is an option controlling this, but can’t find it.

Am I right assuming that blurry text has to do with rendering resolution?

Can you point me to the option?

Thank you.

Your assumptions are incorrect. We render text at native resolutions using built in browser functions. No scaling is done. The only thing special about Cesium’s rendering is that we do not render entire words because it is nonperformant. Instead we render individual letters, this allows words with the same font settings to share letters, saving a ton of memory and texture creation time.

The root of the problem you are seeing is that browsers apply antialiasing to text when it is drawn onto a canvas and then again when it is actually rendered in Cesium on screen. While the feature has been often requested, there is still no way to disable antialiasing when writing text to a canvas (though if I’m wrong we will change it in Cesium ASAP). The Browsers need to add this feature, we can’t.

A possible workaround is for you to specify font at twice it’s desired size (note specifying pt fonts is not linear, but using px is), and then use the label scale property to shrink it back down. This uses more memory but will minimize the amount of aliasing artifacts from the initial canvas writing and create crisper text. Of course this may exaggerate some of the font kerning issues that are in master (addressed in https://github.com/AnalyticalGraphicsInc/cesium/pull/2549 but still needs a little work before merging).

I expect label rendering to improve in Cesium in the future, but the antialiasing issue for smaller fonts is not something we can fix ourselves (as far as I know, I’d love to be wrong).

Don't know if this is useful but I noticed that on the first rendered frame the font is crisp and the next one it gets blurred. I managed to screenshot the thing in this image:
http://s30.postimg.org/sdzhjzroh/correct1.png

Is this browser antialiasing kicking in?

I actually found out that the blurring happens only when I add a polyline to the primitive collection of Cesium, adding 3D primitives such as cylinders does not cause the bug. Im my case I add polylines after the labels. If I only add labels (billboards actually) there is no blurring. Is it possible that this is a openGL context state problem with the texture lookup function (linear vs. point loockup)?

To reproduce the "bug" paste the code in the sandcastle demo, when the polyline is added the text gets blurred. I noticed that adding the polyline this way enables some sort of antialiasing on the jagged border of the globe too.

var viewer = new Cesium.Viewer('cesiumContainer');
viewer.entities.add(
{
  position: new Cesium.Cartesian3(1000,-6000000,1000),
  label:
  {
    text:"TESTlabelWithS0m3 text and numbers9834#]",
    font: '15pt monospace',
    scale: 1,
    style: Cesium.LabelStyle.FILL_AND_OUTLINE,
    outlineWidth: 2,
    verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
    pixelOffset: new Cesium.Cartesian2(0, 0)
  }
});

viewer.scene.primitives.add
(
    new Cesium.Primitive
    ({
        geometryInstances: new Cesium.GeometryInstance
        ({
            geometry: new Cesium.PolylineGeometry
            ({
                positions : Cesium.Cartesian3.fromDegreesArray([0.0, 0.0,5.0, 0.0,5.0, 5.0]),
            }),
            attributes:
      {
        color: Cesium.ColorGeometryInstanceAttribute.fromColor(new Cesium.Color(1.0, 1.0, 1.0, 1.0))
      }
        }),
    appearance: new Cesium.PolylineColorAppearance()
    })
);

Chrome and Firefox have the problem, IE does not seem to be affected.
Sorry for the quadruple post

Federico, you have a good eye. What you are seeing is the issue I described in action. To explain in more detail:

Cesium only performs an FXAA pass when there is translucent geometry on the screen. Your example code actually has a bug in it because you are coloring a polyline solid white but not telling PolylineColorAppearance that your line is opaque. Try changing your code to PolylineColorAppearance({translucent : false}) and you may see the blurriness go away again (unless something else in the scene isn’t triggering the FXAA pass). Because the text is already antialiased once when the FXAA pass happens the text gets blurry.

You can also disable FXAA completely with the two lines below, However, this is not recommended because you will see jagged geometry all over the place (but crisp text). Try it out and see for yourself.

viewer.scene.fxaa = false;

viewer.scene.fxaaOrderIndependentTranslucency = false;

This area of the code isn’t my expertise, so I’ll have Dan take a quick look to confirm that my explanation is correct and this isn’t some sort of bug. (I actually hope its a bug, because that means there’s the possibility of a short-term solution to the problem). We may still be able to fix the blurriness longer term, but it would be a lot easier if browsers just had a way to disable AA text when trying to a canvas.

Thanks again for the debug analysis.

Thankyou for the explanation.

A workaround may be to have a perfect correlation between font textures pixels and the render buffer pixels; with this it should be possible to enable anti aliasing without causing blurring and also should reduce the artifacts when moving the camera around. This should also improve image screen space rendering as long as image and fonts are not scaled.

By rounding screen space "pixel" coordinate before transforming to normalized (0..1) screen space in BillboardCollectionVS.js shader (line 225) the rendering improves but it is not perfect:

gl_Position = czm_viewportOrthographic * vec4(positionWC.xy, -positionWC.z, 1.0);

to

gl_Position = czm_viewportOrthographic * vec4(floor(positionWC.xy+0.5), -positionWC.z, 1.0);

We actually used to clamp to whole pixels for labels as you suggest, but it actually creates a worse problem where moving labels jitter like crazy. For example, load simple.czml with your change and observe the satellite text shaking. It’s even worse when you double click on a satellite to follow it.

Although using "perfect-pixel" coordinates will make jittering more visible I think it is advisable to provide it as an option.

I tried loading simple.czml example with the change and the jittering was indeed worse but I found that when rounding the screen coordinates the x axis ends up exactly between the 2 pixels (if you add 0.5 to both coordinates then x is centered but the y is not). I noticed this because the billboard was jittering only on the y axis. This can be solved by adding 0.5 only to the x coordinate.

Of course when zooming in a lot the world->screen transformation will start to cause precision problems but this happens in both cases.