【问题标题】:Read pixel information from a WebGL 3D canvas return all [0, 0, 0, 255]从 WebGL 3D 画布读取像素信息返回所有 [0, 0, 0, 255]
【发布时间】:2016-10-26 23:51:44
【问题描述】:

我正在尝试完成获取某个 WebGL Web 软件的图像副本的目标:ArcGIS Scene Viewer。它正在使用画布,我试过这个:

    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,所以我不能在第一次初始化 canvas 时设置 preserveDrawingBuffer: true,我所能做的就是在画布加载地图之后执行一些JS。那么我怎样才能得到我需要的图像呢?

我在这里做错了吗?我也尝试了帧缓冲区,它也不起作用:

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/ 它总是返回一个全黑的图像。

【问题讨论】:

标签: javascript canvas webgl arcgis-js-api


【解决方案1】:

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

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

例子:

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] 之类的字符串,所以我不确定该代码正在尝试做什么

【讨论】:

    【解决方案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,它将包含您要查找的像素数据。

    【讨论】:

    • 这给出了与仅使用 readPixels 相同的结果 - 有时是真实颜色,但通常只是 [ 0, 0, 0, 255 ]..
    猜你喜欢
    • 1970-01-01
    • 2017-12-05
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    • 2014-10-06
    • 2011-11-29
    • 2022-12-09
    • 2018-12-03
    相关资源
    最近更新 更多