WebGL从屏幕外画布正确读取像素

时间:2020-10-26 19:09:33

标签: javascript html webgl

我知道这方面有很多资源,但是没有一个对我有用。
其中一些是: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着色器,我正在使用用于像素着色器的通用顶点着色器,特别是raytracer / raymarcher。这是: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

2 个答案:

答案 0 :(得分:3)

您应该始终在浏览器的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之一

答案 1 :(得分: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>