Apbln
Apbln

Reputation: 177

How to use gl.readPixels to read drawn gl.POINTS with pointsize > 1?

My goal is to read pixels of a large point at the canvas. Currently I can't even get the pixels drawn at pointSize = 1. Here's a link: https://codepen.io/issabln/pen/LYEGWyO

the code snippet:

function drawOneBlackPixel( gl, x, y ) {
    // Fills the buffer with a single point?
    gl.bufferData( gl.ARRAY_BUFFER, new Float32Array([
      x,     y]), gl.STATIC_DRAW );

    // Draw one point.
    gl.drawArrays( gl.POINTS, 0, 1 );
}

gl.clearColor(1.0, 1.0, 1.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);

// These tests are supposed to be x,y coordinates from top left.
drawOneBlackPixel( gl, 1, 0 );

const pix = new Uint8Array(4);
gl.readPixels(1, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pix);
console.log(pix)

Any idea?

Upvotes: 1

Views: 181

Answers (2)

user128511
user128511

Reputation:

Let's try it

const gl = document.querySelector('canvas').getContext('webgl');
const vs = `
attribute vec4 position;
void main() {
  gl_Position = position;
  gl_PointSize = 1.0;
}
`;
const fs = `
precision mediump float;
uniform vec4 color;
void main() {
  gl_FragColor = color;
}
`;

const prg = twgl.createProgram(gl, [vs, fs]);
gl.useProgram(prg);
const posLoc = gl.getAttribLocation(prg, 'position');
const colorLoc = gl.getUniformLocation(prg, 'color');

function drawPixel(gl, px, py, color) {
  // compute center of pixel in clip space
  const clipX = (px + 0.5) / gl.canvas.width  * 2 - 1;
  const clipY = (py + 0.5) / gl.canvas.height * 2 - 1;
  gl.vertexAttrib2f(posLoc, clipX, clipY);
  gl.uniform4fv(colorLoc, color);
  gl.drawArrays(gl.POINTS, 0, 1);
}

function checkPixel(gl, px, py, expected, msg) {
  const pixel = new Uint8Array(4);
  gl.readPixels(px, py, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
  const actual = Array.from(pixel).map(v => v / 255);
  let same = true;
  for (let i = 0; same && i < 4; ++i) {
    same = actual[i] === expected[i];
  }
  if (same) {
    console.log(`pass: ${px},${py} was ${ actual.join(',')}`);
  } else {
    console.error(`fail: ${px},${py} was ${actual.join(',')} expected ${expected.join(',')}`);
  }
}

drawPixel(gl, 0, 0, [1, 0, 0, 1]);
drawPixel(gl, 299, 0, [0, 1, 0, 1]);
drawPixel(gl, 0, 149, [0, 0, 1, 1]);
drawPixel(gl, 299, 149, [0, 1, 1, 1]);

checkPixel(gl, 0, 0, [1, 0, 0, 1]);
checkPixel(gl, 299, 0, [0, 1, 0, 1]);
checkPixel(gl, 0, 149, [0, 0, 1, 1]);
checkPixel(gl, 299, 149, [0, 1, 1, 1]);
body { background: #444; }
<script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>
<canvas></canvas>

Upvotes: 1

LJᛃ
LJᛃ

Reputation: 8123

Flipping the Y coordinate does the trick(note the -1 otherwise you'd read outside the viewport)

gl.readPixels(1, gl.drawingBufferHeight-1, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pix);

Upvotes: 3

Related Questions