// picking
c.addEventListener('click',function (e) {
var
cX = e.offsetX, // x within canvas
cY = ctx.drawingBufferHeight - e.offsetY // y within canvas inverted, drawingbufferheight is same as canvas height
;
var
area = 11,
halfArea = (area/2)|0,
sX = cX-halfArea,
sY = cY-halfArea
;
console.log('Picking from ', sX, sY, area,area);
// read data
var data = new Uint8Array(area*area*4);
ctx.readPixels(sX,sY,area,area,ctx.RGBA,ctx.UNSIGNED_BYTE,data);
// draw cross
(function (pickBuf,rc,w) {
function readAt(i, pickBuf) {
return pickBuf[i]=pickBuf[i+1]=pickBuf[i+2]=0;
}
// this is your unmodified loop
var l = rc;
while(l--) {
/* Top-Left sector */
var r = rc+(rc-l), c = l, p = r*w + c, i = 4*p;
found = readAt(i, pickBuf) > 0;
/* Top-Right sector */
var r = rc+(rc-l), c = rc+(rc-l), p = r*w + c, i = 4*p;
found = readAt(i, pickBuf) > 0;
/* Bottom-Left sector */
var r = l, c = l, p = r*w + c, i = 4*p;
found = readAt(i, pickBuf) > 0;
/* Bottom-Right sector */
var r = l, c = rc+(rc-l), p = r*w + c, i = 4*p;
found = readAt(i, pickBuf) > 0;
}
})(data,halfArea,area);
// create preview
var octx = document.createElement('canvas').getContext('2d');
octx.canvas.classList.add('preview');
octx.canvas.width = octx.canvas.height = area;
var idata = octx.createImageData(area,area);
idata.data.set(data);
octx.putImageData(idata,0,0);
ctx.canvas.parentElement.insertBefore(octx.canvas,ctx.canvas);
});
// context setup
var ctx = c.getContext('webgl',{preserveDrawingBuffer:true});
ctx.canvas.width = ctx.canvas.height = 256;
ctx.viewport(0,0,256,256);
// shader setup
var vs=ctx.createShader(ctx.VERTEX_SHADER),fs=ctx.createShader(ctx.FRAGMENT_SHADER),prg=ctx.createProgram();
ctx.shaderSource(vs,`
attribute vec2 vPos;
void main(){gl_Position=vec4(vPos,0,1);}
`);
ctx.shaderSource(fs,`
precision highp float;
void main(){
vec2 p=(gl_FragCoord.xy/256.)*2.-1.;
gl_FragColor=vec4(sign(p),sign(-p.r),1);
}
`);
ctx.compileShader(vs);
ctx.compileShader(fs);
ctx.attachShader(prg,vs);
ctx.attachShader(prg,fs);
ctx.linkProgram(prg);
// screenspace setup
var ssq = ctx.createBuffer();
ctx.bindBuffer(ctx.ARRAY_BUFFER,ssq);
ctx.bufferData(ctx.ARRAY_BUFFER,new Float32Array([-1,-1,1,-1,1,1,-1,1]),ctx.STATIC_DRAW);
ctx.vertexAttribPointer(0,2,ctx.FLOAT,false,0,0);
ctx.enableVertexAttribArray(0);
// draw
ctx.useProgram(prg);
ctx.drawArrays(ctx.TRIANGLE_FAN,0,4);
h2{text-align:center;font-family: Arial,sans-serif;}
#c{display:block;margin:0 auto;outline:1px solid red;cursor:crosshair;}
.preview {
width: 64px;
height: 64px;
outline: none;
display:inline;
image-rendering: pixelated;
transform:scaleY(-1);
margin: 10px;
}
<h2>Click 2 Pick</h2>
<canvas id="c"></canvas>