You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ray picking光线拾取原点异常 近平面物体无法拾取求解

Ray Picking光线拾取近平面物体无法命中问题修复

问题现象

  • 实现光线拾取算法时,生成的射线方向可对准光标方位,原点位于相机位置,但无法拾取靠近近裁剪平面的物体
  • 异常效果可视化:
    光线拾取异常运行效果

图中鼠标位置处于生成的白色射线远端,近裁剪面附近物体无法与射线产生碰撞
实现约定坐标系规则:鼠标坐标(0, 0)对应屏幕左下角位置
原实现伪代码如下:

mouse_x, mouse_y := get_mouse_pointer_position();

ndc := make_vector2(2.0 * mouse_x / window.width - 1, 2.0 * mouse_y / window.height - 1);
hcc := make_vector4(ndc.x, ndc.y, 1, 1);
projection := perspective(1.0, window.height / window.width, 500, 0.01);
projection_inv := inverse(projection);
ecc := projection_inv * hcc;

view := look_at_matrix(scene.camera_pos, scene.camera_target);
view_inv := inverse(view);
ray := normalize((view_inv * ecc).xyz);

return Ray(camera_pos, ray);

核心错误点

  • 透视投影逆变换后未做透视除法:裁剪空间坐标经过逆投影矩阵变换到观察空间后,必须将坐标分量除以自身的w分量完成透视还原,原代码直接将裁剪空间w设为1跳过该步骤,得到的观察空间坐标存在透视偏差,近裁剪面区域的射线方向偏移量完全错误
  • 透视矩阵宽高比参数写反:perspective函数的宽高比参数应为「窗口宽度/窗口高度」,原代码传入的是高宽比,会导致射线横向/纵向缩放比例错误
  • 单端点计算射线逻辑存在缺陷:仅取远裁剪面单个点计算方向,没有校验近裁剪面端点位置,容易因矩阵计算误差导致近段射线偏移

修正后实现

mouse_x, mouse_y := get_mouse_pointer_position();

// NDC坐标计算逻辑保持正确
ndc_x := 2.0 * mouse_x / window.width - 1.0;
ndc_y := 2.0 * mouse_y / window.height - 1.0;

// 修正透视矩阵参数:宽高比改为宽/高,匹配绝大多数图形API的perspective函数参数顺序(近平面参数在前,远平面在后)
projection := perspective(1.0, window.width / window.height, 0.01, 500.0);
projection_inv := inverse(projection);
view := look_at_matrix(scene.camera_pos, scene.camera_target);
view_inv := inverse(view);

// 计算近裁剪面上光标对应点的世界坐标
near_hcc := make_vector4(ndc_x, ndc_y, -1.0, 1.0);
near_ecc := projection_inv * near_hcc;
near_ecc := near_ecc / near_ecc.w; // 必须执行透视除法
near_world := (view_inv * near_ecc).xyz;

// 计算远裁剪面上光标对应点的世界坐标
far_hcc := make_vector4(ndc_x, ndc_y, 1.0, 1.0);
far_ecc := projection_inv * far_hcc;
far_ecc := far_ecc / far_ecc.w; // 必须执行透视除法
far_world := (view_inv * far_ecc).xyz;

// 射线方向为近点指向远点,归一化处理
ray_dir := normalize(far_world - near_world);

// 射线原点取近裁剪面点可避免近平面碰撞的精度误差,需要原点在相机位置直接替换为scene.camera_pos即可
return Ray(near_world, ray_dir);

修正后射线会完整覆盖光标从近裁剪面到远裁剪面的全部路径,近平面物体可正常被拾取。调整hcc的z值无效的核心原因就是没有做透视除法,z值的影响会被错误的w分量缩放抵消。

内容的提问来源于stack exchange,提问作者Tackwin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 20:15:39