Export the scene as an image

In Fog - Cesium Sandcastle, I saw a method of exporting a canvas as an image.

    const container = document.getElementById("cesiumContainer");
    const tmpH = container.style.height;
    const tmpW = container.style.width;

    // resize for screenshot
    container.style.height = "600px";
    container.style.width = "800px";
    viewer.resize();
    viewer.render();

    // chrome blocks opening data urls directly, add an image to a new window instead
    // https://stackoverflow.com/questions/45778720/window-open-opens-a-blank-screen-in-chrome
    const win = window.open();
    win.document.write(`<img src="${viewer.canvas.toDataURL("image/png")}" />`);
    // stop the browser from trying to load "nothing" forever
    win.stop();

    // reset viewer size
    container.style.height = tmpH;
    container.style.width = tmpW;
    viewer.resize();
    viewer.render();

The default value of preservedDrawingBuffer is false, which means that the results in the framebuffer will not be preserved.

Why can calling the viewer.render() once in advance ensure that there is correct content in the framebuffer?

Hi @SAYEOR

This answer is just based on some light research I’ve just done. My understanding is that preserveDrawingBuffer is a bit misleading- it just controls whether WebGL uses a single drawing buffer that gets copied / cleared on each draw (which is slow), versus using a double buffer with a swap each draw (more memory intensive but faster and generally preferred). Without preserveDrawingBuffer turned on, the data in buffer still exists and only gets swapped out on the next draw, so as long as you write it out before the next draw, in theory it works.

Got some of that info from this page, if you search for preserveDrawingBuffer

Hope that helps.

Best,
Matt

@mzschwartz5 Thank you very much for your answer. I have also searched for some information:

  1. Trail Effects with Preserve Drawing Buffer
  2. WebGL Specification

I have extracted some descriptions from the above content:

By default, preserveDrawingBuffer=false, swaps these buffers once rendering is done. And after the swap, the new drawing buffer is cleared.
Before the drawing buffer is presented for compositing the implementation shall ensure that all rendering operations have been flushed to the drawing buffer. By default, after compositing the contents of the drawing buffer shall be cleared to their default values, as shown in the table above.

A very important time point is “rendering completion”. After rendering is completed, the drawing buffer will be cleared. Can it be considered as rendering completion after calling viewer. render()? If so, why can we still retrieve the contents of the drawing buffer?

It could very well be the case that this is simply undefined behavior that this sandcastle is leveraging and getting away with.

Per the WebGL spec: “…If this flag is false, attempting to perform operations using this context as a source image after the rendering function has returned can lead to undefined behavior”

That doesn’t mean it won’t work in some implementations, just that it shouldn’t be relied upon. That, or the viewer.render() function isn’t actually invoking a WebGL render when called this way, but that would require deeper investigation to confirm.