ThreeJS 官方案例学习(webgl_camera_array)
1.效果图

2.源码
<template>
<div>
<div id="container"></div>
</div>
</template>
<script>
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { RoomEnvironment } from 'three/examples/jsm/environments/RoomEnvironment.js';
import Stats from 'three/examples/jsm/libs/stats.module.js';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'
import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js';
import gsap from 'gsap';
const AMOUNT = 6;
export default {
data() {
return {
container: null,
scene: null,
camera: null,
renderer: null,
controller: null,
stats: null,
mixer: null,
mesh: null,
clock: new THREE.Clock()
};
},
mounted() {
this.init()
this.animate()
window.addEventListener("resize", this.onWindowSize)
},
beforeUnmount() {
console.log('beforeUnmount===============');
this.container = null
this.scene = null
this.camera = null
this.renderer = null
this.controller = null
this.stats = null
this.mixer = null
this.mesh = null
},
methods: {
init() {
this.container = document.getElementById('container')
this.setScene()
this.setCamera()
this.setRenderer()
this.setController()
this.addHelper()
this.setLight()
this.setGltfLoader()
this.addStatus()
},
setScene() {
this.scene = new THREE.Scene()
this.scene.background = new THREE.Color(0xbfe3dd);
},
setCamera() {
const ASPECT_RATIO = this.container.clientWidth / this.container.clientHeight
const WIDTH = (this.container.clientWidth / AMOUNT) * window.devicePixelRatio;
const HEIGHT = (this.container.clientHeight / AMOUNT) * window.devicePixelRatio;
const cameras = [];
for (let y = 0; y < AMOUNT; y++) {
for (let x = 0; x < AMOUNT; x++) {
const subcamera = new THREE.PerspectiveCamera(40, ASPECT_RATIO, 0.1, 10)
subcamera.viewport = new THREE.Vector4(Math.floor(x * WIDTH), Math.floor(y * HEIGHT), Math.ceil(WIDTH), Math.ceil(HEIGHT));
subcamera.position.x = (x / AMOUNT) - 0.5;
subcamera.position.y = 0.5 - (y / AMOUNT);
subcamera.position.z = 1.5;
subcamera.position.multiplyScalar(2);
subcamera.lookAt(0, 0, 0);
subcamera.updateMatrixWorld();
cameras.push(subcamera);
}
}
this.camera = new THREE.ArrayCamera(cameras);
this.camera.position.z = 3;
},
setRenderer() {
this.renderer = new THREE.WebGLRenderer({
antialias: true,
logarithmicDepthBuffer: true,
})
this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);
this.renderer.setPixelRatio(window.devicePixelRatio);
this.renderer.shadowMap.enabled = true;
this.container.appendChild(this.renderer.domElement);
},
setController() {
this.controller = new OrbitControls(this.camera, this.renderer.domElement);
this.controller.enableDamping = true;
this.controller.dampingFactor = 0.04;
this.controller.target.set(0, 0.5, 0);
},
setGltfLoader() {
let that = this
const geometryBackground = new THREE.PlaneGeometry(100, 100);
const materialBackground = new THREE.MeshPhongMaterial({ color: 0x000066 });
const background = new THREE.Mesh(geometryBackground, materialBackground);
background.receiveShadow = true;
background.position.set(0, 0, - 1);
this.scene.add(background);
const geometryCylinder = new THREE.CylinderGeometry(0.5, 0.5, 1, 32);
const materialCylinder = new THREE.MeshPhongMaterial({ color: 0xff0000 });
this.mesh = new THREE.Mesh(geometryCylinder, materialCylinder);
this.mesh.castShadow = true;
this.mesh.receiveShadow = true;
this.scene.add(this.mesh);
},
addHelper() {
let helper = new THREE.CameraHelper(this.camera);
let axisHelper = new THREE.AxesHelper(150);
this.scene.add(axisHelper)
let gridHelper = new THREE.GridHelper(100, 30, 0x2C2C2C, 0x888888);
},
setPMREMGenerator() {
const pmremGenerator = new THREE.PMREMGenerator(this.renderer);
this.scene.environment = pmremGenerator.fromScene(new RoomEnvironment(this.renderer), 0.04).texture;
},
setLight() {
const ambientLight = new THREE.AmbientLight(0x999999, 1);
this.scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 3);
directionalLight.position.set(0.5, 0.5, 1);
directionalLight.castShadow = true;
directionalLight.shadow.camera.zoom = 4;
this.scene.add(directionalLight);
const test = new THREE.PointLight("#ffffff", 10, 2);
const testHelperMap = new THREE.PointLightHelper(test);
},
addStatus() {
this.stats = new Stats();
this.container.appendChild(this.stats.dom);
},
onWindowSize() {
const ASPECT_RATIO = this.container.clientWidth / this.container.clientHeight;
const WIDTH = (this.container.clientWidth / AMOUNT) * window.devicePixelRatio;
const HEIGHT = (this.container.clientHeight / AMOUNT) * window.devicePixelRatio;
this.camera.aspect = ASPECT_RATIO;
this.camera.updateProjectionMatrix();
for (let y = 0; y < AMOUNT; y++) {
for (let x = 0; x < AMOUNT; x++) {
const subcamera = this.camera.cameras[AMOUNT * y + x];
subcamera.viewport.set(
Math.floor(x * WIDTH),
Math.floor(y * HEIGHT),
Math.ceil(WIDTH),
Math.ceil(HEIGHT));
subcamera.aspect = ASPECT_RATIO;
subcamera.updateProjectionMatrix();
}
}
this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);
this.renderer.setPixelRatio(window.devicePixelRatio)
},
animate() {
this.mesh.rotation.x += 0.005;
this.mesh.rotation.z += 0.01;
const delta = this.clock.getDelta();
if (this.mixer) {
this.mixer.update(delta);
}
requestAnimationFrame(this.animate);
this.controller.update(delta);
this.stats.update();
this.renderer.render(this.scene, this.camera);
},
},
};
</script>
<style>
#container {
position: absolute;
width: 100%;
height: 100%;
}
</style>