ThreeJS 官方案例学习(webgl_camera_cinematic)
1.效果图
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/0cb8c527fba5495e8b02a235e90f093f.jpeg#pic_center)
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';
import { color } from 'd3';
import { CinematicCamera } from "three/examples/jsm/cameras/CinematicCamera.js";
const radius = 100;
export default {
data() {
return {
container: null,
scene: null,
camera: null,
renderer: null,
controller: null,
stats: null,
mixer: null,
model: null,
gui: null,
clock: new THREE.Clock(),
mouse: new THREE.Vector2(),
raycaster: null,
INTERSECTED: null,
theta: 0,
effectController: {
focalLength: 15,
fstop: 10,
showFocus: false,
focalDepth: 3,
}
};
},
mounted() {
this.raycaster = new THREE.Raycaster()
this.init()
this.animate()
window.addEventListener("resize", this.onWindowSize)
},
beforeUnmount() {
console.log('beforeUnmount===============');
this.scene.remove(this.camera)
cancelAnimationFrame(this.animate)
this.renderer.forceContextLoss()
this.renderer.dispose()
if (this.gui) {
this.gui.destroy()
this.gui = null
}
this.container = null
this.scene = null
this.camera = null
this.renderer = null
this.controller = null
this.stats = null
this.mixer = null
this.model = null
},
methods: {
init() {
this.container = document.getElementById('container')
this.setScene()
this.setCamera()
this.setRenderer()
this.setController()
this.setPMREMGenerator()
this.setLight()
this.addStatus()
this.addMesh()
this.matChanger()
this.setGui()
container.addEventListener("mousemove", this.onDocumentMouseMove);
},
setScene() {
this.scene = new THREE.Scene()
this.scene.background = new THREE.Color(0xbfe3dd);
},
setCamera() {
this.camera = new CinematicCamera(60, this.container.clientWidth / this.container.clientHeight, 1, 1000)
this.camera.position.set(2, 1, 500)
this.camera.aspect = this.container.clientWidth / this.container.clientHeight;
this.camera.updateProjectionMatrix();
this.camera.setLens(5);
this.scene.add(this.camera)
console.log('this.camera.postprocessing.bokeh_uniforms :>> ', this.camera, this.camera.postprocessing.bokeh_uniforms);
},
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.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);
},
addHelper() {
let helper = new THREE.CameraHelper(this.camera);
let axisHelper = new THREE.AxesHelper(1000);
this.scene.add(axisHelper)
let gridHelper = new THREE.GridHelper(1000, 30, 0x2C2C2C, 0x888888);
this.scene.add(gridHelper);
},
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(0xffffff, 1);
this.scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 1.0);
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() {
this.camera.aspect = this.container.clientWidth / this.container.clientHeight;
this.camera.updateProjectionMatrix();
this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);
this.renderer.setPixelRatio(window.devicePixelRatio)
},
onDocumentMouseMove(event) {
event.preventDefault();
this.mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
this.mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
},
addMesh() {
const geometry = new THREE.BoxGeometry(20, 20, 20)
for (let i = 0; i < 1500; i++) {
const object = new THREE.Mesh(
geometry,
new THREE.MeshLambertMaterial({ color: Math.random() * 0xffffff })
)
object.position.set(Math.random() * 800 - 400, Math.random() * 800 - 400, Math.random() * 800 - 400)
this.scene.add(object)
}
},
matChanger() {
for (const e in this.effectController) {
if (e in this.camera.postprocessing.bokeh_uniforms) {
this.camera.postprocessing.bokeh_uniforms[e].value =
this.effectController[e];
}
}
this.camera.postprocessing.bokeh_uniforms["znear"].value = this.camera.near;
this.camera.postprocessing.bokeh_uniforms["zfar"].value = this.camera.far;
this.camera.setLens(
this.effectController.focalLength,
this.camera.frameHeight,
this.effectController.fstop,
this.camera.coc
);
this.effectController["focalDepth"] =
this.camera.postprocessing.bokeh_uniforms["focalDepth"].value;
},
setGui() {
this.gui = new GUI()
this.gui.add(this.effectController, "focalLength", 1, 135, 0.01).onChange(this.matChanger)
this.gui.add(this.effectController, "fstop", 1.8, 22, 0.01).onChange(this.matChanger)
this.gui.add(this.effectController, "focalDepth", 0.1, 100, 0.001).onChange(this.matChanger)
this.gui.add(this.effectController, "showFocus", true).onChange(this.matChanger)
},
animate() {
this.theta += 0.1;
this.camera.position.x = radius * Math.sin(THREE.MathUtils.degToRad(this.theta));
this.camera.position.y = radius * Math.sin(THREE.MathUtils.degToRad(this.theta));
this.camera.position.z = radius * Math.cos(THREE.MathUtils.degToRad(this.theta));
this.camera.lookAt(this.scene.position);
this.camera.updateMatrixWorld();
const delta = this.clock.getDelta();
if (this.mixer) {
this.mixer.update(delta);
}
requestAnimationFrame(this.animate);
this.controller.update(delta);
this.stats.update();
this.raycaster.setFromCamera(this.mouse, this.camera);
const intersects = this.raycaster.intersectObjects(this.scene.children);
if (intersects.length > 0) {
const targetDistance = intersects[0].distance;
this.camera.focusAt(targetDistance);
if (this.INTERSECTED != intersects[0].object) {
if (this.INTERSECTED) { this.INTERSECTED.material.emissive.setHex(this.INTERSECTED.currentHex); }
this.INTERSECTED = intersects[0].object;
this.INTERSECTED.currentHex = this.INTERSECTED.material.emissive.getHex();
this.INTERSECTED.material.emissive.setHex(0xff0000);
}
} else {
if (this.INTERSECTED) { this.INTERSECTED.material.emissive.setHex(this.INTERSECTED.currentHex); }
this.INTERSECTED = null;
}
if (this.camera.postprocessing.enabled) {
this.camera.renderCinematic(this.scene, this.renderer);
} else {
this.scene.overrideMaterial = null;
this.renderer.clear();
this.renderer.render(this.scene, this.camera);
}
},
},
};
</script>
<style>
#container {
position: absolute;
width: 100%;
height: 100%;
}
</style>