Three.js Raycasting坐标偏移:Shader红点与鼠标位置不匹配求助
问题分析与解决方案建议
核心排查方向
从红点偏移随滚动距离变化的特征来看,问题大概率出在屏幕坐标到Shader空间的转换环节,没有正确处理视图滚动、坐标原点差异或画布缩放适配。以下是具体排查点:
1. 鼠标坐标的原点匹配错误
浏览器鼠标坐标默认以页面左上角为原点,但Shader中纹理/模型空间通常以左下角为原点,这会直接导致Y轴方向的偏移。检查代码是否对鼠标Y坐标做了翻转处理:
// 错误:直接传入浏览器原始Y坐标 vec2 mouse = vec2(u_mouseX, u_mouseY); // 正确:基于画布高度翻转Y轴 vec2 mouse = vec2(u_mouseX, u_canvasHeight - u_mouseY);
2. 滚动偏移未做补偿
偏移随滚动距离变化,说明没有把页面滚动的scrollTop/scrollLeft纳入坐标计算。传递鼠标坐标前必须扣除滚动偏移:
const rect = canvas.getBoundingClientRect(); // 获取鼠标在画布内的相对坐标(已扣除滚动和边框偏移) const mouseX = event.clientX - rect.left; const mouseY = event.clientY - rect.top; // 将处理后的坐标传入Shader的uniform变量
3. 画布DPI与缩放适配缺失
如果页面存在缩放或未适配设备像素比(DPR),会导致坐标映射比例错误。确保传入Shader的坐标基于画布实际像素尺寸:
const dpr = window.devicePixelRatio || 1; const mouseX = (event.clientX - rect.left) * dpr; const mouseY = (event.clientY - rect.top) * dpr;
同时在Shader中归一化坐标时,要使用画布的实际像素宽高:
vec2 normalizedMouse = mouse / vec2(u_canvasWidth, u_canvasHeight);
4. 3D模型空间的坐标转换遗漏
如果是在3D模型表面绘制选中点,不能直接将屏幕坐标映射到模型UV,必须通过unproject方法将屏幕坐标转换为世界空间射线,再与模型求交得到表面坐标。
代码检查重点
对照你的实现,优先确认:
- 鼠标坐标是否扣除了页面滚动偏移和画布边框
- Shader中是否完成了鼠标坐标的原点翻转与归一化
- 画布实际像素尺寸与CSS显示尺寸是否一致,是否适配了DPR
内容的提问来源于stack exchange,提问作者Bn'R
相关产品推荐
相关产品推荐

