1.检查npm -v版本和使用对应的vite安装vue3项目
# npm 6.x
npm init vite@latest my-vue-app --template vue
# npm 7+, 需要额外的双横线:
npm init vite@latest my-vue-app -- --template vue
需要安装依赖:npm install
运行:npm run dev
目录结构:
2.threejs官网:
https://threejs.org/
3.安装threejs
npm install --save three
4.准备3D模型素材(我这里使用glb格式)和HDR图片,素材网上可以找有免费的。
这里推荐一些网站:
jpg转hdr网站: https://cn.office-converter.com/how-to-convert-jpeg-to-hdr
免费的hdr图网站:https://tietu.znzmo.com/tietu/hdrtietu_m/p_1.html?color=0
免费的hdr图网站:https://tt.qingmo.com/8/0_0_1_1_0_0.html
ps可以将hdr到处为jpg等格式
免费的fbx模型:https://www.cg99.com/models/
免费的gltf模型:http://glbxz.com/
5.在App.vue中绑定id,挂载,实例化使用
<template>
<div class="scene" id="scene"></div>
</template>
<script setup>
import Base3d from './utils/Base3d';
import { reactive,onMounted } from 'vue';
const data = reactive({
base3d:{}
})
onMounted(()=>{
data.base3d = new Base3d('#scene')
})
</script>
<style>
*{
margin:0;
padding: 0;
}
</style>
6.在项目中的src目录下创建utils目录,在utils目录下创建Base3d.js脚本
import * as THREE from 'three' //导入整个 three.js核心库
import { EquirectangularReflectionMapping } from 'three' //导入纹理映射模块
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader' //导入RGB加载器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' //导入控制器模块,轨道控制器
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader' //导入GLTF模块,模型解析器,根据文件格式来定
class Base3d {
constructor(selector) {
this.container = document.querySelector(selector)
this.camera
this.scene
this.renderer
this.controls
this.init()
this.animate()
}
init() {
//初始化场景
this.initScene()
//初始化相机
this.initCamera()
//初始化渲染器
this.initRender()
//初始化控制器,控制摄像头,控制器一定要在渲染器后
this.initControls()
// 添加物体模型
this.addMesh()
//监听场景大小改变,跳转渲染尺寸
window.addEventListener("resize", this.onWindowResize.bind(this))
}
initScene() {
this.scene = new THREE.Scene()
this.setEnvMap('079')
}
initCamera() {
this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.25, 200)
this.camera.position.set(-1.8, 0.6, 20)
}
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.container.appendChild(this.renderer.domElement)
}
setEnvMap(hdr) { //设置环境背景
new RGBELoader().setPath('./files/hdr/').load(hdr+'.hdr', (texture) => {
texture.mapping = EquirectangularReflectionMapping //圆柱形形纹理映射
this.scene.background = texture
this.scene.environment = texture
})
}
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)
}
//加载模型
setModel(modelName) {
return new Promise((resolve, reject) => {
const loader = new GLTFLoader().setPath('files/gltf/')
loader.load(modelName, (gltf) => {
console.log(gltf);
this.model = gltf.scene.children[0]
this.scene.add(this.model)
resolve(this.modelName + '模型添加成功')
})
})
}
addMesh() {
this.setModel('phone.glb')
}
onWindowResize() { //调整屏幕大小
this.camera.aspect = window.innerWidth / window.innerHeight //摄像机宽高比例
this.camera.updateProjectionMatrix() //相机更新矩阵,将3d内容投射到2d面上转换
this.renderer.setSize(window.innerWidth, window.innerHeight)
}
}
export default Base3d
效果展示:手机模型已经加载至场景中,背景是hdr图。
功能展示:用户可以滑动滚轮将模型进行放大缩小,场景360度无死角旋转。