Cesium newbie. Could somebody help point me in the right direction? (WebGL) (Shader) (Renderer)

First I'll tell you my initial goal is to draw various polygon like this...

Each point has time-series data attached to it and we would like to render the colors based on where that value is at each point on some given gradient or range scheme. (e.g. {range : 1-5, color : blue}, {range : 5-10, color : white}, {range : 10-15, color : green}). Although my image above isn't showing it, I want to exploit webgl's smooth shading library to blend the colors as we see in the starting triangle examples for web and opengl.

I'm new to Cesium and it's wonderful (Sandcastle is a brilliant tool)! However, as I have been looking through some old forum posts and some of the documentation and I can't seem to get a clear picture of where things are currently in terms of using the lower-level WebGL functionality.

I started looking through the forum and found this post...

https://groups.google.com/forum/embed/?place=forum/cesium-dev&showsearch=true&showpopout=true&hideforumtitle=true&fragments=true&parenturl=https%3A%2F%2Fcesiumjs.org%2Fforum.html#!searchin/cesium-dev/WebGL/cesium-dev/WmDTD1PU_Mw/FXLVqQCjw0AJ

But it seems that all the references are outdated, the libraries have changed and the sandcastle examples provided no longer work so I tried to modify it but am still getting errors...

require(['Cesium'], function(Cesium) {
    "use strict";
    
    var viewer = new Cesium.Viewer('cesiumContainer');
    var scene = viewer.scene;

    var ExampleAppearance = function() {
        this.material = undefined;

        this.vertexShaderSource =
    'attribute vec3 position3DHigh;' +
    'attribute vec3 position3DLow;' +
    'attribute vec3 normal;' +
    'varying vec3 v_positionEC;' +
    'varying vec3 v_normalEC;' +
    'void main()' +
    '{' +
    ' vec4 p = czm_computePosition();' +
    ' v_positionEC = (czm_modelViewRelativeToEye * p).xyz;' +
    ' v_normalEC = czm_normal * normal;' +
    ' gl_Position = czm_modelViewProjectionRelativeToEye * p;' +
    '}';

    this.fragmentShaderSource =
    'varying vec3 v_positionEC;' +
    'varying vec3 v_normalEC;' +
    'void main()' +
    '{' +
    ' gl_FragColor = vec4(v_normalEC, 0.5);' +
    '}';
        this.renderState = Cesium.Appearance.getDefaultRenderState(true, false);
    };

    ExampleAppearance.prototype.getFragmentShaderSource = Cesium.Appearance.prototype.getFragmentShaderSource;
    ExampleAppearance.prototype.isTranslucent = Cesium.Appearance.prototype.isTranslucent;
    ExampleAppearance.prototype.getRenderState = Cesium.Appearance.prototype.getRenderState;
  
    var polygon = Cesium.PolygonGeometry.fromPositions({
        positions : Cesium.Cartesian3.fromDegreesArray([
            -122.300313,38.351973,
            -122.299669,38.351094,
            -122.300245,38.350785,
            -122.300548,38.351103,
            -122.300882,38.350944,
            -122.300927,38.350981,
            -122.301006,38.35094,
            -122.301287,38.350796,
            -122.301405,38.350909,
            -122.301669,38.350779,
            -122.301912,38.351047
        ])
    });

    // Add extent instances to primitives
    scene.primitives.add(new Cesium.Primitive({
        geometryInstances : [polygon],
        appearance : new ExampleAppearance()
    }));

    Sandcastle.finishedLoading();
});

with this error...

