前言:大部分的场景下,都是用已经建好的3d模型,在threejs中进行加载。这里我们介绍threejs加载glTF模型。
1. 基本概念
1.1 glTF是什么
GLTF/GLB:
GLTF (GL Transmission Format) 是一种基于 JSON 的开放标准 3D 文件格式。(WebGL、OpenGL 中的 “GL” 和 GLTF 中的 “GL” 是相同的单词。)
GLB 是 GLTF 的二进制版本,文件体积较小,便于传输。
Three.js 内置了GLTFLoader用于加载和解析 GLTF/GLB 格式的模型。
gltf的文件是直接渲染的,不可再次编辑,所以对于一些渲染而言不重要的数据通常都已被删除,例如多边形都已转化为三角形。
关于更多 glTF 信息,可以查看其官网:www.khronos.org/gltf/
1.2 glTF格式的三种表现形式
1. glTF二进制(.glb)
- .glb:其中所有网格数据,图像纹理和相关信息都打包到一个二进制文件中。
2. glTF分离式(.gltf + .bin + textures)
- gltf:3D 场景的所有概要信息,包括灯光、纹理贴图等信息,该文件的内容具体形式为 JSON
- .bin:模型的二进制数据,包含网格和矢量数据的文件
- 纹理贴图资源:纹理图片 xxx.jpg 或 .png
3. glTF嵌入式 (.gltf)
- .gltf:以 JSON 形式保存所有场景信息数据,包括材质和纹理信息。这种形式由于文件内容是 json,因此是可以通过文本再次编辑的
.glb === .gltf + .bin + textures
Blender 默认导出 glTF 2.0 格式时,采用的是 .glb 后缀形式。
想要更改成别的导出形式,我们可以在 Blender 导出项 格式下拉框中更改为 “.gltf 分离(.gltf + .bin + 纹理)” 或 "glTF嵌入式(.gltf)"。那么此时导出的文件格式就是 .gltf 后缀形式。
1.3 在Blender中导出gltf文件
在blender打开源文件,如下图所示
直接导出后,在threejs中加载后变成了这样:
出现这种材质贴图不见,且原来有弧度的地方变形的情况,不用怀疑,就是导出的时候出了问题。
官方解释:
glTF的内部结构模拟了图形芯片在实时渲染时常用的内存缓冲区,这样资产可以交付到桌面、网页或移动终端,并以最少的处理进行迅速显示。 因此,当导出为glTF时,四边形和多边形会自动转换为三角形。 与Blender相比,不连续的UV和平面阴影边缘可能导致glTF中的顶点数适度增多,因为这样的顶点会被分开以导出。 同样,曲线和其他非网格数据不会保留,必须在导出之前转换为网格。
所以要从blender入手去解决导出的问题。要将展示的物体转换成网格模式。也就是在blender建模模式下,右键转换到网格,可一次性应用修改器。
这里去掉一些不想展示的物体和参考图,修改为网格模式,导出glb格式文件。
左侧为导出的glb在threejs中的展示,右侧图为blender中的模型展示,所以除了纹理和贴图,blender模型中的着色器渲染是哪一步不对,导致色彩丢失了呢?如果只是简单的BSDF材质是可以渲染的,但我们模型中使用到了 纹理坐标生成分离xyz增加渐变效果。
翻阅资料,查看到例如使用UV映射,则需要设置使用名为 KHR_texture_transform 的glTF扩展导出。
UV映射:通过将UV贴图节点和映射节点连接到任何图像纹理节点,可以控制UV贴图选择和转换。 映射节点中的设置使用名为
KHR_texture_transform的glTF扩展导出。顶部有一个映射类型选择器。推荐使用 点 导出。也支持 纹理 和 矢量 。支持的偏移量是:位置 - X和Y
旋转 - 仅限Z
缩放 - X和Y
对于 纹理 类型,缩放 X和Y必须相等(均匀缩放)。
但是八青妹找了一天也不知道这些扩展在哪里安装和选择,blender的版本为4.1,问题出在哪儿呢?后续研究后再来更新解决方法。
2. gltf加载器
2.1 加载方式
threejs的扩展库gltf加载器GLTFLoader.js
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
// 创建GLTF加载器对象
const loader = new GLTFLoader();
gltf加载器方法.load(),在加载后,可以更改指定物体的属性。
loader.load('/demo.glb',function(gltf) {
const model = gltf.scene;
//获取模型中名称为立方体035的物体
const cube = model.getObjectByName('立方体035');
if(cube) {
//给该物体添加属性
cube.material.color.set(0xff0000);
cube.material.opacity = 0.5;
cube.material.transparent = true;
}
// 调整模型缩放和旋转
model.scale.set(1.5,1.5,1.5);
// 把gltf.scene里面模型添加到场景scene中
scene.add(model);
})
blender建模学习推荐kurtwei.com/ 的视频,每个视频都很用心,没有一句废话,逻辑清晰,有条有理。
最后附上几个线上glTF的文件资源。
一个宇航员: modelviewer.dev/shared-asse…
一只小鸭子: