【问题标题】:WebGL Reading pixels properly from offscreen canvasWebGL 从屏幕外画布正确读取像素
【发布时间】:2020-10-27 20:37:01
【问题描述】:

我知道这方面有很多资源,但没有一个对我有用。
有些是:webgl readpixels is always returning 0,0,0,0,
还有这个:https://stackoverflow.com/questions/44869599/readpixels-from-webgl-canvas\ 还有这个:Read pixels from a WebGL texture
但它们都没有帮助或成功。

目标:使用 WebGL 着色器渲染屏幕外画布,然后将其用作单独的 WebGL 着色器中的纹理。

注意事项:

  • 对于这些 WebGL 着色器,我使用了用于像素着色器的通用顶点着色器,特别是光线追踪器/光线跟踪器。这是:attribute vec2 a_position; void main() { gl_Position = vec4(a_position.xy, 0.0, 1.0); }。这个顶点着色器输入了两个覆盖屏幕的三角形,所以基本上片段着色器完成了所有工作。

问题:为了从屏幕外画布上获取图像数据,我尝试了以下方法:

  1. WebGL gl.readPixels 函数
var capturedImageData = new Float32Array(screenWidth * screenHeight * 4);
gl.readPixels(0, 0, screenWidth, screenHeight, gl.RGBA, gl.FLOAT, capturedImageData);
  1. 使用另一个画布和getContext('2d')
var offscreenCanvas = document.createElement("canvas");
offscreenCanvas.width = screenWidth;
offscreenCanvas.height = screenHeight;
var ctx = offscreenCanvas.getContext('2d');
ctx.drawImage(glCanvas, 0, 0);
var capturedImageData = ctx.getImageData(0, 0, screenWidth, screenHeight);

这两种方法都会导致 capturedImageData 数组被
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, . . . 填充,这显然是不对的。

如果有人遇到过这个问题,我们将不胜感激。谢谢!

该程序的直接链接是: https://www.khanacademy.org/cs/-/6289631977619456

【问题讨论】:

  • 你检查过 JavaScript 控制台吗?你应该得到一个错误。
  • 欢迎来到 Stack Overflow!我很高兴您找到了解决问题的方法。但是,实际的答案/解决方案不应编辑到您的问题中。一般来说,您应该edit 对问题进行澄清,但不要在其中包含答案。您应该使用用于解决问题的代码/解决方案创建自己的答案(如果不存在),然后接受它(系统可能需要 48 小时延迟才能这样做)。当你自己解决了问题时,answering your own question is encouraged
  • 啊,好的,感谢您的帮助!我现在就这样做。

标签: javascript html webgl


【解决方案1】:

您应该始终查看浏览器的 JavaScript 控制台(按 F12)或从菜单中选择它。我应该为您的代码显示错误

var capturedImageData = new Float32Array(screenWidth * screenHeight * 4);
gl.readPixels(0, 0, screenWidth, screenHeight, gl.RGBA, gl.FLOAT, capturedImageData);

const gl = document.createElement('canvas').getContext('webgl');
const screenWidth = 300;
const screenHeight = 150;
var capturedImageData = new Float32Array(screenWidth * screenHeight * 4);
gl.readPixels(0, 0, screenWidth, screenHeight, gl.RGBA, gl.FLOAT, capturedImageData);

当我运行你的代码时,我得到了这个错误

js:16 WebGL: INVALID_ENUM: readPixels: invalid type

您无法使用FLOAT 阅读。见this answer

但是,您尝试执行的操作是渲染到一个纹理并将其用作另一个着色器的输入,这不应该使用 readPixels 完成。应该使用允许您直接渲染到纹理的帧缓冲区来完成。

请参阅thisthese 之一

【讨论】:

  • 感谢您的回答!我一直在阅读有关帧缓冲区的内容,它们似乎确实是一个更好的解决方案。
【解决方案2】:

由于某些原因,gl.readPixels 与 Uint8Array 配合得更好。

var capturedImageData = new Uint8Array(screenWidth * screenHeight * 4);
gl.readPixels(0, 0, screenWidth, screenHeight, gl.RGBA, gl.UNSIGNED_BYTE, capturedImageData);

这是一个演示:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />

  </head>
  <canvas></canvas>
  <body>
    <script>
      var gl = document.querySelector("canvas").getContext("webgl");    

    
     gl.clearColor(1, 0, 1, 1);
     gl.clear(gl.COLOR_BUFFER_BIT);
    
    
      var pixels = new Uint8Array(4 * window.innerWidth * window.innerHeight);
      gl.readPixels(0, 0, window.innerWidth, window.innerHeight, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
      
      
      console.log(pixels[0]);
    

  
    </script>
  </body>
</html>

【讨论】:

  • 我在发帖几个小时后最终解决了这个问题,而这正是解决方案。感谢您的帮助:)
  • 没问题!我会注意完成的版本:)
猜你喜欢
  • 2017-12-05
  • 2013-06-11
  • 1970-01-01
  • 2011-02-09
  • 1970-01-01
  • 1970-01-01
  • 2012-11-17
  • 1970-01-01
  • 2011-11-15
相关资源
最近更新 更多