多相机
同一份场景渲染四次:鸟瞰、正交俯视、平视与长焦特写,共用一块画布。
说明
四台相机共用同一条场景数据,只改变观察方式。
每台相机渲染前都要按自己的视口比例更新投影:
透视相机改 aspect,正交相机重设四个边界。
这一步漏掉时,画面会横向压扁。
左下角是平视视角,机位高度与人眼接近,能看到楼体的立面与遮挡关系; 右上角换成正交俯视,楼间距与路网位置最清楚,且没有近大远小。 两者的差别正是选择投影方式时最需要判断的地方。
| 视口 | 相机 | 设置 |
|---|---|---|
| 左上 | 透视 | 视野 45 度,机位 (58, 44, 62),可拖拽旋转 |
| 右上 | 正交 | 俯视,up 设为 (0, 0, −1),纵向可见 84 单位 |
| 左下 | 透视 | 视野 55 度,机位高度 7,平视 |
| 右下 | 透视 | 视野 22 度,长焦压缩空间 |
| 楼群 | — | 140 个立方体,高度按序号取模 |
| 参考物 | — | 160 单位网格与一根北向细柱 |
视口与裁剪矩形
renderer.setScissorTest(true);
function renderView(cam, x, y, w, h) {
renderer.setViewport(x, y, w, h);
renderer.setScissor(x, y, w, h);
if (cam.isOrthographicCamera) {
const halfH = 42;
const halfW = halfH * (w / h);
cam.left = -halfW;
cam.right = halfW;
cam.top = halfH;
cam.bottom = -halfH;
cam.updateProjectionMatrix();
} else {
cam.aspect = w / h;
cam.updateProjectionMatrix();
}
renderer.render(scene, cam);
}
setViewport 决定画在哪里,setScissor
决定哪块区域允许被写入,两者通常取相同的矩形。
坐标原点在画布左下角,Y 轴向上,这跟 CSS 相反,
所以「左上」的实际参数是 y = H / 2。
开启裁剪测试后,每次渲染的自动清屏也被限制在裁剪矩形内, 因此四个视口不会互相擦除背景。这也是必须两边都设置的原因。
交互挂在哪台相机上
OrbitControls 只绑定了一个相机与一个 DOM 元素,
拖拽会作用在整个画布上,但只有左上角的透视视图随之变化。
多视口若都要交互,需要按指针位置判断落在哪个象限,
再切换 controls.object,或为每个视口各建一套控制器。
单视口按钮把整块画布交给透视相机,并隐藏其余三个标签。 切换只改渲染调用,场景数据没有重建,所以没有额外开销。
正交相机的宽高比
正交相机没有 aspect 属性,比例完全由四个边界决定。
固定纵向范围、按宽高比推算横向范围的写法,
能保证不同视口尺寸下地物不被拉伸,方格仍是方格。
多相机不是多图层。四台相机看到的是同一份场景,
只是投影不同。要按图层分别控制可见性,应使用
Object3D.layers 或手动切换 visible,
three.js 不会因为相机不同而自动分区。