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' //导入整个 three.js核心库
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' //导入控制器模块,轨道控制器
//声明一个类
class Base3d {
//构造器
constructor(selector) {
this.container = document.querySelector(selector)
this.camera
this.scene
this.renderer
this.controls
this.spotLight
this.init()
this.animate()
}
init() {
//初始化场景
this.initScene()
//初始化相机
this.initCamera()
//初始化渲染器
this.initRender()
//初始化控制器,控制摄像头,控制器一定要在渲染器后
this.initControls()
//监听场景大小改变,跳转渲染尺寸
window.addEventListener("resize", this.onWindowResize.bind(this))
//初始化三维坐标系
this.initAxesHelper()
//初始化几何体网格模型
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 }) //设置抗锯齿
//设置屏幕像素比
this.renderer.setPixelRatio(window.devicePixelRatio)
//渲染的尺寸大小
this.renderer.setSize(window.innerWidth, window.innerHeight)
//色调映射
this.renderer.toneMapping = THREE.ACESFilmicToneMapping
//曝光
this.renderer.toneMappingExposure = 3
//初始化背景颜色
this.renderer.setClearColor(new THREE.Color(0xeeeeee));
// 设置渲染物体阴影
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() { //调整屏幕大小
this.camera.aspect = window.innerWidth / window.innerHeight //摄像机宽高比例
this.camera.updateProjectionMatrix() //相机更新矩阵,将3d内容投射到2d面上转换
this.renderer.setSize(window.innerWidth, window.innerHeight)
}
initAxesHelper() {//三维坐标系
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 });
// 创建地面
const plane = new THREE.Mesh(planeGeometry, planeMaterial)
// 物体移动位置
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;
// 对象是否渲染到阴影贴图当中
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;
// 对象是否渲染到阴影贴图当中
sphere.castShadow = true;
this.scene.add(sphere)
}
initLight() {
// 创建聚光灯
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