WebGL鼠标跟随圆形适配问题:跨设备及窗口Resize时定位异常
解决鼠标跟随圆形在不同分辨率/窗口Resize时的偏移问题
问题背景
实现了鼠标指针跟随圆形绘制功能,在1920×932的PC视口上显示正常,但在1280×593的笔记本视口上圆形无法精准跟随鼠标。硬编码视口尺寸为vec2(1920,932)时,笔记本上显示正常,但窗口Resize后偏移问题复现;PC端Resize时无异常。需要实现圆形在任意屏幕尺寸或窗口Resize时都能精准跟随鼠标。
问题根源
当前片段着色器中,宽高比校正逻辑存在错误:代码以鼠标点为原点对UV坐标进行缩放,导致坐标空间错位。当设备视口宽高比与硬编码值存在差异时,圆形就会偏离鼠标位置。
修正后的代码
export const fragment = ` varying vec2 vUv; uniform vec2 viewport; uniform vec2 uMouse; float createCircle() { // 将视口像素坐标转换为归一化UV(范围0-1) vec2 viewportUv = gl_FragCoord.xy / viewport; // 计算视口宽高比 float viewportAspect = viewport.x / viewport.y; // 翻转鼠标Y轴(适配WebGL坐标系,Y轴向下为正) vec2 mousePoint = vec2(uMouse.x, 1.0 - uMouse.y); // 计算等比例缩放因子,以较短边为基准保持坐标空间为正方形 vec2 center = vec2(0.5); // 将视口UV转换到无拉伸的等比例空间 vec2 normalizedViewportUv = (viewportUv - center) * vec2( viewportAspect < 1.0 ? viewportAspect : 1.0, viewportAspect > 1.0 ? 1.0 / viewportAspect : 1.0 ) + center; // 将鼠标坐标同步转换到同一等比例空间 vec2 normalizedMousePoint = (mousePoint - center) * vec2( viewportAspect < 1.0 ? viewportAspect : 1.0, viewportAspect > 1.0 ? 1.0 / viewportAspect : 1.0 ) + center; // 调试:标记鼠标位置(红色) if (length(normalizedViewportUv - normalizedMousePoint) < 0.01) { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } // 计算圆形半径:基于视口宽度保持固定像素大小 float circleRadius = max(0.0, 100.0 / viewport.x); // 计算当前像素到鼠标点的距离 float dist = distance(normalizedViewportUv, normalizedMousePoint); // 平滑过渡圆形边缘 dist = smoothstep(circleRadius, circleRadius + 0.001, dist); return dist; } void main() { float circle = createCircle(); // 绘制点精灵的圆形遮罩 float dist = length(gl_PointCoord - vec2(0.5)); float disc = smoothstep(0.5, 0.45, dist); gl_FragColor = vec4(disc * circle); // 剔除透明区域 if (disc < 0.01) discard; }`;
关键修正点
- 改用基于视口中心的等比例坐标转换,确保视口UV与鼠标坐标处于同一无拉伸的坐标空间,彻底解决宽高比差异导致的偏移。
- 同步对鼠标坐标和视口UV做相同的转换逻辑,保证两者相对位置始终一致。
- 保留原鼠标Y轴翻转逻辑(若CPU端已将鼠标坐标转换为WebGL坐标系,可移除
1.0 - uMouse.y)。 - 圆形半径计算逻辑保留,确保不同分辨率下圆形物理像素大小一致。
内容的提问来源于stack exchange,提问作者demo test
相关产品推荐
相关产品推荐

