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

如何获取Three.js相机视场四角在y=0平面上的坐标?

获取透视相机视场角在y=0平面交点的实现方案

核心逻辑很简单:透视相机的视场边界是从相机位置出发、穿过视口四个角的四条射线,求这四条射线和y=0平面的交点,就是你要的区域四个角点。

实现步骤

  • 先确认相机初始化正确:设置好匹配窗口宽高比的aspect参数,将相机lookAt指向(0,0,0),渲染器尺寸铺满窗口,提前更新相机的投影矩阵和世界矩阵,避免拿未更新的矩阵计算出错。
  • 把NDC空间(标准化设备坐标)下的四个视口角点,反投影到世界空间,得到视锥体近裁剪面上的四个边界点。
  • 以相机位置为起点,穿过四个近面边界点生成四条射线,分别计算射线和y=0平面的交点,过滤掉相机背后的无效交点即可。

直接可用的代码

/**
 * 获取相机视场四个角在y=0平面的交点
 * @param {THREE.PerspectiveCamera} camera 已完成初始化的透视相机
 * @returns {THREE.Vector3[]} 按屏幕左下、右下、右上、左上顺序返回的四个交点坐标
 */
function getY0PlaneFrustumCorners(camera) {
  const intersections = [];
  // NDC空间视口四个角点,z=-1对应Three.js透视相机的近裁剪面
  const ndcCorners = [
    new THREE.Vector3(-1, -1, -1),
    new THREE.Vector3(1, -1, -1),
    new THREE.Vector3(1, 1, -1),
    new THREE.Vector3(-1, 1, -1)
  ];
  const rayOrigin = camera.position.clone();
  const TARGET_PLANE_Y = 0;

  ndcCorners.forEach(ndcPos => {
    // NDC坐标转世界坐标,得到视锥体近面上的边界点
    const worldBorderPoint = ndcPos.unproject(camera);
    // 计算射线方向
    const rayDir = worldBorderPoint.sub(rayOrigin).normalize();

    // 射线和平面平行(相机y坐标和平面齐平)时无有效交点,跳过
    if (Math.abs(rayDir.y) < 1e-6) return;
    // 计算射线到平面的参数t,t<0说明交点在相机背后,无效
    const t = (TARGET_PLANE_Y - rayOrigin.y) / rayDir.y;
    if (t < 0) return;

    // 计算最终交点
    const crossPoint = rayOrigin.clone().add(rayDir.multiplyScalar(t));
    intersections.push(crossPoint);
  });

  return intersections;
}

注意事项

  • 不要搞混坐标轴:y=0是XZ水平面,平面上的二维坐标对应交点的x和z属性,所有交点的y值固定为0,不要错拿y值当平面纵轴。
  • 返回的四个点顺序是屏幕顺时针从左下角开始的顺序,可以直接按这个顺序生成平面几何体或者判断模型是否在区域内。
  • 如果后续修改了相机fov、宽高比、位置,或者窗口触发了resize,记得重新调用函数计算交点,同时提前调用camera.updateProjectionMatrix()和camera.updateMatrixWorld()保证矩阵正确。
  • 如果你的相机本身y坐标为0,视场射线会和y=0平面平行,没有有效交点,这种情况需要调整相机位置高度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 01:45:44