获取碰撞检测点的大小
Getting size of point for collision detection
如果我的术语有误,请原谅我,但我只是想在 WebGL 中做一些简单的点碰撞检测。我有一堆 gl.POINTS
漂浮在 canvas 周围(640x480,设置为 HTML 属性),我在我的顶点着色器中设置了 gl_PointSize = 10.0
,并且正在尝试转换这到正确的坐标系。
我只是想根据每个渲染点的四个角进行一些基本的碰撞检测(假设我已经增加了它们的大小来表示一个正方形,只是为了让这些点相互反弹)。
我遇到的问题是我似乎无法理解如何计算它们的确切大小。我有它们的顶点位置,我想我可以简单地在 canvas 大小、点大小和 [-1, 1].
的 WebGL 坐标之间进行归一化
基本上,有没有'simple'方法来计算点的精确大小?
一个点的大小是它的中心 +/- 它大小的一半
+-[canvas]-----------------------+
| |
| |
| |
| +---+ |
| | + | |
| +---+ |
| |
+--------------------------------+
在上面的示例中 canvas 32x7
该点的中心位于 4x2 像素处。它的 gl_PointSize
是 3。它的剪辑 space 位置是
cx = px / canvasWidth * 2 - 1
cx = 4 / 32 * 2 - 1 = -0.75
cy = py / canvasHeight * 2 - 1
cy = 2 / 7 * 2 - 1 = -0.43
其剪辑space宽高为
clipWidth = gl_PointSize / canvasWidth
clipHeight = gl_PointSize / canvasHeight
还要记住 WebGL 中的 +Y
const gl = document.querySelector('canvas').getContext('webgl');
const vs =`
attribute vec4 position;
attribute float pointSize;
attribute vec4 color;
varying vec4 v_color;
void main() {
gl_Position = position;
gl_PointSize = pointSize;
v_color = color;
}
`;
const fs = `
precision mediump float;
varying vec4 v_color;
void main() {
gl_FragColor = v_color;
}
`;
const prg = twgl.createProgram(gl, [vs, fs]);
const posLoc = gl.getAttribLocation(prg, 'position');
const sizeLoc = gl.getAttribLocation(prg, 'pointSize');
const colorLoc = gl.getAttribLocation(prg, 'color');
const numPoints = 12;
const points = [];
for (let i = 0; i < numPoints; ++i) {
points.push({
x: r(-1, 1),
y: r(-1, 1),
color: [0, r(0, 1), r(0, 1), 1],
size: r(15, 55),
});
}
function r(min, max) {
return Math.random() * (max - min) + min;
}
let px = -10;
let py = -10;
function render() {
gl.useProgram(prg);
// convert mouse to clipspace
const cx = px / gl.canvas.width * 2 - 1;
const cy = py / gl.canvas.height * -2 + 1;
for (const point of points) {
const {x, y, color, size} = point;
// size to clip size
const halfClipWidth = size / gl.canvas.width;
const halfClipHeight = size / gl.canvas.height;
const left = x - halfClipWidth;
const right = x + halfClipWidth;
const top = y + halfClipHeight;
const bottom = y - halfClipHeight;
const hit = cx >= left && cx <= right &&
cy >= bottom && cy <= top;
gl.vertexAttrib2f(posLoc, x, y);
gl.vertexAttrib1f(sizeLoc, size);
gl.vertexAttrib4fv(colorLoc, hit ? [1, 0, 0, 1] : color);
gl.drawArrays(gl.POINTS, 0, 1);
}
}
render();
gl.canvas.addEventListener('mousemove', (e) => {
const rect = gl.canvas.getBoundingClientRect();
px = (e.clientX - rect.left) * gl.canvas.width / gl.canvas.clientWidth;
py = (e.clientY - rect.top) * gl.canvas.height / gl.canvas.clientHeight;
render();
});
body { margin: 40px; }
canvas { border: 1px solid black; }
<canvas></canvas>
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
另请记住,WebGL 中的位置是边缘而不是像素。如果你有一个 2x2 canvas 剪辑 space 中左下角像素的中心是 -0.5,-0.5
-1 0 1
| | |
+---+---+-- 1
| | |
| | |
| | |
+---+---+-- 0
| | |
| + | | <--- you can see the center of that pixel is at -0.5, -0.5
| | |
+---+---+-- -1
在像素 space 中,相同的 canvas 将是
0 1 2
| | |
+---+---+-- 2
| | |
| | |
| | |
+---+---+-- 1
| | |
| + | | <--- you can see the center of that pixel is at 0.5, 0.5
| | |
+---+---+-- 0
gl.POINTS
以像素 space 中的点为中心,加上 +/- gl_PointSize / 2 以形成一个矩形。中心位于该矩形内的任何像素都将被渲染(或者更确切地说考虑渲染给定所有其他测试 depth/stencil/discard,等等...)
如果我的术语有误,请原谅我,但我只是想在 WebGL 中做一些简单的点碰撞检测。我有一堆 gl.POINTS
漂浮在 canvas 周围(640x480,设置为 HTML 属性),我在我的顶点着色器中设置了 gl_PointSize = 10.0
,并且正在尝试转换这到正确的坐标系。
我只是想根据每个渲染点的四个角进行一些基本的碰撞检测(假设我已经增加了它们的大小来表示一个正方形,只是为了让这些点相互反弹)。
我遇到的问题是我似乎无法理解如何计算它们的确切大小。我有它们的顶点位置,我想我可以简单地在 canvas 大小、点大小和 [-1, 1].
的 WebGL 坐标之间进行归一化基本上,有没有'simple'方法来计算点的精确大小?
一个点的大小是它的中心 +/- 它大小的一半
+-[canvas]-----------------------+
| |
| |
| |
| +---+ |
| | + | |
| +---+ |
| |
+--------------------------------+
在上面的示例中 canvas 32x7
该点的中心位于 4x2 像素处。它的 gl_PointSize
是 3。它的剪辑 space 位置是
cx = px / canvasWidth * 2 - 1
cx = 4 / 32 * 2 - 1 = -0.75
cy = py / canvasHeight * 2 - 1
cy = 2 / 7 * 2 - 1 = -0.43
其剪辑space宽高为
clipWidth = gl_PointSize / canvasWidth
clipHeight = gl_PointSize / canvasHeight
还要记住 WebGL 中的 +Y
const gl = document.querySelector('canvas').getContext('webgl');
const vs =`
attribute vec4 position;
attribute float pointSize;
attribute vec4 color;
varying vec4 v_color;
void main() {
gl_Position = position;
gl_PointSize = pointSize;
v_color = color;
}
`;
const fs = `
precision mediump float;
varying vec4 v_color;
void main() {
gl_FragColor = v_color;
}
`;
const prg = twgl.createProgram(gl, [vs, fs]);
const posLoc = gl.getAttribLocation(prg, 'position');
const sizeLoc = gl.getAttribLocation(prg, 'pointSize');
const colorLoc = gl.getAttribLocation(prg, 'color');
const numPoints = 12;
const points = [];
for (let i = 0; i < numPoints; ++i) {
points.push({
x: r(-1, 1),
y: r(-1, 1),
color: [0, r(0, 1), r(0, 1), 1],
size: r(15, 55),
});
}
function r(min, max) {
return Math.random() * (max - min) + min;
}
let px = -10;
let py = -10;
function render() {
gl.useProgram(prg);
// convert mouse to clipspace
const cx = px / gl.canvas.width * 2 - 1;
const cy = py / gl.canvas.height * -2 + 1;
for (const point of points) {
const {x, y, color, size} = point;
// size to clip size
const halfClipWidth = size / gl.canvas.width;
const halfClipHeight = size / gl.canvas.height;
const left = x - halfClipWidth;
const right = x + halfClipWidth;
const top = y + halfClipHeight;
const bottom = y - halfClipHeight;
const hit = cx >= left && cx <= right &&
cy >= bottom && cy <= top;
gl.vertexAttrib2f(posLoc, x, y);
gl.vertexAttrib1f(sizeLoc, size);
gl.vertexAttrib4fv(colorLoc, hit ? [1, 0, 0, 1] : color);
gl.drawArrays(gl.POINTS, 0, 1);
}
}
render();
gl.canvas.addEventListener('mousemove', (e) => {
const rect = gl.canvas.getBoundingClientRect();
px = (e.clientX - rect.left) * gl.canvas.width / gl.canvas.clientWidth;
py = (e.clientY - rect.top) * gl.canvas.height / gl.canvas.clientHeight;
render();
});
body { margin: 40px; }
canvas { border: 1px solid black; }
<canvas></canvas>
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
另请记住,WebGL 中的位置是边缘而不是像素。如果你有一个 2x2 canvas 剪辑 space 中左下角像素的中心是 -0.5,-0.5
-1 0 1
| | |
+---+---+-- 1
| | |
| | |
| | |
+---+---+-- 0
| | |
| + | | <--- you can see the center of that pixel is at -0.5, -0.5
| | |
+---+---+-- -1
在像素 space 中,相同的 canvas 将是
0 1 2
| | |
+---+---+-- 2
| | |
| | |
| | |
+---+---+-- 1
| | |
| + | | <--- you can see the center of that pixel is at 0.5, 0.5
| | |
+---+---+-- 0
gl.POINTS
以像素 space 中的点为中心,加上 +/- gl_PointSize / 2 以形成一个矩形。中心位于该矩形内的任何像素都将被渲染(或者更确切地说考虑渲染给定所有其他测试 depth/stencil/discard,等等...)