Html5 canvas gl readPixels坐标系:读取并检查多个点

Html5 canvas gl readPixels坐标系:读取并检查多个点,html5-canvas,webgl,coordinate-systems,glreadpixels,Html5 Canvas,Webgl,Coordinate Systems,Glreadpixels,我需要从拾取缓冲区读取一块像素,以检查周围的点是否存在碰撞,如下图所示: 我在x,y,点击我的canvas,因此我定义了一个11x11像素的正方形区域,以cX,cY为中心,然后我从x1,y1开始一次读取拾取缓冲区: var w = 11, h = 11, cX = x, cY = cH - y, rc = ~~(0.5*w), x1 = cX - rc, y1 = cY + rc; gl.readPixels(x1, y1, w, h, gl.RGBA, gl.UNSIGNED_BYTE,

我需要从拾取缓冲区读取一块像素,以检查周围的点是否存在碰撞,如下图所示:

我在
x
y
,点击我的
canvas
,因此我定义了一个11x11像素的正方形区域,以
cX
cY
为中心,然后我从
x1
y1
开始一次读取拾取缓冲区:

var w = 11, h = 11, cX = x, cY = cH - y, rc = ~~(0.5*w), x1 = cX - rc, y1 = cY + rc;

gl.readPixels(x1, y1, w, h, gl.RGBA, gl.UNSIGNED_BYTE, pickBuf);
然后,我沿着红色箭头从缓冲区的中心向外部循环,同时检查拾取缓冲区内部是否有积极响应(发现碰撞):

函数readAt(i,pickBuf){
返回pickBuf[i]0;
/*左下角扇区*/
var r=l,c=l,p=r*w+c,i=4*p;
found=读取(i,pickBuf)>0;
/*右下角扇区*/
var r=l,c=rc+(rc-l),p=r*w+c,i=4*p;
found=读取(i,pickBuf)>0;
}
这段代码正在运行,我能够选择一个几何体,但现在我相信我还没有正确理解整个坐标系,因为碰撞结果总是在它应该位于的点的上方和左侧。为什么会发生这种情况

在我看来,
readPixels
应该读取从
画布的左下角开始到右上角的字节。是真的,还是我错过了什么

我知道,
gl
坐标系与我的
canvas
方向相反,因此我在
cY=cH-Y
处定义拾取缓冲区的中心,并在
y1=cY+rc
处定义拾取缓冲区的Y起点,但无论如何,这给了我错误的结果,在我从中心走到我的采摘方块外面。我对坐标系的解释哪里出错了

在我看来,readPixels应该从 画布的左下角到右上角。是吗 是真的,还是我错过了什么

那是真的

不管怎么说,这在我走路的时候给了我错误的结果

除了中间像素没有被检查之外,它对我来说是有效的,我怀疑问题出在代码的其他地方

//拾取
c、 addEventListener('click',函数(e){
变量
cX=e.offsetX,//x在画布中
cY=ctx.drawingBufferHeight-e.offsetY//y在画布内反转,drawingBufferHeight与画布高度相同
;
变量
面积=11,
半面积=(面积/2)| 0,
sX=cX半面积,
sY=cY半面积
;
控制台日志('从中拾取'、sX、sY、区域、区域);
//读取数据
var数据=新的UINT8阵列(面积*面积*4);
读取像素(sX,sY,area,area,ctx.RGBA,ctx.UNSIGNED_字节,数据);
//画十字
(功能(pickBuf、rc、w){
函数readAt(i,pickBuf){
返回pickBuf[i]=pickBuf[i+1]=pickBuf[i+2]=0;
}
//这是未修改的循环
var l=rc;
而(l--){
/*左上角扇区*/
var r=rc+(rc-l),c=l,p=r*w+c,i=4*p;
found=读取(i,pickBuf)>0;
/*右上角扇区*/
var r=rc+(rc-l),c=rc+(rc-l),p=r*w+c,i=4*p;
found=读取(i,pickBuf)>0;
/*左下角扇区*/
var r=l,c=l,p=r*w+c,i=4*p;
found=读取(i,pickBuf)>0;
/*右下角扇区*/
var r=l,c=rc+(rc-l),p=r*w+c,i=4*p;
found=读取(i,pickBuf)>0;
}
})(数据、半区域、区域);
//创建预览
var octx=document.createElement('canvas').getContext('2d');
octx.canvas.classList.add('preview');
octx.canvas.width=octx.canvas.height=area;
var idata=octx.createImageData(面积,面积);
idata.data.set(数据);
octx.putImageData(idata,0,0);
canvas.parentElement.insertBefore(octx.canvas,ctx.canvas);
});
//上下文设置
var ctx=c.getContext('webgl',{preserveDrawingBuffer:true});
ctx.canvas.width=ctx.canvas.height=256;
视区(0,0256256);
//着色器设置
var vs=ctx.createShader(ctx.VERTEX_着色器),fs=ctx.createShader(ctx.FRAGMENT_着色器),prg=ctx.createProgram();
ctx.shaderSource(vs`
属性向量2 vPos;
void main(){gl_Position=vec4(vPos,0,1);}
`);
ctx.shaderSource(fs`
高精度浮点;
void main(){
vec2p=(gl_FragCoord.xy/256.)*2.-1。;
gl_FragColor=vec4(符号(p),符号(-p.r),1);
}
`);
ctx.compileShader(vs);
ctx.compileShader(fs);
ctx.attachShader(prg,vs);
ctx.attachShader(prg,fs);
ctx.linkProgram(prg);
//屏幕空间设置
var ssq=ctx.createBuffer();
bindBuffer(ctx.ARRAY\u BUFFER,ssq);
ctx.bufferData(ctx.ARRAY_BUFFER,新Float32Array([-1,-1,1,-1,1]),ctx.STATIC_DRAW);
VertexAttributePointer(0,2,ctx.FLOAT,false,0,0);
ctx.EnableVertexAttributeArray(0);
//画
ctx.useProgram(prg);
ctx.牵引阵列(ctx.三角扇形,0,4)
h2{文本对齐:居中;字体系列:Arial,无衬线;}
#{显示:块;边距:0自动;轮廓:1px实心红色;光标:十字线;}
.预览{
宽度:64px;
高度:64px;
大纲:无;
显示:内联;
图像渲染:像素化;
变换:scaleY(-1);
利润率:10px;
}
单击2拾取

THX为方便起见,我省略了cX,cY的第一次检查。cX,cY的选择工作得很好,特别是在那里。老实说,我无法想象其他地方会出现这个问题,但我会进一步调查。我再也没有发现这个问题了,但无论如何,我真的很感激你的片段。
function readAt(i, pickBuf) {
    return pickBuf[i] << 16 | pickBuf[i+1] << 8 | pickBuf[i+2];
}

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;
}