三要素 场景 相机 渲染器
物理网格材质(MeshPhysicalMaterial)
<template>
<div ref="canvasbox">
<div class="select-box">
<div class="box">
<span>车身颜色</span>
<input type="color" value="#ff0000" @input="changeCarBody">
</div>
<div class="box">
<span>挑选轮毂</span>
<input type="color" value="#ff0000" @input="changeWhell">
</div>
</div>
</div>
</template>
<script setup>
import { onMounted, ref } from 'vue';
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
const canvasbox = ref(null)
// 车身颜色
const carBody = new THREE.MeshPhysicalMaterial({
color: 0xff0000,
metalness: 1, // 金属度
roughness: 0.5, //粗糙度
clearcoat: 1, // 光滑
clearcoatRoughness: 0, // 粗糙度
})
// 轮毂颜色
const whell = new THREE.MeshPhysicalMaterial({
color: 0xff0000,
metalness: 1, // 金属度
roughness: 0.5, //粗糙度
clearcoat: 1, // 光滑
clearcoatRoughness: 0, // 粗糙度
})
// 前脸
const frontBuilding = new THREE.MeshPhysicalMaterial({
color: 0xff0000,
metalness: 1, // 金属度
roughness: 0.5, //粗糙度
clearcoat: 1, // 光滑
clearcoatRoughness: 0, // 粗糙度
})
// 引擎盖
const engineHood = new THREE.MeshPhysicalMaterial({
color: 0xff0000,
metalness: 1, // 金属度
roughness: 0.5, //粗糙度
clearcoat: 1, // 光滑
clearcoatRoughness: 0, // 粗糙度
})
// 进气口
const airIntake = new THREE.MeshPhysicalMaterial({
color: 0xff0000,
metalness: 1, // 金属度
roughness: 0.5, //粗糙度
clearcoat: 1, // 光滑
clearcoatRoughness: 0, // 粗糙度
})
// 挡风玻璃
const windshield = new THREE.MeshPhysicalMaterial({
color: 0xffffff,
metalness: 0,
transmission: 1,
roughness: 0,
transparent: true,
})
// 内饰座椅
const interiorSeats = new THREE.MeshPhysicalMaterial({
color: 0xffffff,
metalness: 0,
transmission: 1,
roughness: 0,
transparent: true,
})
const init = () => {
// 场景
const scene = new THREE.Scene();
scene.background = new THREE.Color("#cccccc")
scene.environment = "#cccccc"
// 坐标辅助
// const axesHelper = new THREE.AxesHelper(10)
// scene.add(axesHelper)
// 相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 2, 4);
// 渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
canvasbox.value.appendChild(renderer.domElement);
// 坐标格辅助对象. 坐标格实际上是2维线数组
const grid = new THREE.GridHelper(30, 30)
grid.material.opacity = 0.2
grid.material.transparent = true
scene.add(grid)
// 控制器
const controls = new OrbitControls(camera, renderer.domElement)
controls.update()
// 模型加载器
// 需要解压
const loader = new GLTFLoader()
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath("/draco/gltf/");
loader.setDRACOLoader(dracoLoader);
loader.load('/public/baoma/bmw.glb', gltf => {
console.log(gltf);
const model = gltf.scene
model.traverse(child => {
if (child.isMesh) {
console.log(child.name);
if (child.name.includes('Mesh002')) {
child.material = carBody
}
if (child.name.includes('轮毂')) {
child.material = whell
}
if (child.name.includes('前脸')) {
child.material = frontBuilding
}
if (child.name.includes('引擎盖')) {
child.material = engineHood
}
if (child.name.includes('进气口')) {
child.material = airIntake
}
if (child.name.includes('挡风玻璃')) {
child.material = windshield
}
if (child.name.includes('Mesh022')) {
child.material = interiorSeats
}
}
})
function animate() {
requestAnimationFrame(animate);
model.rotation.y+=0.001
renderer.render(scene, camera);
}
animate();
scene.add(model)
}, xhr => { }, err => { console.log(err); })
// 灯光
// 前灯光
const light1 = new THREE.DirectionalLight(0xffffff, 1)
light1.position.set(0, 0, 10)
scene.add(light1)
// 后灯光
const light2 = new THREE.DirectionalLight(0xffffff, 1)
light2.position.set(0, 0, -10)
scene.add(light2)
// 左灯光
const light3 = new THREE.DirectionalLight(0xffffff, 1)
light3.position.set(-10, 0, 0)
scene.add(light3)
// 右灯光
const light4 = new THREE.DirectionalLight(0xffffff, 1)
light4.position.set(10, 0, 0)
scene.add(light4)
// 上灯光
const light5 = new THREE.DirectionalLight(0xffffff, 1)
light5.position.set(0, 10, 0)
scene.add(light5)
// 下灯光
const light6 = new THREE.DirectionalLight(0xffffff, 1)
light6.position.set(0, -10, 0)
scene.add(light6)
// 添加光源
const light7 = new THREE.DirectionalLight(0xffffff, 1);
light7.position.set(0, 10, 5);
scene.add(light7);
// 添加光源
const light8 = new THREE.DirectionalLight(0xffffff, 1);
light8.position.set(-5, 10, 0);
scene.add(light8);
// 添加光源
const light9 = new THREE.DirectionalLight(0xffffff, 1);
light9.position.set(0, 10, -5);
scene.add(light9);
// function animate() {
// requestAnimationFrame(animate);
// renderer.render(scene, camera);
// }
// animate();
}
// 车身颜色方法
const changeCarBody = e => {
const color = e.target.value
carBody.color.set(color)
frontBuilding.color.set(color)
engineHood.color.set(color)
airIntake.color.set(color)
}
// 轮毂颜色切换
const changeWhell = e => {
whell.color.set(e.target.value)
}
onMounted(() => { init() })
</script>
<style scoped>
.select-box {
position: fixed;
top: 0;
right: 20px;
background-color: #e5e5e5;
border-radius: 10px;
padding: 20px;
}
.box {
display: flex;
justify-content: space-between;
align-items: center;
}
</style>