Skip to content

Commit 22655bc

Browse files
committed
update 24 add DRACOLoader
1 parent 3486a64 commit 22655bc

File tree

2 files changed

+238
-7
lines changed

2 files changed

+238
-7
lines changed

24 Three.js解决方案之加载.gLTF模型.md

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,219 @@ https://modelviewer.dev/shared-assets/models/Astronaut.glb
445445

446446

447447

448+
<br>
449+
450+
你以为本文结束了?没有!
451+
452+
在上面示例中,我们实际上漏掉了一个非常重要的知识点:加载被压缩过的 .glb 文件
453+
454+
455+
456+
<br>
457+
458+
## glTF文件压缩和加载(解压)——Draco
459+
460+
在本文的示例中,所演示加载的 .glb 文件是我自己在 Blender 中创建导出的。
461+
462+
如同图片文件一样,也有专门针对 .glb 文件压缩的工具,最为著名的就是谷歌公司开源的:draco
463+
464+
465+
466+
### Draco简介
467+
468+
Draco 是一种库,用于压缩和解压缩 3D 几何网格(geometric mesh) 和 点云(point cloud)
469+
470+
draco官网:https://google.github.io/draco/
471+
472+
draco源码:https://github.com/google/draco
473+
474+
475+
476+
<br>
477+
478+
draco 底层是使用 c++ 编写的。
479+
480+
draco 可以在不牺牲模型效果的前提下,将 .glb 文件压缩体积减小很多。
481+
482+
> 就好像将普通文件压缩成 .zip 一样
483+
484+
> 至于文件减少多少,这个暂时没有查询到
485+
486+
487+
488+
<br>
489+
490+
#### Draco使用流程是:
491+
492+
1. 使用 Draco 将模型压缩,最终压缩后的文件格式为 .drc 或 .glb
493+
494+
> Draco 可以压缩众多 3D 格式文件,.glb 仅仅是其中一种
495+
496+
2. 在 .glb 文件内部有一个特殊字段,用来表述本文件是否经过了 draco 压缩
497+
498+
3. 当客户端(JS) 使用 GLTFLoader 去加载某个 .glb 文件时会去读取该标识
499+
500+
4. 若判断该 .glb 文件未被压缩则直接进行加载和解析
501+
502+
5. 若判断该 .glb 文件是被 draco 压缩过的,则会尝试调用 draco 解压类,下载 .glb 文件的同时进行解压,最终将下载、解压后的 .glb 数据传递给 GLTFLoader 使用
503+
504+
> 这就引申出来一个事情:我们需要提前将负责 draco 解压的类传递给 GLTFLoader,具体如何做请看后面的讲解。
505+
506+
507+
508+
<br>
509+
510+
#### 如何使用 Draco 压缩 .glb 文件?
511+
512+
具体如何操作实现,暂时我也没有学习,先搁置一下。
513+
514+
> 敬请期待以后的更新
515+
516+
517+
518+
<br>
519+
520+
#### 如何在Three.js 中加载压缩过的 .glb 文件?
521+
522+
关于 Draco 的介绍,可以查看 Three.js 对于 Draco 的介绍描述:
523+
524+
https://github.com/mrdoob/three.js/tree/dev/examples/js/libs/draco
525+
526+
527+
528+
Three.js 源码包中 draco 针对 gltf 文件的解压文件库:
529+
530+
https://github.com/mrdoob/three.js/tree/dev/examples/js/libs/draco/gltf
531+
532+
在该目录下,一共有 4 个文件:
533+
534+
1. draco_decoder.js
535+
536+
> draco 解压(解码) 相关 js
537+
538+
2. draco_decoder.wasm
539+
540+
> .wasm 文件是 WebAssembly 解码器
541+
>
542+
> 关于 WebAssembly 更多知识,请执行查阅:https://www.wasm.com.cn/
543+
544+
3. draco_encoder.js
545+
546+
> draco 压缩(编码) 相关 js
547+
548+
4. draco_wasm_wrapper.js
549+
550+
> 用于封装 .wasm 解码器的 js
551+
552+
对于我们使用 Three.js 而言,以上 4 个文件中除 draco_encoder.js 以外,其他 3 个文件都是我们需要的。
553+
554+
555+
556+
重点来了...
557+
558+
<br>
559+
560+
#### 第1步:拷贝 draco/gltf 文件到项目 public 中
561+
562+
我们将 Three.js 中 examples/js/libs/draco/gltf 目录拷贝到 React 项目的 public 目录中。
563+
564+
> draco gltf 属于第 3 方库,我们目前暂时采用拷贝到 public 目录中这种形式
565+
566+
> 在 Three.js 官方示例中使用的是 `examples/js/libs/draco/`,这是因为在 draco/ 和 draco/gltf 目录下,都有上面 4 个文件,所以使用哪个目录都可以。
567+
568+
569+
570+
#### 第2步:实例化一个 DRACOLoader,并传递给 GLTFLoader
571+
572+
> 关于 DRACOLoader 的详细解释,请参考官方文档:
573+
>
574+
> https://threejs.org/docs/#examples/zh/loaders/DRACOLoader
575+
576+
<br>
577+
578+
我们将之前 GLTFLoader 的代码修改如下:
579+
580+
```diff
581+
+ import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'
582+
583+
const gltfLoader = new GLTFLoader()
584+
585+
+ const dracoLoader = new DRACOLoader()
586+
+ dracoLoader.setDecoderPath('./examples/js/libs/draco/gltf')
587+
+ dracoLoader.setDecoderConfig({ type: 'js' })
588+
+ gltfLoader.setDRACOLoader(dracoLoader)
589+
590+
gltfLoader.load('./model/vivo.glb', (gltf) => {
591+
scene.add(gltf.scene)
592+
})
593+
```
594+
595+
596+
597+
<br>
598+
599+
下面就针对上面 4 行核心代码进行解释说明:
600+
601+
1. `const dracoLoader = new DRACOLoader()`
602+
603+
实例化一个 DRACOLoader
604+
605+
2. `dracoLoader.setDecoderPath('./examples/js/libs/draco/gltf')`
606+
607+
设置 dracoLoader 应该去哪个目录里查找 解压(解码) 文件
608+
609+
3. `dracoLoader.setDecoderConfig({ type: 'js' })`
610+
611+
设置 dracoLoader 的配置项
612+
613+
4. `gltfLoader.setDRACOLoader(dracoLoader)`
614+
615+
将 dracoLoader 传递给 gltfLoader,供 gltfLoader 使用
616+
617+
至此,结束!
618+
619+
620+
621+
<br>
622+
623+
虽然 draco 非常复杂,但是对于我们使用者而言却很简单,仅仅上面 4 行代码即可实现加载被 draco 压缩过的 .glb 文件。
624+
625+
626+
627+
<br>
628+
629+
## 加载.drc模型文件
630+
631+
在上面示例中,我们加载的是被 draco 压缩过的 .glb 文件。
632+
633+
那如果是被 draco 压缩过的 .drc 文件呢?
634+
635+
答:更加简单,直接使用 DRACOLoader即可。
636+
637+
638+
639+
<br>
640+
641+
DRACOLoader使用示例代码如下:
642+
643+
```
644+
const loader = new DRACOLoader();
645+
loader.setDecoderPath( '/examples/js/libs/draco/gltf' );
646+
loader.preload();
647+
648+
loader.load('./xxx/model.drc',
649+
function ( geometry ) {
650+
const material = new THREE.MeshStandardMaterial( { color: 0x606060 } );
651+
const mesh = new THREE.Mesh( geometry, material );
652+
scene.add( mesh );
653+
}
654+
}
655+
```
656+
657+
658+
659+
660+
448661
<br>
449662

