准备工作
1. 创建Vue脚手架
2. 引入three.js
3. 下载3D模型
开始行动
1.创建脚手架就不说了(看我的文档,或者直接私信)
2.引入three.js
three.js是新技术,版本更新很快。直接去官网(three.js docs)看文档,引入指令是
npm install three
回车运行
在你的package-lock.json文件中多出这行代码
这就现在好了。
下载3D模型,可以去一些国内外网站上下载,
可以去我的资源里下载
获取后下载到
这个文件夹直接解压当前文件夹
出现了就可以了
开始写代码
选择这个文件
这个文件夹直接将文件内容所有都删除把下边的代码粘贴上去
<template>
<div class="aaaa">
<canvas id="three"></canvas>
</div>
</template>
<script>
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
export default {
name: 'OneshiHomeView',
mounted() {
this.initThree()
},
methods: {
initThree(){
// 为Three.js创建一个scene:
const scene = new THREE.Scene()
// scene可以理解为我们将要渲染的环境、背景。我们可以给它换个颜色:
// scene.background = new THREE.Color('#eee');
scene.background = new THREE.TextureLoader().load( "https://img0.baidu.com/it/u=1009816953,2368115040&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500" )
// 拿到canvas:
const canvas = document.querySelector('#three')
// 创建一个WebGLRenderer,将canvas和配置参数传入
const renderer = new THREE.WebGLRenderer({ canvas, antialias: true });
// 想要产生影子,添加
renderer.shadowMap.enabled = true;
// camera用来观看场景里的内容,Three.js提供多种相机,比较常用的是PerspectiveCamera(透视摄像机)以及OrthographicCamera (正交投影摄像机)
// 使用PerspectiveCamera(透视摄像机)
const camera = new THREE.PerspectiveCamera(
50, //摄像机视锥体垂直视野角度。可以理解为人类的视野广度。
window.innerWidth / window.innerHeight,//摄像机视锥体横纵比。渲染结果的横向尺寸和纵向尺寸的比值,这里我们使用的是 浏览器窗口的宽高比
0.1, //摄像机视锥体近端面。一切比近面更近的事物将不被渲染。
1000 //摄像机视锥体远端面。一切比远面更远的事物将不被渲染,但是设置过大可能会影响性能。
)
/* PerspectiveCamera( fov : Number, aspect : Number, near : Number, far : Number )具有四个参数
:fov — 摄像机视锥体垂直视野角度。可以理解为人类的视野广度。
aspect — 摄像机视锥体横纵比。渲染结果的横向尺寸和纵向尺寸的比值,这里我们使用的是 浏览器窗口的宽高比。
near — 摄像机视锥体近端面。一切比近面更近的事物将不被渲染。
far — 摄像机视锥体远端面。一切比远面更远的事物将不被渲染,但是设置过大可能会影响性能。
*/
// 生成的camera默认是放在中心点(0,0,0)的,但这是待会模型要放的位置,因此,我们把摄像机挪个位置
camera.position.z = 100;
const gltfLoader = new GLTFLoader()
gltfLoader.load('scene.gltf', (gltf) => {
let model = gltf.scene
// 遍历模型每部分
model.traverse((o) => {
//将图片作为纹理加载
let explosionTexture = new THREE.TextureLoader().load(
"textures/GUNDAM_baseColor.png"
)
//调整纹理图的方向
explosionTexture.flipY = false
//将纹理图生成基础网格材质(MeshBasicMaterial)
const material = new THREE.MeshBasicMaterial({
map: explosionTexture,
})
//给模型每部分上材质
o.material = material
// 阴影
if (o.isMesh) {
o.castShadow = true
o.receiveShadow = true
}
})
scene.add(model)
})
function resizeRendererToDisplaySize(renderer) {
const canvas = renderer.domElement
var width = window.innerWidth
var height = window.innerHeight
var canvasPixelWidth = canvas.width / window.devicePixelRatio
var canvasPixelHeight = canvas.height / window.devicePixelRatio
const needResize =
canvasPixelWidth !== width || canvasPixelHeight !== height
if (needResize) {
renderer.setSize(width, height, false)
}
return needResize
}
// 创建它,可以写在animate函数上面:
const controls = new OrbitControls(camera, renderer.domElement)
// 给它加点阻尼感,更真实点,泥可以对比下加不加的区别:
controls.enableDamping = true
//
let floorGeometry = new THREE.PlaneGeometry(3000, 3000)
let floorMaterial = new THREE.MeshPhongMaterial({color: 0xff0000});
//
let floor = new THREE.Mesh(floorGeometry, floorMaterial)
floor.rotation.x = -0.5 * Math.PI
floor.receiveShadow = true
floor.position.y = -0.001
scene.add(floor)
//
const dirLight = new THREE.DirectionalLight(0xffffff, 0.6)
//光源等位置
dirLight.position.set(-100, 10, 80)
//可以产生阴影
dirLight.castShadow = true
dirLight.shadow.mapSize = new THREE.Vector2(1024, 1024)
scene.add(dirLight)
const hemLight = new THREE.HemisphereLight(0xffffff, 0xffffff, 0.6)
hemLight.position.set(100, 480, 0)
scene.add(hemLight)
// Three.js 需要一个动画循环函数,Three.js 的每一帧都会执行这个函数。
function animate() {
controls.update()
renderer.render(scene,camera)
requestAnimationFrame(animate)
if (resizeRendererToDisplaySize(renderer)) {
const canvas = renderer.domElement
camera.aspect = canvas.clientWidth / canvas.clientHeight
camera.updateProjectionMatrix()
}
}
animate()
}
},
};
</script>
<style lang="scss">
.aaaa{
width: 100%;
height: 1000px;
background-color: #f00;
display: flex;
justify-content: center;
text-align: center;
position: relative;
}
#three {
width: 800px;
height: 600px;
position: absolute;
left: 100px;
top: 100px;
}
</style>
细说一下
const gltfLoader = new GLTFLoader();
gltfLoader.load( 'path/to/model.glb', function ( gltf ) {
scene.add( gltf.scene );
}, undefined, function ( error ) {
console.error( error );
} );
中的 'path/to/model.glb' ,因为前边把3D模型放在了public文件夹。
不是相对路径
不是绝对路径
是相对于public文件夹的路径。
如果是public文件夹下的textures文件夹
'textures'
如果是public文件夹下的license.txt文件
'license.txt'