使用 Three.js 和本地 Draco Loader 高效加载压缩 GLB 模型
在前端项目中,使用 Three.js 渲染 3D 模型时,经常会遇到模型文件过大的问题。为了优化加载速度和传输带宽,很多 GLB 模型都会使用 Draco 压缩。然而,直接加载压缩模型可能会遇到 404 错误或解码失败,尤其是使用官方 CDN 或本地开发时。本文将手把手教你如何在 Vue + Three.js 项目中使用本地 Draco Loader,加载压缩 GLB 模型。
一、Draco 简介
Draco 是 Google 开发的 3D 几何压缩库,可以将几何数据压缩到原来的 10~30% 左右,同时支持 顶点、法线、纹理坐标 压缩。Three.js 提供了 DRACOLoader 来解析压缩的 GLB/GLTF 模型。
官方 CDN 地址:
https://www.gstatic.com/draco/v1/decoders/
但在本地开发时,使用 CDN 可能会遇到 跨域限制 或 404,因此建议把 Draco 文件放在项目的public
目录下。
二、准备工作
1. 安装 Three.js
npm install three
2. 获取 Draco 解码器文件
在
three
包中,Draco 文件位于:node_modules/three/examples/jsm/libs/draco/
主要文件包括:
draco_decoder.js
draco_decoder.wasm
draco_wasm_wrapper.js
draco_wasm_wrapper.wasm
3. 复制文件到 public 目录
# 创建 draco 文件夹 New-Item -ItemType Directory -Force .\public\draco# 复制解码器文件 Copy-Item -Path .\node_modules\three\examples\jsm\libs\draco\* -Destination .\public\draco\
确保目录结构如下:
public/draco/draco_decoder.jsdraco_decoder.wasmdraco_wasm_wrapper.jsdraco_wasm_wrapper.wasm
<template><div ref="threeCanvas" style="width: 100%; height: 100vh;"></div> </template><script setup> import { ref, onMounted, onBeforeUnmount } from 'vue'; import * as THREE from 'three'; import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'; import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'; import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';const threeCanvas = ref(null); let scene, camera, renderer, controls;function initScene() {scene = new THREE.Scene();camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);camera.position.set(0, 2, 5);renderer = new THREE.WebGLRenderer({ antialias: true });renderer.setSize(window.innerWidth, window.innerHeight);threeCanvas.value.appendChild(renderer.domElement);controls = new OrbitControls(camera, renderer.domElement);controls.enableDamping = true;// 光源const ambient = new THREE.AmbientLight(0xffffff, 0.8);const dir = new THREE.DirectionalLight(0xffffff, 1);dir.position.set(5, 10, 7);scene.add(ambient, dir);window.addEventListener('resize', onWindowResize); }function onWindowResize() {camera.aspect = window.innerWidth / window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth, window.innerHeight); }async function loadModel() {const loader = new GLTFLoader();const dracoLoader = new DRACOLoader();dracoLoader.setDecoderPath('/draco/'); // ⚡ 指向 public/dracodracoLoader.preload();loader.setDRACOLoader(dracoLoader);loader.load('/models/test-pipeline.glb', gltf => {scene.add(gltf.scene);}, undefined, err => {console.error('加载模型出错', err);}); }function animate() {requestAnimationFrame(animate);controls.update();renderer.render(scene, camera); }onMounted(async () => {initScene();await loadModel();animate(); });onBeforeUnmount(() => {window.removeEventListener('resize', onWindowResize);renderer.dispose(); }); </script>
浏览器访问:
http://localhost:8080/draco/draco_wasm_wrapper.js
如果能访问文件,说明本地 Draco 已经生效。
我文章里面有在线引入报错所以使用本地化引入解决