Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Read pixel information from a WebGL 3D canvas return all [0, 0, 0, 255]

I'm trying to complete a goal to get a image copy of a certain WebGL Web software: ArcGIS Scene Viewer. It is using a canvas and I tried this:

    var canvas = document.getElementsByTagName("canvas")[0];
    var resultDOM = document.getElementById("result");
    resultDOM.innerText = canvas;
    var gl = canvas.getContext("webgl", {preserveDrawingBuffer: true});
    var pixels = new Uint8Array(gl.drawingBufferWidth * gl.drawingBufferHeight * 4);
    gl.readPixels(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
    console.log(pixels); // Uint8Array

But the Array logged in console is always full of [0, 0, 0, 255]. So I'm not in full control of the JSAPI I use to create that canvas, so I can't set preserveDrawingBuffer: true when first time initializing the canvas, all I can do is after the canvas loaded the map then execute some JS. So how can I get the image I need?

Am I doing something wrong here? I also tried framebuffer, it is also not working:

canvas.addEventListener('click', function(ev) {
    var gl = canvas.getContext("webgl", {
      preserveDrawingBuffer: true
    });
    var framebuffer = gl.createFramebuffer();
    //insert code to get mouse x,y position on canvas
    var top = canvas.offsetTop;
    var left = canvas.offsetLeft;
    var x = ev.clientX - left;
    var y = ev.clientY - top;
    var pixels = new Uint8Array(4);
    gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
    gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
    gl.bindFramebuffer(gl.FRAMEBUFFER, null);
    console.log(x, y, pixels);
});

The pixel value returned is also [0, 0, 0, 0].

Here's a sample you can try: https://jsfiddle.net/qvtt87ky/ It is always returning a whole black image.

like image 278
sillicon Avatar asked Oct 19 '25 13:10

sillicon


1 Answers

If you just need an copy of the webgl canvas, the easiest way would be to draw the webgl canvas to an offscreen canvas and extract the pixel data using the CanvasRenderingContext2D.

var webglCanvas;

var offscreenCanvas = document.createElement("canvas");
offscreenCanvas.width = webglCanvas.width;
offscreenCanvas.height = webglCanvas.height;
var ctx = offscreenCanvas.getContext("2d");

ctx.drawImage(webglCanvas,0,0);
var imageData = ctx.getImageData(0,0, offscreenCanvas.width, offscreenCanvas.height);

console.log(imageData.data);

imageData.data is an Uint8ClampedArray and it will have the pixel data that you are looking for.

like image 84
geoji Avatar answered Oct 22 '25 03:10

geoji