我遵循 webgl 基础知识并绘制 2d 对象并使用矩阵缩放顶点和渲染。
在渲染之前,我传递设置为顶点的 width/height
来渲染四边形。这定义了对象的大小。但是在顶点着色器中,我像这样对这些顶点应用变换:
in vec2 aPosition;
in vec2 aTexCoord;
out vec2 vQuadCoord;
uniform mat3 uMatrix;
void main() {
vec2 position = (uMatrix * vec3(aPosition, 1)).xy;
vQuadCoord = aTexCoord;
gl_Position = vec4(position, 0, 1);
}
此矩阵控制对象的平移/旋转/缩放
。渲染后,我想知道这个对象的边界。但特别是在缩放之后我不知道界限。如果我在 x,y
处平移这个对象(带有矩阵),它的位置是已知的,但是如果我缩放这个对象,x 会向左移动,移动量未知。 webgl 基础知识没有提到这个主题,什么是检测对象边界和精确转换的好方法,因为我也有枢轴问题,我可能会问另一个问题。
最佳答案
您需要将鼠标坐标转换为裁剪空间,然后将它们乘以矩阵的逆矩阵。这将为您提供相对于 aPosition
值的鼠标坐标。
之后就看你的了。如果提供给 aPosition
的值(顶点)是一个矩形,那么您可以只检查该矩形的变换点。如果它们是更复杂的形状,如星形,那么您需要制作自己的函数来执行 point in star
或 point in triangle
并检查每个三 Angular 形,但至少转换后,鼠标位置位于相对于您的顶点的坐标中。您还可以在初始时间计算顶点的边界框,并使用它来测试变换后的点。
function main() {
const gl = document.querySelector('canvas').getContext('webgl2');
if (!gl) {
return alert('need WebGL2');
}
const vs = `#version 300 es
in vec2 aPosition;
uniform mat3 uMatrix;
void main() {
vec2 position = (uMatrix * vec3(aPosition, 1)).xy;
gl_Position = vec4(position, 0, 1);
}
`;
const fs = `#version 300 es
precision mediump float;
uniform vec4 color;
out vec4 outColor;
void main() {
outColor = color;
}
`;
const programInfo = twgl.createProgramInfo(gl, [vs, fs]);
// create a quad that starts at 0,0 and is 20 units wide and 10 tall
const bufferInfo = twgl.createBufferInfoFromArrays(gl, {
aPosition: {
numComponents: 2,
data: [
0, 0,
0, 10,
20, 0,
20, 0,
0, 10,
20, 10,
],
}
});
const vao = twgl.createVAOFromBufferInfo(gl, programInfo, bufferInfo);
let mouseClipX = 0;
let mouseClipY = 0;
const infoElem = document.querySelector('#info');
function render(time) {
t = time / 1000;
twgl.resizeCanvasToDisplaySize(gl.canvas);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.useProgram(programInfo.program);
gl.bindVertexArray(vao);
let mat = m3.projection(gl.canvas.width, gl.canvas.height);
mat = m3.translate(
mat,
150 + Math.sin(t * 0.1) * 100,
75 + Math.cos(t * 0.2) * 50);
mat = m3.rotate(mat, t * 0.3);
mat = m3.scale(
mat,
2 + Math.sin(t * 0.4) * 0.5,
2 + Math.cos(t * 0.5) * 0.5);
// convert clipspace mouse to aPosition relative values
// 'mat' takes aPosition and converts to clip space
// so the inverse of 'mat' would take clip space and
// convert back to aPosition space.
const invMat = m3.inverse(mat);
const p = m3.transformPoint(invMat, [mouseClipX, mouseClipY]);
// now check in aPosition space. It's a 20x10 rect starting at 0,0 so
const inbox = p[0] >= 0 && p[0] < 20 &&
p[1] >= 0 && p[1] < 10;
twgl.setUniforms(programInfo, {
uMatrix: mat,
color: inbox ? [1, 0, 0, 1] : [0, 0, 1, 1],
});
twgl.drawBufferInfo(gl, bufferInfo);
infoElem.textContent = inbox ? 'mouse in rect' : 'no hit';
requestAnimationFrame(render);
}
requestAnimationFrame(render);
gl.canvas.addEventListener('mousemove', (event) => {
// convert canvas relative mouse coordinates to clip space
mouseClipX = (event.offsetX / gl.canvas.clientWidth ) * 2 - 1;
mouseClipY = (event.offsetY / gl.canvas.clientHeight) * -2 + 1; // note we flip Y
});
}
main();
canvas { border: 1px solid black; }
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<script src="https://webgl2fundamentals.org/webgl/resources/m3.js"></script>
<canvas></canvas>
<pre id="info"></pre>
关于javascript - 如何在模型 View 转换后获取正在绘制的对象的二维尺寸以在 webgl 上进行 HitTest ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57697719/