Three.js: readRenderTargetPixels not working on iOS Safari

Created on 12 Sep 2020  路  2Comments  路  Source: mrdoob/three.js

Reading data from renderTarget does not work on iOS

Example: https://jsfiddle.net/9n0bha3v/1/
QR Code to Example:
image

What the example is supposed to do:
On desktop browsers (tested on Chrome, Safari - latest MacOS) you can click on the webGL canvas and
the pixels are being read into a Uint8Array.

function readPixels(renderer, scene, camera, renderTarget) {

  const {width, height} = renderer.getDrawingBufferSize(new THREE.Vector2());
  const buffer = new Uint8Array(width * height * 4);
  renderer.setRenderTarget(renderTarget);
  renderer.render(scene, camera);
  renderer.readRenderTargetPixels(renderTarget, 0, 0, width, height, buffer);

  return {
    width, height, buffer
  };

}

We then draw those pixels to a 2D canvas for visual feedback using context2D.putImageData. The webGL canvas is essentially duplicated. This is working on all browsers on my desktop machine.

function drawBufferTo2DCanvas(width, height, buffer) {

  // clone buffer data to 2d canvas
  const cvs = document.createElement('canvas');
  const ctx = cvs.getContext('2d');
  cvs.width = width;
  cvs.height = height;
  cvs.style.transform = 'scaleY(-1)'; // flip y

  const imageData = ctx.createImageData(width, height);

  for (let i = 0; i < imageData.data.length; i++) {
    imageData.data[i] = buffer[i];
  }

  ctx.putImageData(imageData, 0, 0);

}

When you try to do the same on iOS Safari all of the rgba values are straight zeros.
The same is true when trying to get an image from the webGL context by calling:
renderer.domElement.toDataURL() (a transparent image is returned)

Things I've already tried:

  • using WebGL1Renderer since iOS does not support webGL 2.0
  • do not read floats since iOS does not support reading from floating point textures
  • initialize renderer with preserveDrawingBuffer set to true
  • initialize renderer with premultipliedAlpha set to false
  • readPixels immediately after rendering to avoid reading from a cleared buffer

The official Three.js example for reading pixels also seems to not work on iOS Safari.

Any hints?

Three.js version
  • [ ] Dev
  • [x] r120
  • [ ] ...
Browser
  • [ ] All of them
  • [ ] Chrome
  • [ ] Firefox
  • [ ] Internet Explorer
  • [x] Safari
OS
  • [ ] All of them
  • [ ] Windows
  • [ ] macOS
  • [ ] Linux
  • [ ] Android
  • [x] iOS
Hardware Requirements (graphics card, VR Device, ...)

Tested on iOS Safari on latest iPhone 11 Pro and latest iPad Pro.

Browser Issue

Most helpful comment

This is an issue with Safari's WebGL implementation.
Please report the issue here: https://bugs.webkit.org/

All 2 comments

This is an issue with Safari's WebGL implementation.
Please report the issue here: https://bugs.webkit.org/

Relevant webkit bug for reference:
https://bugs.webkit.org/show_bug.cgi?id=209139

Was this page helpful?
0 / 5 - 0 ratings