WebGL 从屏幕外正确读取像素 canvas
WebGL Reading pixels properly from offscreen canvas
我知道有很多这方面的资源,但是 none 其中对我有用。
其中一些是:webgl readpixels is always returning 0,0,0,0、
还有这个:
以及这个:Read pixels from a WebGL texture
但是 none 其中有帮助或取得了成功。
目标:使用 WebGL 着色器渲染离屏 canvas,然后在单独的 WebGL 着色器中将其用作纹理。
备注:
- 对于这些 WebGL 着色器,我使用了用于像素着色器的通用顶点着色器,具体来说,raytracer/raymarcher。这是:
attribute vec2 a_position; void main() { gl_Position = vec4(a_position.xy, 0.0, 1.0); }
。这个顶点着色器输入了两个覆盖屏幕的三角形,所以基本上片段着色器完成了所有工作。
问题:为了让图像数据脱离屏幕canvas,我尝试了这些方法:
- WebGL
gl.readPixels
函数
var capturedImageData = new Float32Array(screenWidth * screenHeight * 4);
gl.readPixels(0, 0, screenWidth, screenHeight, gl.RGBA, gl.FLOAT, capturedImageData);
- 使用另一个 canvas 和
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, . . .
,这显然是不对的。
如果有人遇到过这个问题,将不胜感激。谢谢!
直接link程序是:
https://www.khanacademy.org/cs/-/6289631977619456
出于某种原因 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>
您应该始终查看浏览器的 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 完成。应该使用允许您直接渲染到纹理的帧缓冲区来完成。
我知道有很多这方面的资源,但是 none 其中对我有用。
其中一些是:webgl readpixels is always returning 0,0,0,0、
还有这个:
以及这个:Read pixels from a WebGL texture
但是 none 其中有帮助或取得了成功。
目标:使用 WebGL 着色器渲染离屏 canvas,然后在单独的 WebGL 着色器中将其用作纹理。
备注:
- 对于这些 WebGL 着色器,我使用了用于像素着色器的通用顶点着色器,具体来说,raytracer/raymarcher。这是:
attribute vec2 a_position; void main() { gl_Position = vec4(a_position.xy, 0.0, 1.0); }
。这个顶点着色器输入了两个覆盖屏幕的三角形,所以基本上片段着色器完成了所有工作。
问题:为了让图像数据脱离屏幕canvas,我尝试了这些方法:
- WebGL
gl.readPixels
函数
var capturedImageData = new Float32Array(screenWidth * screenHeight * 4);
gl.readPixels(0, 0, screenWidth, screenHeight, gl.RGBA, gl.FLOAT, capturedImageData);
- 使用另一个 canvas 和
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, . . .
,这显然是不对的。
如果有人遇到过这个问题,将不胜感激。谢谢!
直接link程序是: https://www.khanacademy.org/cs/-/6289631977619456
出于某种原因 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>
您应该始终查看浏览器的 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 完成。应该使用允许您直接渲染到纹理的帧缓冲区来完成。