app.vue
<template>
<div class="scene" id="scene"></div>
</template>
<script setup>
import Base3d from './utils/Base3d2';
import { reactive,onMounted } from 'vue';
const data = reactive({
base3d:{}
})
onMounted(()=>{
data.base3d = new Base3d('#scene')
})
</script>
<style>
*{
margin:0;
padding: 0;
overflow: hidden;
}
</style>
Base3d2.js
import * as THREE from 'three' //導(dǎo)入整個(gè) three.js核心庫
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' //導(dǎo)入控制器模塊,軌道控制器
//聲明一個(gè)類
class Base3d {
//構(gòu)造器
constructor(selector) {
this.container = document.querySelector(selector)
this.camera
this.scene
this.renderer
this.controls
this.spotLight
this.init()
this.animate()
}
init() {
//初始化場景
this.initScene()
//初始化相機(jī)
this.initCamera()
//初始化渲染器
this.initRender()
//初始化控制器,控制攝像頭,控制器一定要在渲染器后
this.initControls()
//監(jiān)聽場景大小改變,跳轉(zhuǎn)渲染尺寸
window.addEventListener("resize", this.onWindowResize.bind(this))
//初始化三維坐標(biāo)系
this.initAxesHelper()
//初始化幾何體網(wǎng)格模型
this.initGeometry()
//初始化燈光
this.initLight()
}
initScene() {
this.scene = new THREE.Scene()
}
initCamera() {
this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.25, 2000)
this.camera.position.set(30, 30, 30)
this.camera.lookAt(this.scene.position)
}
initRender() {
this.renderer = new THREE.WebGLRenderer({ antialias: true }) //設(shè)置抗鋸齒
//設(shè)置屏幕像素比
this.renderer.setPixelRatio(window.devicePixelRatio)
//渲染的尺寸大小
this.renderer.setSize(window.innerWidth, window.innerHeight)
//色調(diào)映射
this.renderer.toneMapping = THREE.ACESFilmicToneMapping
//曝光
this.renderer.toneMappingExposure = 3
//初始化背景顏色
this.renderer.setClearColor(new THREE.Color(0xeeeeee));
// 設(shè)置渲染物體陰影
this.renderer.shadowMap.enabled = true;
this.container.appendChild(this.renderer.domElement)
}
render() {
this.renderer.render(this.scene, this.camera)
}
animate() {
this.renderer.setAnimationLoop(this.render.bind(this))
}
initControls() {
this.controls = new OrbitControls(this.camera, this.renderer.domElement)
}
onWindowResize() { //調(diào)整屏幕大小
this.camera.aspect = window.innerWidth / window.innerHeight //攝像機(jī)寬高比例
this.camera.updateProjectionMatrix() //相機(jī)更新矩陣,將3d內(nèi)容投射到2d面上轉(zhuǎn)換
this.renderer.setSize(window.innerWidth, window.innerHeight)
}
initAxesHelper() {//三維坐標(biāo)系
this.axes = new THREE.AxesHelper(20)
this.scene.add(this.axes)
}
initGeometry() {
const planeGeometry = new THREE.PlaneGeometry(60, 60);
// 給地面物體上色
const planeMaterial = new THREE.MeshStandardMaterial({ color: 0xcccccc });
// 創(chuàng)建地面
const plane = new THREE.Mesh(planeGeometry, planeMaterial)
// 物體移動(dòng)位置
plane.rotation.x = -0.5 * Math.PI;
plane.position.x = 0;
plane.position.y = 0;
plane.position.z = 0;
plane.castShadow = true;
// 接收陰影
plane.receiveShadow = true;
// 將地面添加到場景中
this.scene.add(plane);
// 添加立方體
const cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
const cubeMaterial = new THREE.MeshLambertMaterial({ color: 0xff0000 })
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.position.x = 0;
cube.position.y = 4;
cube.position.z = 2;
// 對象是否渲染到陰影貼圖當(dāng)中
cube.castShadow = true;
this.scene.add(cube)
// 球體
const sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
const spherMaterial = new THREE.MeshLambertMaterial({ color: 0xff0000 })
const sphere = new THREE.Mesh(sphereGeometry, spherMaterial)
sphere.position.x = 10;
sphere.position.y = 4;
sphere.position.z = 0;
// 對象是否渲染到陰影貼圖當(dāng)中
sphere.castShadow = true;
this.scene.add(sphere)
}
initLight() {
// 創(chuàng)建聚光燈
const spotLight = new THREE.SpotLight(0xFFFFFF);
spotLight.position.set(130, 130, -130);
spotLight.castShadow = true;
spotLight.angle = Math.PI / 4;
spotLight.shadow.penumbra = 0.05
spotLight.shadow.mapSize.width = 1024;
spotLight.shadow.mapSize.innerHeight = 1024;
// 添加聚光燈
this.scene.add(spotLight)
}
}
export default Base3d
