在前端项目中,使用 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 three2. 获取 Draco 解码器文件
在
three包中,Draco 文件位于:node_modules/three/examples/jsm/libs/draco/主要文件包括:
draco_decoder.js
draco_decoder.wasm
draco_wasm_wrapper.js
draco_wasm_wrapper.wasm3. 复制文件到 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.js draco_decoder.wasm draco_wasm_wrapper.js draco_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/draco dracoLoader.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 已经生效。
我文章里面有在线引入报错所以使用本地化引入解决
1879

被折叠的 条评论
为什么被折叠?



