cesium icon indicating copy to clipboard operation
cesium copied to clipboard

Create one liner to render canvas to image

Open ggetz opened this issue 7 years ago • 9 comments

Create a one liner to render the current canvas to an image.

Requested on the forum here: https://groups.google.com/forum/#!searchin/cesium-dev/webgl%7Csort:date/cesium-dev/FdQk03zgOMI/KAZp4QiPBwAJ

ggetz avatar Oct 26 '17 20:10 ggetz

Hello! We will try and complete this as part of 24 Pull Requests London with Codebar.

gabriellagal avatar Dec 02 '17 11:12 gabriellagal

Thanks @gabriellagal! Let us know if you have any questions =)

hpinkos avatar Dec 02 '17 15:12 hpinkos

Sorry @hpinkos we ended up shifting our focus from it. It was a more advanced problem than we thought - a little above our level at the moment!

gabriellagal avatar Dec 02 '17 16:12 gabriellagal

No problem =)

hpinkos avatar Dec 02 '17 16:12 hpinkos

Hi, any update about the progress of the issue?

sg-gily avatar Mar 13 '19 17:03 sg-gily

TerriaJS actually builds this right into their Cesium viewer, see the snippet linked to from this forum post:

https://groups.google.com/d/msg/cesium-dev/I-SN1jx0bvg/Vi0h24vFBgAJ

OmarShehata avatar Apr 30 '19 16:04 OmarShehata

Hi @ggetz! I am happy to take this on. However, it would be very helpful if you could provide some more context for this issue. What specifically is needed to implement a fix?

srothst1 avatar Feb 08 '22 01:02 srothst1

Bumping this issue since taking screenshots is an important part of the dev process and this seems like it could be useful feature for end users too.

Currently, I am using this snippet; and based on offline discussion, a lot of other CesiumJS developers use a similar approach:

Sandcastle.addToolbarButton("Capture", function() {
  const scene = viewer.scene;
  const screenshot = function (scene) {
    
    const canvas = scene.canvas;
    const fileName = "screenshot";
    const link = document.createElement('a');
    link.download = fileName + '.png';
    canvas.toBlob(function(blob) {
        link.href = URL.createObjectURL(blob);
        link.click();
    });
    link.remove();
    scene.postRender.removeEventListener(screenshot);
  };
  scene.postRender.addEventListener(screenshot);
});

This has come up several times on the community forum:

I think adding this to the public API, and potentially integrating it into Sandcastle should be looked into (by way of a keyboard shortcut, for example).

Additionally, this function to take a screenshot could take in parameters to do things like increasing resolution scale, improving shadow quality, screen space error to take high quality screenshots.

From a quick look, it seems like ThreeJS doesn't have an API for this, but Babylon.js has tools to help with screenshots.

sanjeetsuhag avatar Apr 20 '22 15:04 sanjeetsuhag

This has also been requested in https://community.cesium.com/t/question-about-screenshot-and-model/28940

The basic functionality of registering a postRender listener and saving the canvas as a blob/URL seems to work. However, at a certain size, the screenshot function just generates a black image. To reproduce this, the sandcastle that was also posted at https://community.cesium.com/t/question-about-screenshot-and-model/28940/18 is replicated here:

https://sandcastle.cesium.com/index.html#c=lVRta9swEP4rwl9qr0FeKIOOvDASChsECs1evhiGIl1sJbIUJNlpN/Lfe7Id8tJkdF8s393zPDrdncSNdp7UErZgyYho2JIpOFmV9Gfji7OIN/bUaM+kBptFySDTmV5WmntpNHGcKRBTtvGVhThYUucJ+Ztp0glTC86oKqDnAYwbdbBBAPEmB8dBh0hHacyTsAXQrjAeMXETTcho3G6zB3Gma+YaeYzT1hx0iMag3kyUWcTxAr/HAoTs1zT9kB7+BSyqPAc72LvanbZnmVJ0e3j29HeuqLBsi4ebVMsl2F9S+OKMXbyb/RVkXvgTulFAlcmxM3P5B4h0JItut7dZFNYiGVw6x+n2WPk1ZiAMr0rQnmJpmYcHBcGKb9jNQSRAqTBbrQwTyMmibyXLga42eRadogoLS0T8eJp1go+LFXCPdlvsUzRXkq/jM6eF0tRw5A1iFmqzvip2dcL6HWTXw6RlSDpdbQCz7pGP9POnvUJb/41x/gm0aJRCDg81lmImnceojQ/D19J2zfcNlQnxL94uXJs504Iz57GJCP9ujFowO6m8Nxo72t0i8twPecbNgJ7er34SpN6pcndN5e5/VO6vqdwn7VMQ9aKh8y8KxvuufJHlxlhPKqtiSlMP5UbhRLh0UfE14MQ5t2/AMD2mDoWsiRSjC88O4Yo5h5FlpVQY/SwaD1PEv6GGWcUb9FiDVewlwIr+eNY6KaXDFM3LTN/W4Ez5FQ

I did spend some time (too much - a few hours, to be honest) trying to figure out why that happens. For the "standalone HTML test" posted at https://community.cesium.com/t/question-about-screenshot-and-model/28940/20 , it is possible to create screenshots that are waaaay larger than the ones that are possible from within CesiumJS. I've been reading about GL context, WebGL, drawing buffers, device limits, but no avail. In other (WebGL) tests, it also seems to bail out at a certain size, but without any error messages or clues about the reasons.

(While diving into some details, the GL context and toBlob function exposed completely erratic behavior. For example: I could save a ~13000x8000 pixel screenshot. but whether or not that was possible depended on the CSS styling that was used for the cesiumViewer div. Yes. Seriously.)

The point is: If the "one-liner" screenshot functionality is added, it should be checked whether this also works when the resolutionScale is set to a "high" value (like 8 or 10, to create a screenshot in the >10k x 10k size range).

javagl avatar Jan 09 '24 18:01 javagl