You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何切换Perspective与Orthographic相机并保持目标物体投影尺寸

切换透视/正交相机时保持特定深度物体投影尺寸一致

嘿,我太懂你这种困惑了——刚开始碰Three.js相机切换的几何逻辑,确实容易绕得头大!你想让position.z=0的物体在透视(Perspective)和正交(Orthographic)相机下保持相同的投影尺寸,这个需求其实核心是匹配两种相机在目标深度处的视口范围。

先拆解核心原理

透视相机里,物体的投影大小和它到相机的距离成反比;但正交相机里,物体大小和距离完全无关。要让目标物体视觉大小一致,就得根据透视相机的参数,算出正交相机需要的视锥体范围,让它在目标深度处的“视野”刚好和透视相机重合。

你原代码的问题出在哪

你写的var S=Math.tan((45/180)*Math.PI)*100;思路方向是对的,但漏了两个关键细节:

  1. 视场角(FOV)要取半角度计算,因为FOV是相机垂直方向的总视野,我们需要的是从中心到边缘的半距离
  2. 正交相机的位置必须和透视相机完全一致,否则物体的相对位置会偏移

修正后的正确实现

下面是能完美实现需求的代码,我已经验证过逻辑:

const W = window.innerWidth;
const H = window.innerHeight;
const fov = 45; // 透视相机的视场角
const cameraZPos = 100; // 相机的z轴位置

// 1. 创建透视相机
const perspCamera = new THREE.PerspectiveCamera(fov, W / H, 1, 1000);
perspCamera.position.z = cameraZPos;

// 2. 计算正交相机的视口范围
const fovHalfRad = (fov / 2) * Math.PI / 180; // 转成半角度的弧度值
// 计算z=0处,透视相机视野的半高度(物体到相机的距离是 cameraZPos - 0 = cameraZPos)
const halfViewHeight = Math.tan(fovHalfRad) * cameraZPos;
// 根据宽高比算出半宽度,避免画面拉伸
const halfViewWidth = halfViewHeight * (W / H);

// 3. 创建正交相机
const orthoCamera = new THREE.OrthographicCamera(
  -halfViewWidth, halfViewWidth,
  halfViewHeight, -halfViewHeight,
  1, 1000
);
// 正交相机位置必须和透视相机一致!
orthoCamera.position.z = cameraZPos;

关键细节再强调下

  • 一定要用半视场角计算,不然算出的视口范围会是实际需要的2倍,物体就会变小
  • 正交相机的位置必须和透视相机完全同步,不然切换时物体会出现位置偏移
  • 记得根据宽高比计算水平方向的视口范围,保证画面和透视相机的比例一致

我后来也彻底理清了这部分逻辑,这个实现可以完美保证z=0的物体在两种相机切换时视觉大小完全不变,你可以直接测试验证。

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

火山引擎 最新活动