Skip to content
Advertisement

readPixels from WebGL2RenderContext returns only black pixels

So there is a game online that uses WebGL2 and WebAssembly. My goal is to interact with the game by script. It uses pointers internally which makes it hard to read data from the game data. That’s why I decided to go over the UI using the WebGL context. I’m very new to WebGL, graphics and rendering in general and have no idea what I’m actually doing.

I’ve found the canvas and can execute methods on it. My first step is to take screenshots of areas using WebGL that I may use to analyze parts of the UI. For that I’m using WebGLRenderingContext#readPixels. Here’s a snippet reading the whole canvas and saving its’ pixels as RGBA:

const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("webgl2");
const pixels = new Uint8Array(ctx.drawingBufferWidth * ctx.drawingBufferHeight * 4);
ctx.readPixels(0, 0, ctx.drawingBufferWidth, ctx.drawingBufferHeight, ctx.RGBA, ctx.UNSIGNED_BYTE, pixels)
// Returns only black / white
pixels.findIndex(pixel => pixel !== 0 && pixel !== 255); // -1

So in this case, there are only black pixels, all 4-tuples equal (0,0,0,255). A method to draw those pixels in a temporary canvas and download its’ ImageData as png creates a black image.

What’s the reason behind this and how can I fix it?

Advertisement

Answer

For performance reasons the WebGl’s drawing buffer gets cleared after drawing. https://www.khronos.org/registry/webgl/specs/latest/1.0/#2.2

Any calls to readPixels() will just return empty data.

To keep it’s content you need to set the preserveDrawingBuffer flag to true wen getting the drawing context via the getContext(“webgl”) function.

So change this

const ctx = canvas.getContext("webgl2");

to

const ctx = canvas.getContext("webgl2", {preserveDrawingBuffer: true});
User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement