ThreeJS 官方案例学习(webgl_clipping)
1.效果图
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/d5a19c85e340454594dd7c6c45aca3f4.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';
export default {
data() {
return {
container: null,
scene: null,
camera: null,
renderer: null,
controller: null,
stats: null,
model: null,
clock: new THREE.Clock(),
startTime: null,
};
},
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.object = null
},
methods: {
init() {
this.container = document.getElementById('container')
this.startTime = Date.now();
this.setScene()
this.setCamera()
this.setRenderer()
this.setController()
this.addHelper()
this.setLight()
this.setMesh()
this.addStatus()
},
setScene() {
this.scene = new THREE.Scene()
},
setCamera() {
this.camera = new THREE.PerspectiveCamera(20, this.container.clientWidth / this.container.clientHeight, 0.01, 100)
this.camera.position.set(5, 2, 8)
this.camera.aspect = this.container.clientWidth / this.container.clientHeight;
this.camera.updateProjectionMatrix();
this.camera.lookAt(new THREE.Vector3(0, 0, 0))
this.scene.add(this.camera)
},
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.renderer.localClippingEnabled = true;
this.renderer.sortObjects = false;
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, 1, 0);
},
setMesh() {
const localPlane = new THREE.Plane(new THREE.Vector3(0, - 1, 0), 0.8);
const material = new THREE.MeshPhongMaterial({
color: 0x80ee10,
shininess: 100,
side: THREE.DoubleSide,
clippingPlanes: [localPlane],
clipShadows: true,
})
const geometry = new THREE.TorusKnotGeometry(0.4, 0.08, 95, 20);
this.object = new THREE.Mesh(geometry, material);
this.object.castShadow = true;
this.object.position.y = 0.8;
this.scene.add(this.object);
const ground = new THREE.Mesh(
new THREE.PlaneGeometry(9, 9, 1, 1),
new THREE.MeshPhongMaterial({ color: 0xa0adaf, shininess: 150 })
);
ground.rotation.x = - Math.PI / 2;
ground.receiveShadow = true;
this.scene.add(ground);
const Empty = Object.freeze([]);
this.renderer.clippingPlanes = Empty;
this.renderer.localClippingEnabled = true;
const gui = new GUI()
const folderLocal = gui.addFolder('Local Clipping')
const propsLocal = {
'Enable': this.renderer.localClippingEnabled,
get 'Shadows'() {
return material.clipShadows;
},
set 'Shadows'(v) {
material.clipShadows = v;
},
get 'Plane'() {
return localPlane.constant;
},
set 'Plane'(v) {
localPlane.constant = v;
}
}
let planeHelper = new THREE.PlaneHelper(localPlane, 5, 0xff0000);
this.scene.add(planeHelper);
folderLocal.add(propsLocal, 'Enable').listen().onChange((v) => {
this.renderer.localClippingEnabled = v
setParams()
})
folderLocal.add(propsLocal, 'Shadows');
folderLocal.add(propsLocal, 'Plane', 0.3, 2);
const globalPlane = new THREE.Plane(new THREE.Vector3(-1, 0, 0), 0.1);
const globalPlanes = [globalPlane];
const folderGlobal = gui.addFolder('Global Clipping')
const propsGlobal = {
'Enable': this.renderer.clippingPlanes !== Empty,
get 'Plane'() {
return globalPlane.constant;
},
set 'Plane'(v) {
globalPlane.constant = v;
},
};
folderGlobal.add(propsGlobal, 'Enable').listen().onChange((v) => {
this.renderer.clippingPlanes = v ? globalPlanes : Empty;
})
folderGlobal.add(propsGlobal, "Plane", -0.4, 3);
},
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);
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(0xcccccc);
this.scene.add(ambientLight);
const spotLight = new THREE.SpotLight(0xffffff, 60);
spotLight.angle = Math.PI / 5;
spotLight.penumbra = 0.2;
spotLight.position.set(2, 3, 3);
spotLight.castShadow = true;
spotLight.shadow.camera.near = 3;
spotLight.shadow.camera.far = 10;
spotLight.shadow.mapSize.width = 1024;
spotLight.shadow.mapSize.height = 1024;
this.scene.add(spotLight);
const directionalLight = new THREE.DirectionalLight(0x55505a, 3.0);
directionalLight.position.set(0, 3, 0);
directionalLight.castShadow = true;
directionalLight.shadow.camera.near = 1;
directionalLight.shadow.camera.far = 10;
directionalLight.shadow.camera.right = 1;
directionalLight.shadow.camera.left = - 1;
directionalLight.shadow.camera.top = 1;
directionalLight.shadow.camera.bottom = - 1;
directionalLight.shadow.mapSize.width = 1024;
directionalLight.shadow.mapSize.height = 1024;
this.scene.add(directionalLight);
},
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)
},
animate() {
const currentTime = Date.now();
const time = (currentTime - this.startTime) / 1000;
requestAnimationFrame(this.animate);
this.controller.update();
this.stats.update();
this.renderer.render(this.scene, this.camera);
},
},
};
</script>
<style>
#container {
position: absolute;
width: 100%;
height: 100%;
}
</style>