为了更好的兼容提供素材的解码器,建议使用[email protected]版本
npm install [email protected] -S
不然有可能会出现以下问题:
素材:
链接: https://pan.baidu.com/s/1gqqOwEC-Iy4D_rCFGmLR9g
提取码: c6xj
关键代码:
loader.load("car.glb", (gltf) => {
let textureLoader = new THREE.TextureLoader();
textureLoader = textureLoader.load("three/050.jpg");
//映射-折射映射,不设置将不会透明
textureLoader.mapping = THREE.EquirectangularRefractionMapping;
// gltf.scene.rotation.x= -Math.PI/2
gltf.scene.traverse((child) => {
if (child.isMesh) {
if (child.name.includes("轮毂")) {
child.material = this.wheelPhysicalMaterial;
this.wheels.push(child);
}
if (child.name.includes("Mesh002")) {
console.log(this.carBodyPhysicalMaterial);
child.material = this.carBodyPhysicalMaterial;
this.carBody = child;
}
if (child.name.includes("前脸")) {
child.material = this.carFrontPhysicalMaterial;
this.carFront = child;
}
if (child.name.includes("引擎盖_1")) {
child.material = this.carHoodPhysicalMaterial;
this.carHood = child;
}
if (child.name.includes("挡风玻璃")) {
child.material = this.carGlassPhysicalMaterial;
this.carGlass = child;
}
}
});
scene.add(gltf.scene);
});
完整代码:
汽车展示与选配
选择车身颜色
class="select-item"
v-for="(item, index) in colors"
:key="index"
@click="selectColor(index)"
>
class="select-item-color"
:style="{ backgroundColor: item }"
>
选择贴膜材质
class="select-item"
v-for="(item, index) in materials"
:key="index"
@click="selectMaterial(index)"
>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader";
import { Water } from "three/examples/jsm/objects/Water2";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
export default {
name: "HOME",
components: {
// vueQr,
// glHome,
},
data() {
return {
wheels: [],
carBody: "",
carFront: "",
carHood: "",
carGlass: "",
colors: ["red", "blue", "green", "gray", "orange", "purple"],
materials: [
{ name: "磨砂", value: 1 },
{ name: "冰晶", value: 0 },
],
wheelPhysicalMaterial: new THREE.MeshPhysicalMaterial({
color: 0xff0000,
metalness: 1,
roughness: 0.5,
transmission: 1,
transparent: true,
clearcoatRoughness: 0,
}),
carBodyPhysicalMaterial: new THREE.MeshPhysicalMaterial({
color: 0xff0000,
metalness: 1,
roughness: 0.5,
clearcoat: 1,
clearcoatRoughness: 0,
}),
carFrontPhysicalMaterial: new THREE.MeshPhysicalMaterial({
color: 0xff0000,
metalness: 1,
roughness: 0.5,
clearcoat: 1,
clearcoatRoughness: 0,
}),
carHoodPhysicalMaterial: new THREE.MeshPhysicalMaterial({
color: 0xff0000,
metalness: 1,
roughness: 0.5,
clearcoat: 1,
clearcoatRoughness: 0,
}),
carGlassPhysicalMaterial: new THREE.MeshPhysicalMaterial({
color: 0xffffff,
metalness: 0,
roughness: 0,
transmission: 1,
transparent: true,
}),
};
},
mounted() {
//使用控制器控制3D拖动旋转OrbitControls
//控制3D物体移动
//1.创建场景
const scene = new THREE.Scene();
console.log(scene);
//2.创建相机
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
20000
);
//设置相机位置
camera.position.set(0, 0, 10);
//将相机添加到场景
scene.add(camera);
//添加周围环境灯光(由物体发出的灯光)参数(灯色,强度0-1)
const light01 = new THREE.DirectionalLight(0xffffff, 1);
light01.position.set(0, 0, 10);
scene.add(light01);
const light02 = new THREE.DirectionalLight(0xffffff, 1);
light02.position.set(0, 0, -10);
scene.add(light02);
const light03 = new THREE.DirectionalLight(0xffffff, 1);
light03.position.set(10, 0, 0);
scene.add(light03);
const light04 = new THREE.DirectionalLight(0xffffff, 1);
light04.position.set(-10, 0, 0);
scene.add(light04);
const light05 = new THREE.DirectionalLight(0xffffff, 1);
light05.position.set(0, 10, 0);
scene.add(light05);
//加载模型
const loader = new GLTFLoader().setPath("three/glb/");
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath("three/draco/gltf/");
// dracoLoader.setDecoderConfig({
// type: 'js'
// })
loader.setDRACOLoader(dracoLoader);
this.carBodyPhysicalMaterial.clearcoatRoughness = this.materials[1].value;
this.carFrontPhysicalMaterial.clearcoatRoughness = this.materials[1].value;
this.carHoodPhysicalMaterial.clearcoatRoughness = this.materials[1].value;
loader.load("car.glb", (gltf) => {
let textureLoader = new THREE.TextureLoader();
textureLoader = textureLoader.load("three/050.jpg");
//映射-折射映射,不设置将不会透明
textureLoader.mapping = THREE.EquirectangularRefractionMapping;
// gltf.scene.rotation.x= -Math.PI/2
gltf.scene.traverse((child) => {
if (child.isMesh) {
if (child.name.includes("轮毂")) {
child.material = this.wheelPhysicalMaterial;
this.wheels.push(child);
}
if (child.name.includes("Mesh002")) {
console.log(this.carBodyPhysicalMaterial);
child.material = this.carBodyPhysicalMaterial;
this.carBody = child;
}
if (child.name.includes("前脸")) {
child.material = this.carFrontPhysicalMaterial;
this.carFront = child;
}
if (child.name.includes("引擎盖_1")) {
child.material = this.carHoodPhysicalMaterial;
this.carHood = child;
}
if (child.name.includes("挡风玻璃")) {
child.material = this.carGlassPhysicalMaterial;
this.carGlass = child;
}
}
});
scene.add(gltf.scene);
});
//添加坐标轴辅助器
const axesHepler = new THREE.AxesHelper(5);
scene.add(axesHepler);
//初始化渲染器
const render = new THREE.WebGLRenderer({
//设置抗锯齿,防失真
antialis: true,
//对数深度缓冲区,防止模型闪烁
logarithmicdepthbuffer: true,
});
/*设置场景渲染编码threejs将贴图的编码都默认设置为THREE.LinearEncoding,
*导致图片色彩失真(色彩不像正常那么鲜艳,会灰蒙蒙的),所以务必将场景中的所有贴图的编码都调整为THREE.sRGBEncoding
*/
render.outputEncoding = THREE.sRGBEncoding;
//设置渲染器的尺寸
render.setSize(window.innerWidth, window.innerHeight);
//创建轨道控制器,可以拖动,控制的是摄像头
const controls = new OrbitControls(camera, render.domElement);
//设置控制阻尼,让控制器有更真实的效果
controls.enableDamping = true;
//将webgl渲染的canvas内容添加到body上
document.getElementById("three_div").appendChild(render.domElement);
//清除默认设置颜色
render.setClearColor("#000");
//设置场景背景颜色
scene.background = new THREE.Color("#ccc");
scene.environment = new THREE.Color("#ccc");
const gridHelper = new THREE.GridHelper(10, 10);
console.log("网格", gridHelper);
gridHelper.material.opacity = 1;
gridHelper.material.transparent = true;
scene.add(gridHelper);
//渲染下一帧的时候就会调用回调函数
let renderFun = () => {
//更新阻尼数据
controls.update();
//需要重新绘制canvas画布
render.render(scene, camera);
//监听屏幕刷新(60HZ,120HZ),每次刷新触发一次requestAnimationFrame回调函数
//但是requestAnimationFrame的回调函数注册生命只有一次,因此需要循环注册,才能达到一直调用的效果
window.requestAnimationFrame(renderFun);
};
// window.requestAnimationFrame(renderFun);
renderFun();
//画布全屏
window.addEventListener("dblclick", () => {
if (document.fullscreenElement) {
document.exitFullscreen();
} else {
//document.documentElement.requestFullscreen();
render.domElement.requestFullscreen();
}
});
//监听画面变化,更新渲染画面,(自适应的大小)
window.addEventListener("resize", () => {
//更新摄像机的宽高比
camera.aspect = window.innerWidth / window.innerHeight;
//更新摄像机的投影矩阵
camera.updateProjectionMatrix();
//更新渲染器宽度和高度
render.setSize(window.innerWidth, window.innerHeight);
//设置渲染器的像素比
render.setPixelRatio(window.devicePixelRatio);
console.log("画面变化了");
});
},
methods: {
selectColor(index) {
this.carBodyPhysicalMaterial.color.set(this.colors[index]);
this.carFrontPhysicalMaterial.color.set(this.colors[index]);
this.carHoodPhysicalMaterial.color.set(this.colors[index]);
this.wheelPhysicalMaterial.color.set(this.colors[index]);
},
selectMaterial(index) {
this.carBodyPhysicalMaterial.clearcoatRoughness =
this.materials[index].value;
this.carFrontPhysicalMaterial.clearcoatRoughness =
this.materials[index].value;
this.carHoodPhysicalMaterial.clearcoatRoughness =
this.materials[index].value;
// alert(this.materials[index].value)
// this.wheelPhysicalMaterial.clearcoatRoughness = this.materials[index].value;
},
},
};
* {
margin: 0;
padding: 0;
}
.home-content {
position: fixed;
top: 0;
right: 20px;
}
.select-item-color {
width: 50px;
height: 50px;
border: 1px solid #ccc;
margin: 10px;
display: inline-block;
cursor: pointer;
border-radius: 10px;
}
.select {
display: flex;
}
效果图: