I am working on a Chrome Extension that reads the image of a WebGL canvas on a specific site and checks the pixel color value of a couple certain locations. The issue I ran into however was the readPixels() function returning all 0's. I've tried adding the {preserveDrawingBuffer: true}
tag, and creating a framebuffer (I think?) and neither of my implementations for either solution have worked. Here is my code. I know there is a way to take a screenshot of the entire webstite viewport, but for sake of simplicity and compatibility, it would be far easier to just find the specific canvas.
async function getData(){ // this function is run on even keyup or keydown and executes properly
console.log("getData function")
const queue = document.getElementById("queueCanvas");
console.log(queue);
// pixel locations |v|
// 35,60 // 35,160 // 35,200 // 35,275 // 35,350
var gl = queue.getContext("webgl", {preserveDrawingBuffer: true});
// debug
gl.viewport(0, 0, queue.width, queue.height);
gl.clearColor(0, 0, 0.5, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
// debug (turn tha canvas background blue so that even if I search the wrong location, it should still give me a blue pixel
var fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.drawingBufferWidth, gl.drawingBufferHeight, 0 , gl.RGB, gl.UNSIGNED_BYTE, null);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
console.log(gl)
var pixels = new Uint8Array(
4 * gl.drawingBufferWidth * gl.drawingBufferHeight
);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
gl.readPixels(
0,
0,
gl.drawingBufferWidth,
gl.drawingBufferHeight,
gl.RGB,
gl.UNSIGNED_BYTE,
pixels
);
console.log(pixels); // 0 0 0 0 0 ...
var x = 35;
var y = 60;
var pixelR = pixels[4 * (y * gl.drawingBufferWidth + x)];
var pixelG = pixels[4 * (y * gl.drawingBufferWidth + x) + 1];
var pixelB = pixels[4 * (y * gl.drawingBufferWidth + x) + 2];
console.log("pixel color " + pixelR+", "+pixelG+", "+pixelB); // 0,0,0
}
I have looked at stack overflow and found a couple results that did not work for me, and found a Google WebGL Dev Team forum post that also did not work. I concede however that these solutions may have been correct, but my implementations of said solutions are incorrect. Here are the three resources. Get Color at position Webgl readPixels returns all zero webgl readpixels is always returning 0,0,0,0. It is important to note that the canvas is not mine, and I am not sure if its possible to access the canvas rendering code.
Additional semi-relevant info: The website in question is Jstris, and I am trying to access the queue of upcoming peices to analyze the best possible opener given the opening bag.
I will gladly follow up with any more information on the problem that you would need. Thank you for your time.
I tried to replicate your example and the one thing that appears incorrect is the pixel format gl.RGB
in gl.readPixels
. When I use gl.RGB
in my example I get [0, 0, 0, 0] values, but when I use gl.RGBA
I get the correct value. Could this be the issue?
<!DOCTYPE html>
<html>
<head></head>
<body>
<canvas></canvas>
</body>
<script>
const canvas = document.querySelector('canvas');
const gl1 = canvas.getContext('webgl');
const gl2 = canvas.getContext('webgl');
gl1.clearColor(1, 0, 0, 1);
gl1.clear(gl1.COLOR_BUFFER_BIT);
const out1 = new Uint8Array(4);
const out2 = new Uint8Array(4);
gl1.readPixels(0, 0, 1, 1, gl1.RGB, gl1.UNSIGNED_BYTE, out1);
gl2.readPixels(0, 0, 1, 1, gl2.RGBA, gl2.UNSIGNED_BYTE, out2);
console.log(out1); // [ 0, 0, 0, 0]
console.log(out2); // [255, 0, 0, 255]
</script>
</html>