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>
运行代码后出现错误(错误截图:
)。此前已修正OrbitControls绑定的相机错误,但问题仍未解决,请问我的代码中遗漏了什么?
问题原因与修复方案
问题核心是ArrayCamera的子相机未设置视口(viewport),这是使用ArrayCamera的强制要求——渲染器需要明确每个子相机负责画布的哪个区域,否则会抛出错误。
修复步骤
- 为左右两个子相机分别设置视口:因为是VR分屏效果,每个相机占据画布宽度的一半、全屏高度。
- 修正子相机的
aspect比例:原本的宽高比是全屏比例,现在要改成半屏宽/全屏高。 - 添加窗口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
相关产品推荐
相关产品推荐