450663
下一章节,我们要学习如何添加 场景背景,呵, VR 看房效果要来了!

25 Three.js解决方案之添加背景和天空盒.md

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,26 @@ const canvasStyle = {
307307
308308
309309
310+
<br>
311+
312+
上面对于天空盒的解释正确吗?
313+
314+
答:正确但不严谨!
315+
316+
317+
318+
<br>
319+
320+
通常我们所说天空盒(Skybox) 一个非常重要的特性就是:像天空一样大的盒子
321+
322+
进一步解释就是:这个盒子空间像天空一样无边无际,永远不到头。
323+
324+
> 说直白点,天空盒就好像我们平时的场景(Three.Scene),无论缩小到什么限度,还是放大到什么限度,永远走不出场景之外。
325+
326+
而本文下面所有的示例,其实都是针对场景背景添加纹理贴图,所以下面示例中的天空盒(skybox)空间等同于场景本身。
327+
328+
329+
310330
<br>
311331
312332
**天空盒一共有 2 种形式的贴图资源:**
@@ -566,19 +586,17 @@ textureLoader.load(require('@/assets/imgs/tears_of_steel_bridge.jpg').default,
566586
567587
你以为本文结束了?没有!
568588
569-
我们上面示例讲的都是加载纹理,然后通过设置 场景背景(scene.background) 来实现的,除了这种方式,还有没有别的途径来实现
589+
我们上面示例都是 天空盒(skybox),那如果是真的一个立方体呢
570590
591+
> 天空盒 是没有尺寸,空间无限大的,而普通立方体则是有尺寸的。
571592
593+
下面示例我们将创建一个立方体,然后对立方体内部进行贴图,并渲染和观察立方体盒子内部。
572594
573-
<br>
574-
575-
接下来我们就要讲解第 3 种方式:创建球体,然后让我们身处球体之内。
576595
577-
> 为什么是球体,而不是 立方体?
578596
597+
<br>
579598
599+
## 普通立方体内部贴图和渲染
580600
581-
<br>
582601
583-
## 场景背景的第3种添加方式
584602

0 commit comments

Comments
 (0)