An error occurred while rendering. Rendering has stopped.
undefined
TypeError: Cannot read property '_workerName' of undefined
TypeError: Cannot read property '_workerName' of undefined
    at Primitive.update (http://cesiumjs.org/Cesium/Source/Scene/Primitive.js:761:46)
    at PrimitiveCollection.update (http://cesiumjs.org/Cesium/Source/Scene/PrimitiveCollection.js:364:27)
    at updatePrimitives (http://cesiumjs.org/Cesium/Source/Scene/Scene.js:1572:27)
    at render (http://cesiumjs.org/Cesium/Source/Scene/Scene.js:1634:9)
    at Scene.render (http://cesiumjs.org/Cesium/Source/Scene/Scene.js:1678:13)
    at CesiumWidget.render (http://cesiumjs.org/Cesium/Source/Widgets/CesiumWidget/CesiumWidget.js:659:25)
    at render (http://cesiumjs.org/Cesium/Source/Widgets/CesiumWidget/CesiumWidget.js:68:32)

So overall I would also like some advice (maybe an up to date example) of how I could do this. Should I try to make my own Geometry with it's own appearance? (I guess that currently we shouldn't create our own custom geometry per the tutorial)...

I looked up to see if people had done anything to draw linear gradients:
https://groups.google.com/forum/embed/?place=forum/cesium-dev&showsearch=true&showpopout=true&hideforumtitle=true&fragments=true&parenturl=http%3A%2F%2Fcesiumjs.org%2Fforum.html#!searchin/cesium-dev/gradient/cesium-dev/IUtQ9U53e5E/zwG4mA7YptgJ

One post suggests to define a material but this will be specific to each polygon and set of points so I'm not sure if this is the correct route to go.
https://groups.google.com/forum/embed/?place=forum/cesium-dev&showsearch=true&showpopout=true&hideforumtitle=true&fragments=true&parenturl=http%3A%2F%2Fcesiumjs.org%2Fforum.html#!searchin/cesium-dev/gradient/cesium-dev/xxSp8UzMBeg/XI9mUEdRQjcJ

Or in future (or maybe more recent) releases are there any ways we will be able to directly draw something using pure webgl and just add it to the map at a specific grid coordinate? (This would ease the mind of all involved at my lab).

Thank you!!

Brian

Hi Brian,

Perhaps you could use the work-in-progress in the ground-primitive branch?

Here’s a few articles on low level graphics in Cesium:

http://cesiumjs.org/2015/05/14/Graphics-Tech-in-Cesium/

http://cesiumjs.org/2015/05/15/Graphics-Tech-in-Cesium-Architecture/

http://cesiumjs.org/2015/05/26/Graphics-Tech-in-Cesium-Stack/

The renderer is not part of the public API so it may change from release to release.

Patrick

Hi Patrick,

Thanks a lot! I looked at the ground-primitive branch and have started educating myself with the cesium architecture. I believe that the terrain will be important for me to model in the future but my first goal is to draw a polygon like this...

and for now I'll the EllipsoidSurfaceAppearance class to dictate how the polygon rests on the surface.

To generate the image above in plain WebGL I send my function the outer coordinates of the polygon and 2 Steiner points in the middle then use the poly2tri triangulation library to triangulate the polygon. I then proceed to draw each triangle while randomly assigning each corner either R,B or G colors. (At some point I will have each shared point render the same color).

My initial thought to get something working was to try and draw a single triangle with the 3 points specified with 3 colors. I plan on doing this by defining something like TriangleMaterialProperty.js and try to mirror one of the procedural materials like Strip or Grid. I also think that I may make a copy of a PolygonGeometry.js and make TriangleGeometry.js to enforce exactly 3 points are drawn.

Once this is done I hope to at least be able to do what I'm currently doing in WebGL but drawn on the globe and try to work from there. My hope is that by defining the triangle geometry I can take advantage of combining multiple triangles into a single primitive and as it was indicated this keeps things efficient.

I'm not sure how feasible or efficient this will be so again I'm seeking out your advice to see if you have any other recommendations. Thank you!

Brian

Hi Brian,

This old draft tutorial on creating custom geometries may be useful to you:

https://github.com/AnalyticalGraphicsInc/cesium/wiki/Geometry-and-Appearances

The API has changed slightly since then, but the changes should be minor.

If you create any geometries or appearances that may be useful to the Cesium community that you would like to contribute, please open a pull request or consider making them a plugin.

Patrick

Hey Patrick,

This looks really promising! However, after I added the normals to the tetrahedron I still don't see shading. I've cleaned and rebuilt a few times to verify that I wasn't referencing any old build code and I'm up to the step in the tutorial where you call createTangentSpaceDebugPrimitive.

Here's my sandcastle code...

// Create the viewer.
var viewer = new Cesium.Viewer('cesiumContainer');
var scene = viewer.scene;
var ellipsoid = scene.mapProjection.ellipsoid;

var modelMatrix = Cesium.Matrix4.multiplyByTranslation(
            Cesium.Transforms.eastNorthUpToFixedFrame(
            ellipsoid.cartographicToCartesian(
                Cesium.Cartographic.fromDegrees(-100.0, 40.0)
            )
        ),
        new Cesium.Cartesian3(0.0, 0.0, 200000.0), new Cesium.Matrix4());

modelMatrix = Cesium.Matrix4.multiplyByUniformScale(modelMatrix,500000.0, new Cesium.Matrix4());

var instance = new Cesium.GeometryInstance({
    geometry :
    //Cesium.GeometryPipeline.toWireframe(
        new Cesium.TetrahedronGeometry()//)

Hey Patrick,

I still have the original question I asked about the tetrahedron but I was able to figure out how to accomplish plotting a basic triangle with 3 different colors and utilizing webgl shaders to do the rest. Here's what it looks like...

I ended up being able to use PerInstanceFlatColorAppearance shaders and then define my own triangle geometry to use it. My next plan is to make a MultiColorPolygonPrimitive.js that takes in a |positions| >=3 and a matching set of colors to each vertex. I will triangulate the polygon and proceed to plot all triangles (sharing some vertices).

Would you guys be interested in this code?

Do you guys have any good triangulation code or libraries? I am currently using poly2tri.

Thanks!

Brian

Hi Brian,

Thanks for sharing your progress.

I suspect you are not seeing shading because flat is set to true (which means to use “flat” shading).

appearance : new Cesium.PerInstanceColorAppearance({

flat : true,

translucent : false

}),

Try setting it to false.

For triangulation, see PolygonPipeline.js. We use a randomized algorithm that is pretty fast and robust. I’m not sure how it compares to poly2tri. We compared it to a few triangulation libraries at one point (maybe including poly2tri?), and it was more robust, but I think there are new ones now that we’ll want to look at eventually.

Would you guys be interested in this code?

Most likely. Thanks for the offer. I suggest opening up a pull request with your initial work. We’ll have a quick look, and if we think it fits with core Cesium, we’ll ask for all the doc, tests, etc. See CONTRIBUTING.md for more info.

Patrick

Wonderful! So I am considering adding a vertex class that would encapsulate positions and colors (and all other variables described by VertexFormat) and I was thinking this may be going against some design principles for your code. Have you considered making a Vertex class and decided not to for some reason? Thanks!

Brian

Brian,

I would pass on the Vertex class - not all vertices will have the same data, and Cesium often works with “structures of arrays” as opposed to “arrays of structures.”

Patrick

Hey Patrick,

So I've decided to go the Plug-in route as this proved to be the best way for me to contribute in the time crunch that I generally have to deal with. I wanted to get your feedback and would like to know what I should change to be added on your list of plug-ins. I already know I went against your Vertex advice but it makes sense in the context of our lab but this can be eventually taken out. I even convert from a list of vertices to two separate lists of colors and positions in my class.

I will try to update it periodically as our lab requires different functionality. Here is my repository where I'll put all my plug-ins.

Also, I am having trouble getting createMultiColorPolygon to work. So currently it's being done synchronously calling createGeometry. When you have a chance could you see if there's something wrong I'm doing?

Thanks!

Add the following quote to solve your problems:
<script type="text/javascript" src="../../../Build/Cesium/Cesium.js"></script>
My Cesium version is 1.13.
Hope to help you.