前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >3D领域的jpg?模型交换格式glTF概述

3D领域的jpg?模型交换格式glTF概述

原创
作者头像
WendyGrandOrder
发布2020-10-30 14:50:28
3.8K0
发布2020-10-30 14:50:28
举报
文章被收录于专栏:RESTART POiNTERRESTART POiNTER

什么是glTF?

在3D开发领域,存储模型是一个基本需求,对于前端也不例外。就像一般网页需要使用jpg、png、webp等格式渲染图片一样,3d页面/软件/游戏的开发者,也需要把角色、场景、动画等等信息,按照某种格式存储下来,使用时解析并渲染。

通常来说,3d模型的数据由一些固定的元素构成,但存储格式却种类繁多,web常用的格式有obj、stl等等,不同平台和渲染引擎也会设计自己的私有格式,它们之间通常互不兼容,导致跨平台交换模型十分困难。为了解决这个痛点,glTF应运而生。

glTF是由khronos制定推广的一套开源存储标准,致力于成为3D领域的jpg,它的全称是GL Transmission Format,对GL图形api十分友好,比传统的obj、stl更便捷,目前已迭代到2.0版本,并得到许多建模软件和渲染引擎的支持,Maya、3dmax、unity、blender等都可以导入导出glTF模型,threejs,babylonjs等web渲染引擎都提供动态加载器。

如果你有跨平台需要交换3d模型的需求,不妨考虑使用它。

glTF的设计思想

glTF的核心设计思路是数据和结构的分离,通过json文件存储模型的层级和索引信息,通过二进制文件存储扁平的数据体。 这样做的优点是方便数据的读写,比起传统的使用二进制数据+标记位的方式,省略了很多索引和字节判断的逻辑,使代码更加简明易懂,同时只需要一次遍历即可解析全部数据,读取效率也更高。

但这样做的缺点是json文件复杂度增加,需要设置专门的索引构造,用来指明读取二进制文件的方式。

下面来看glTF的文件结构。

glTF文件结构概览

一个典型的glTF格式的json文件,由以下结构组成

每个结构都是单元数组,结构之间通过数组下标互相索引。

因为索引表达了树状结构,所以json中的属性,都是扁平的一维数组。

根据实际用途,我们把上述数据划分为“存储属性”和“几何属性”两类。存储属性是glTF专有的,用来指明二进制文件的读取方式,几何属性则用来表达模型的实际信息。

存储结构

包括buffers,bufferViews,accessors三部分

buffers数组中的某个单元,指向某个二进制文件。

bufferViews数组中的某个单元,指向某个buffer,并规定了读取文件的长度和偏移值,这些数据可以非常直观地转换成二进制阅读器的代码,将读出的数据写进WebGL或其他渲染api。

accessors指明了如何通过bufferViews来获取一组数据,并且规定了该数据的类型和范围。它是最终被几何属性引用的单位。几何结构里的坐标,索引等等,都会对应accessors里的一个下标值。

几何属性

除去以上三个结构与数据存取相关外,其余的结构都用来标识模型的几何信息,这些信息一定程度上是通用的,只是不同文件格式会设计不同的方式存储它们。

scenes、nodes

scenes是场景的根节点,包含了若干个nodes,nodes本身也是树状结构,可以包含若干个子节点,共同组成一个场景。

注意,虽然是树状结构,但子元素通过children数组间接引用,所以存储本身是一个一维的数组,避免了文件层级过深。

nodes中的一个单元可以是多种类型——如摄像机(camera),变换(matrix)和网格(mesh)

摄像机:

即是场景中camera的相关配置(如果有的话),不再赘述。

变换: 在三维模型里,骨骼就等同于变换,所以如果使用glTF存储角色模型,通常把就骨骼信息存储为node节点,存储的方式可以是矩阵,也可以是rotate、scale、transform三个三元数组,二者表达的信息是等价的,但矩阵更便于计算。

网格:

骨骼末梢的节点通常是网格(mesh)节点,它们是真正参与绘制的单元(这意味着如果输出一个没有mesh的glTF,是不会渲染出任何内容的)。

