cesium icon indicating copy to clipboard operation
cesium copied to clipboard

Image Material doesn't update when canvas content or image src changes

Open hpinkos opened this issue 7 years ago • 6 comments

Reported on the forum: https://groups.google.com/forum/?hl=en#!topic/cesium-dev/7Bda_BkaJMU

The canvas used for the image material is updating, but the rectangle itself does not. It's because we only read from the canvas once and then it's skipped for subsequent updates https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Source/Scene/Material.js#L762

Is there any way to detect if a canvas has changed?

<style>
    @import url(../templates/bucket.css);
    #canvas {
        position: absolute;
        left: 0;
        top: 50px;
    }
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>Loading...</h1></div>
<div id="toolbar"></div>
<canvas id="canvas" width="800" height="200"></canvas>
var viewer = new Cesium.Viewer('cesiumContainer');

var i = 0;
function drawCanvas() {
    var canvas = document.getElementById("canvas");
    var context = canvas.getContext('2d');
    context.clearRect(0, 0, canvas.width, canvas.height);    
    context.font = 'italic 40pt Calibri';
    context.fillStyle = "white";
    context.fillText(i++, 20, 100);
    return canvas;
}

viewer.entities.add({
    rectangle: {
        coordinates: Cesium.Rectangle.fromDegrees(-92.0, 30.0, -76.0, 40.0),
        material: new Cesium.ImageMaterialProperty({
            image: new Cesium.CallbackProperty(drawCanvas, false),
            transparent: true
        })
    }
});

viewer.zoomTo(viewer.entities);

image example:

var viewer = new Cesium.Viewer('cesiumContainer');

var image = new Image(100, 200);
image.src = '../images/Cesium_Logo_Color.jpg';

var material = Cesium.Material.fromType('Image', {
    image: image
});

viewer.scene.primitives.add(new Cesium.Primitive({
    geometryInstances : new Cesium.GeometryInstance({
        geometry : new Cesium.RectangleGeometry({
            rectangle : Cesium.Rectangle.fromDegrees(-120.0, 30.0, -110.0, 40.0),
            vertexFormat : Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT
        })
    }),
    appearance : new Cesium.EllipsoidSurfaceAppearance({
        material : material
    })
}));

Sandcastle.addToolbarButton('Change image', function() {
    image.onload = function(){
        material.uniforms.image = image;
    };
    image.src = '../images/Cesium_Logo_overlay.png';
});

hpinkos avatar Mar 07 '17 14:03 hpinkos

This is by design. We can consider adding something like a dynamic flag to update the WebGL texture from the canvas each frame; in the meantime, the app should explicitly update it.

pjcozzi avatar Mar 07 '17 23:03 pjcozzi

Might something like this be able to support updating tiles as well?

For instance, I'd like to visualize wind in Cesium. My data is tiled PNGs with raw UV vector values encoded into the Red and Green bands. (https://mapbox.github.io/webgl-wind/demo/)

I can get the particles dropped but updating the canvas to move them isn't possible with the current Imagery/ImageryLayer implementation.

NaderCHASER avatar Apr 27 '18 20:04 NaderCHASER

Reported again here: https://groups.google.com/d/msg/cesium-dev/D4Nre2wu3II/KuCki2YsAAAJ

OmarShehata avatar Jul 23 '18 21:07 OmarShehata

Anyone had solved it?

zapzqc avatar Nov 02 '18 08:11 zapzqc

@zapzqc looks like a workaround is to use two canvasas to swap between, more on that here: https://groups.google.com/d/msg/cesium-dev/7Bda_BkaJMU/mfAM7WraBAAJ

OmarShehata avatar Nov 02 '18 12:11 OmarShehata

This is by design. We can consider adding something like a dynamic flag to update the WebGL texture from the canvas each frame; in the meantime, the app should explicitly update it.

@pjcozzi I'll be glad to know how to update the WebGL texture explicit

GuyAgiv avatar Dec 27 '23 07:12 GuyAgiv