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

Three.js问题:使用ArrayCamera时渲染器无法正常工作

问题描述

我在HTML中编写了如下代码:

<script type="module">
  import * as THREE from "https://cdn.jsdelivr.net/npm/three@0.121.1/build/three.module.js";
  import { OrbitControls } from "https://cdn.jsdelivr.net/npm/three@0.121.1/examples/jsm/controls/OrbitControls.js";

  const renderer = new THREE.WebGLRenderer();
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  const scene = new THREE.Scene();
  const cameraR = new THREE.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
  );
  const cameraL = new THREE.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
  );
  
  const axesHelper = new THREE.AxesHelper( 5 );
  scene.add( axesHelper );

  const geometry = new THREE.BoxBufferGeometry(1, 1, 1);
  const material = new THREE.MeshNormalMaterial();
  const cube = new THREE.Mesh(geometry, material);
  scene.add(cube);

  cameraR.position.x = 0.5;
  cameraR.position.z = 5;
  cameraL.position.x = -0.5;
  cameraL.position.z = 5;
  
  var cameras = [];
  cameras.push(cameraL)
  cameras.push(cameraR)     
  var cameraVR = new THREE.ArrayCamera( cameras );
  cameraVR.position.set( 0, 0, 5 );

  const controls = new OrbitControls(cameraVR, 
        renderer.domElement);
  controls.update();

  (function animate() {
    requestAnimationFrame(animate);
    
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;

    controls.update();
    renderer.render(scene, cameraVR);
  })();
</script>

运行代码后出现错误(错误截图:Three.js ArrayCamera错误)。此前已修正OrbitControls绑定的相机错误,但问题仍未解决,请问我的代码中遗漏了什么?

问题原因与修复方案

问题核心是ArrayCamera的子相机未设置视口(viewport),这是使用ArrayCamera的强制要求——渲染器需要明确每个子相机负责画布的哪个区域,否则会抛出错误。

修复步骤

  1. 为左右两个子相机分别设置视口:因为是VR分屏效果,每个相机占据画布宽度的一半、全屏高度。
  2. 修正子相机的aspect比例:原本的宽高比是全屏比例,现在要改成半屏宽/全屏高。
  3. 添加窗口resize监听,避免窗口大小变化后视口和投影矩阵错位。

完整修复代码

<script type="module">
  import * as THREE from "https://cdn.jsdelivr.net/npm/three@0.121.1/build/three.module.js";
  import { OrbitControls } from "https://cdn.jsdelivr.net/npm/three@0.121.1/examples/jsm/controls/OrbitControls.js";

  const renderer = new THREE.WebGLRenderer();
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  const scene = new THREE.Scene();
  // 修正子相机的aspect比例为半屏宽/全屏高
  const cameraR = new THREE.PerspectiveCamera(
    75,
    (window.innerWidth / 2) / window.innerHeight,
    0.1,
    1000
  );
  const cameraL = new THREE.PerspectiveCamera(
    75,
    (window.innerWidth / 2) / window.innerHeight,
    0.1,
    1000
  );
  
  const axesHelper = new THREE.AxesHelper( 5 );
  scene.add( axesHelper );

  const geometry = new THREE.BoxBufferGeometry(1, 1, 1);
  const material = new THREE.MeshNormalMaterial();
  const cube = new THREE.Mesh(geometry, material);
  scene.add(cube);

  cameraR.position.x = 0.5;
  cameraR.position.z = 5;
  cameraL.position.x = -0.5;
  cameraL.position.z = 5;

  // 为子相机设置视口
  const widthHalf = window.innerWidth / 2;
  const heightFull = window.innerHeight;
  cameraL.viewport = new THREE.Vector4(0, 0, widthHalf, heightFull);
  cameraR.viewport = new THREE.Vector4(widthHalf, 0, widthHalf, heightFull);
  
  var cameras = [];
  cameras.push(cameraL)
  cameras.push(cameraR)     
  var cameraVR = new THREE.ArrayCamera( cameras );
  cameraVR.position.set( 0, 0, 5 );

  const controls = new OrbitControls(cameraVR, renderer.domElement);
  controls.update();

  // 窗口resize监听,同步更新视口和投影矩阵
  window.addEventListener('resize', () => {
    const width = window.innerWidth;
    const height = window.innerHeight;
    const widthHalf = width / 2;

    renderer.setSize(width, height);
    
    cameraL.aspect = widthHalf / height;
    cameraL.updateProjectionMatrix();
    cameraL.viewport.set(0, 0, widthHalf, height);

    cameraR.aspect = widthHalf / height;
    cameraR.updateProjectionMatrix();
    cameraR.viewport.set(widthHalf, 0, widthHalf, height);

    cameraVR.aspect = width / height;
    cameraVR.updateProjectionMatrix();
  });

  (function animate() {
    requestAnimationFrame(animate);
    
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;

    controls.update();
    renderer.render(scene, cameraVR);
  })();
</script>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 11:20:38