从WebGL 3D画布读取像素信息返回所有[0,0,0,255]

时间:2016-10-26 23:51:44

标签: javascript canvas webgl arcgis-js-api

我试图完成目标以获取某个WebGL Web软件的图像副本:ArcGIS场景查看器。它使用画布,我尝试了这个:

    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

但是登录控制台的数组总是满[0,0,0,255]。 所以我没有完全控制我用来创建画布的JSAPI,因此我在第一次初始化preserveDrawingBuffer: true时无法设置canvas,我所能做的只是在画布加载地图然后执行一些JS。那么我怎样才能得到我需要的图像?

我在这里做错了吗?我也尝试过framebuffer,它也不起作用:

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);
});

返回的像素值也是[0,0,0,0]。

您可以尝试以下示例:https://jsfiddle.net/qvtt87ky/ 它总是返回一个完整的黑色图像。

2 个答案:

答案 0 :(得分:2)

如果您只需要webgl画布的副本,最简单的方法是将webgl画布绘制到屏幕外画布并使用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是一个Uint8ClampedArray,它将包含您要查找的像素数据。

答案 1 :(得分:1)

Framebuffers只是附件的集合。您没有添加任何附件,因此您的帧缓冲区未设置。

最重要的是,如果你想从帧缓冲区中读取内容,你必须将数据放入(渲染到)帧缓冲区。即使您添加了附件,您的示例代码也不会这样做。

示例:

var gl = document.querySelector("canvas").getContext("webgl");

// Clear the canvas to red
gl.clearColor(1, 0, 0, 1); // red
gl.clear(gl.COLOR_BUFFER_BIT);

// Make a framebuffer
var fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);

// Make a texture
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
var width = 1;
var height = 1;
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);

// Attach the texture to the framebuffer
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);

// Clear the texture to green
gl.clearColor(0, 1, 0, 1); // green
gl.clear(gl.COLOR_BUFFER_BIT);

var pixel = new Uint8Array(4);
// Read from texture (because it's attached to the current
// framebuffer
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
console.log("texture:", pixel);

// Read from canvas to show it's a different color
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
console.log("canvas:", pixel);
<canvas></canvas>

其他

此代码对我没有意义

var resultDOM = document.getElementById("result");
resultDOM.innerText = canvas;

将画布添加为innerText只意味着它会尝试将HTMLCanvasElement转换为可能只打印[object HTMLCanvasElement]之类的字符串,因此我不确定该代码是什么正在努力