I have a three.js scene that is using ArrayCamera with 2 cameras. One is first-person, the other an aerial view. For the aerial view, I'm rendering 2 spheres but only one is visible. It seems anything with a position.z value greater than 0 doesn't render but I'm not sure why.
import * as THREE from "https://esm.sh/three";
// https://threejs.org/examples/#webgl_camera_array
const canvasWidth = window.innerWidth;
const canvasHeight = window.innerHeight;
const canvasPixelRatio = Math.min(window.devicePixelRatio, 2);
// Divide by 2 because each camera takes up half the viewport.
const cameraWidth = (window.innerWidth / 2) * window.devicePixelRatio;
const cameraHeight = window.innerHeight * window.devicePixelRatio;
const cameraAspectRatio = cameraWidth / cameraHeight;
const layout = document.querySelector("#myDiv");
// SCENE
const scene = new THREE.Scene();
// MESHES
const sphere1 = new THREE.Mesh(
new THREE.SphereGeometry(0.5),
new THREE.MeshBasicMaterial({ color: "white", wireframe: true })
);
sphere1.position.set(0, 0, -1);
scene.add(sphere1);
const sphere2 = new THREE.Mesh(
new THREE.SphereGeometry(0.5),
new THREE.MeshBasicMaterial({ color: "white", wireframe: true })
);
sphere2.position.set(0, 0, 1);
scene.add(sphere2);
// Ground plane
const meshPlane = new THREE.Mesh(
new THREE.PlaneGeometry(100, 100, 40, 40),
new THREE.MeshBasicMaterial({
color: "white",
wireframe: true
})
);
meshPlane.rotation.x = Math.PI / 2; // Rotate to lie flat
scene.add(meshPlane);
// First-person camera
const firstPersonCamera = new THREE.PerspectiveCamera(
75,
cameraAspectRatio,
0.1,
100
);
firstPersonCamera.position.set(0, 0, 5); // In front of cube
firstPersonCamera.lookAt(0, 0, -1); // Look forward
// Not sure what this is doing but without it, things break.
firstPersonCamera.updateMatrixWorld();
const aerialCamera = new THREE.OrthographicCamera(
cameraWidth / -2,
cameraWidth / 2,
cameraHeight / 2,
cameraHeight / -2,
0,
2000
);
aerialCamera.position.set(0, 1, 0); // Above origin
aerialCamera.lookAt(0, 0, 0); // Look down
aerialCamera.zoom = 40;
// Not sure what this is doing but without it, things break.
aerialCamera.updateMatrixWorld();
const cameras = new THREE.ArrayCamera([firstPersonCamera, aerialCamera]);
cameras.cameras[0].viewport = new THREE.Vector4(
0,
0,
cameraWidth,
cameraHeight
); // Left half
cameras.cameras[1].viewport = new THREE.Vector4(
cameraWidth,
0,
cameraWidth,
cameraHeight
); // Right half
// Must be called after any change of parameters.
cameras.cameras[0].updateProjectionMatrix();
cameras.cameras[1].updateProjectionMatrix();
const helper = new THREE.CameraHelper(cameras);
scene.add(helper);
// HELPERS
const axesHelper = new THREE.AxesHelper();
scene.add(axesHelper);
// RENDERER
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(canvasWidth, canvasHeight);
renderer.setPixelRatio(canvasPixelRatio);
layout.appendChild(renderer.domElement);
// ANIMATE
function onNewFrame() {
renderer.render(scene, cameras);
}
renderer.setAnimationLoop(onNewFrame);