nodes中的mesh节点只是一个索引,引用了meshes数组里的一个元素,网格的几何信息都定义在meshes里。

meshes

包含了网格的基础几何信息,如顶点坐标,顶点索引,法线,切线等等,以及它对应的材质下标。

几何信息的部分这里不再赘述,但需要额外关注targets属性。它声明了该网格的形变动画信息。

形变动画,morph targets,在不同的软件中又命名为blend shape,shape keys,其本质是一种定义网格动画的方式。形变动画原理上和骨骼动画不同,并非通过骨骼来带动网格运动,而是通过将若干个网格顶点聚合为一个通道(target),并通过定义每个顶点的position和normal,“捏出”该通道形变后的状态。每个状态即是一个关键帧,在两帧极值之间,通过取0和1之间的权重数据进行插值形成。

当前的通道权重信息,就存储在weights属性里,extra中的targetName属性,指明了每个通道的名称。 插值计算本身的计算效率很高,但存储关键帧的数据量庞大,是一种用空间换时间的策略。应用领域很广泛,比如用于角色捏脸。

形变动画的存储并没有统一标准,不同文件格式会设计不同的机制。glTF选择存储在mesh中,这样设计的好处是省去了一级索引,targets中的下标即对应顶点数组,但坏处是如果一个网格中只有少量顶点被通道包含,那么会存在大量冗余的位被设置为0。

skins

骨骼蒙皮信息,定义了mesh中的每个顶点受骨骼影响的权重信息。将其和meshes,nodes的信息结合,即可表达骨骼动画的基本结构。每个图元类型的node,可以持有一个mesh和一个skin索引,skin的joints里存储了node的下标,表示该图元受到哪些骨骼的影响,以及每块骨骼的逆矩阵。

逆矩阵是一个重要的信息,用于计算骨骼动画时,把节点的变化从全局坐标变回局部坐标。如果不这样做,我们算出来的节点位置就是叠加了骨骼矩阵本身的双重变化,从而出现错误的结果。

代码语言:javascript
复制
jointMatrix[j] =
  inverse(globalTransform) *
  globalJointTransform[j] *
  inverseBindMatrix[j];

结合skin和nodes的信息,使用上面的公式,我们可以算出每个骨骼的变化矩阵。

同时,我们在受到骨骼影响的meshes内部,定义了JOINTS和WEIGHTS数组,储存每个顶点受骨骼影响的权重信息。 注意,glTF格式也使用了普遍的假定——每个顶点最多受到四块骨骼影响,所以JOINTS和WEIGHTS数组的长度通常是顶点数组的4倍。

三者之间的引用关系以下图表示。

material、textures、images、samplers

上述四种结构定义了材质和纹理信息。 material材质支持设置PBR(Physically Based Rendering,基于物理属性的渲染)属性,渲染时方便转化为PBR渲染中的各项参数,默认使用Metallic-Roughness-Model,具体的参数这里不再赘述。

textures储存了纹理资源,可以引用某一个图片images,也可以直接写入文件的二进制数据。纹理可以被几何单元(mesh)引用,也可以被材质(material)引用,纹理坐标则由一个accessor获得。

纹理资源的采样器,可以使用sampler来定义,其中的参数都可以直接交给基于gl api的渲染引擎使用。

animations

用于存储动画信息,静态模型可以忽略此结构。

总结

glTF作为一种通用模型交换格式,可以容纳常见的3d模型所必须的信息,由于采用json结构表达,也非常适合前端同学入门学习。在blender等建模软件、unity等游戏引擎,threejs等动态运行时库中,均获得了比较好的支持。

参考资料

glTF 2.0 Quick Reference Guide(https://www.khronos.org/files/gltf20-reference-guide.pdf

https://github.com/KhronosGroup/glTF

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是glTF?
  • glTF的设计思想
  • glTF文件结构概览
  • 存储结构
  • 几何属性
    • scenes、nodes
      • meshes
        • skins
          • material、textures、images、samplers
            • animations
            • 总结
            • 参考资料
            相关产品与服务
            文件存储
            文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档