1、数据结构
图像库传输格式(Graphic Library Transmission Format, glTF)使用的是JSON格式。以3D场景为根节点组织数据,对场景结构进行描述的场景图。通过网格、材质、相机、动画、皮肤、纹理等节点的定义和关联,实现3D场景的描述。其中,材质、皮肤定义了3D对象的外观,动画定义了3D对象的变换操作(如选择、平移操作)。网格定义了3D对象如何的骨骼变换,相机定义了渲染程序的视锥体设置等。
基本结构如下:

2、对3D基本概念的支持
(1)坐标系统和单位

(2)几何体
网格体(Meshes):
一个节点Node可以定义网格体和形变参数,网格体也可以附加皮肤。网格体由原型类的数组组成,而原型类是针对GPU调用而组织的。原型类定义了网格体顶点的属性,方便GPU调用。原型类还定义了索引。属性和索引可以被相关包含数据的类进行访问和引用。每个原型类也可以指定与GPU拓扑类型相对应的材质和模式。原型类定义如下:
{
"meshes": [
{
"primitives": [
{
"attributes": {
"NORMAL": 23,
"POSITION": 22,
"TANGENT": 24,
"TEXCOORD_0": 25
},
"indices": 21,
"material": 3,
"mode": 4
}
]
}
]
}其属性包括:
| 名称 | 访问器类型 | 类型 | 说明 |
|---|---|---|---|
| POSITION | VEC3 | float | XYZ的坐标顶点 |
| NORMAL | VEC3 | float | XYZ的坐标顶点法线 |
| TANGENT | VEC3 | float | XYZW顶点法线的切线,W为切线指示的符号,其值为(-1或+1) |
| TEXCOORD_n | VEC2 | float/unsigned byte normalized/unsigned short normalized | 纹理坐标 |
| COLOR_n | VEC2 VEC4 | float/unsigned byte normalized/unsigned short normalized | RGB或RGBA顶点颜色线性乘子 |
| JONITS_n | VEC4 | unsigned byte /unsigned short | |
| WEIGHT_n | VEC4 | float/unsigned byte normalized/unsigned short normalized |
形变:
形变是对Mesh的扩展,其实质是给原型类对象的属性加入一组的权重值,从而改变原型网格体产生的。运算方式如下:
primitives[i].attributes.POSITION +
weights[0] * primitives[i].targets[0].POSITION +
weights[1] * primitives[i].targets[1].POSITION +
weights[2] * primitives[i].targets[2].POSITION + ...
形变就是通过原型类中的targerts属性定义而实现的。而这个target数组通过JSON对象传入原型对象:
{
"primitives": [
{
"attributes": {
"NORMAL": 23,
"POSITION": 22,
"TANGENT": 24,
"TEXCOORD_0": 25
},
"indices": 21,
"material": 3,
"targets": [
{
"NORMAL": 33,
"POSITION": 32,
"TANGENT": 34
},
{
"NORMAL": 43,
"POSITION": 42,
"TANGENT": 44
}
]
}
],
"weights": [0, 0.5]
}皮肤:
皮肤存储于skins数据中。每个皮肤都由三个关键参数决定,一个是联接节点joints,一个是反向绑定矩阵inverseBindMatrices访问器,还有骨骼skeleton属性。联接节点是皮肤作用的节点范围,反向绑定矩阵指出了皮肤放置于联接节点的位置,骨骼节点为联接层级(Joint Hierarchy)指出了根节点或是一个直接或间接的父节点。
{
"nodes": [
{
"name": "node_0",
"children": [ 1 ],
"translation": [ 0.0, 1.0, 0.0 ]
},
{
"name": "node_1",
"children": [ 2 ],
"scale": [ 0.5, 0.5, 0.5 ]
},
{
"name": "node_2"
},
{
"name": "node_3",
"children": [ 4 ],
"translation": [ 1.0, 0.0, 0.0 ]
},
{
"name": "node_4",
"mesh": 0,
"rotation": [ 0.0, 1.0, 0.0, 0.0 ],
"skin": 0
}
],
"skins": [
{
"inverseBindMatrices": 0,
"joints": [ 1, 2 ],
"skeleton": 1
}
]
}(3)纹理数据
纹理包括三类:纹理、图片和采集器。
纹理由两个属性来定义,一个是图片来源,二是采集器索引。
{
"textures": [
{
"sampler": 0,
"source": 2
}
]
}图片:
每个图片或具其中一项:
- 一个URI,其指向的支持文件格式的外部文件;
- 一个数据URI,其自带嵌入数据;
- 一个带BufferView的索引(在此图片的mimeType必须被指定)。
{
"images": [
{
"uri": "duckCM.png"
},
{
"bufferView": 14,
"mimeType": "image/jpeg"
}
]
}采集器:
采集器需要指明过滤和打包模式。过滤模式控制着纹理的放大和缩小。打包模式定义了如何处理纹理的像素坐标,主要模式有:重复、镜像重复、夹边。
{
"samplers": [
{
"magFilter": 9729,
"minFilter": 9987,
"wrapS": 10497,
"wrapT": 10497
}
]
}(4)材质
glTF支持包括物理材质渲染(PBR)、金属粗糙度模型等材质模型,能实现跨平台的应用展示。
1)物理材质渲染(PBR):是指基于多种光照模型模拟物体反射、散射、折射等过程的渲染技术。传统的光照模型包括Lambert漫反射模型、Phong模型、Blinn-Phong模型等,PBR模型有BRDR表面反射、fresnel反射、子表面折射等。
2)金属粗糙度材质:主要由基础色、金属质、粗糙度三个变量来定义。
{
"materials": [
{
"name": "gold",
"pbrMetallicRoughness": {
"baseColorFactor": [ 1.000, 0.766, 0.336, 1.0 ],
"metallicFactor": 1.0,
"roughnessFactor": 0.0
}
}
]
}3)附加纹理:
法线纹理:是一种切线空间法线纹理。纹理将切线空间中的法线编码为XYZ值作为RGB值存储于线性转换函数中。法线纹理不能包括alpha通道。在均一化后,纹理值为:
- 红色通道:red [0.0 .. 1.0] 转换为 X [-1 .. 1]
- 绿色通道:green [0.0 .. 1.0] 转换为 Y [-1 .. 1]
- 蓝色通道:blue (0.5 .. 1.0] 转换为 Z (0 .. 1]
遮挡纹理:它是接收较少环境光的一种指示,常由红色通道来指示,0代表完全遮挡,1代表没有遮挡。
发光纹理:此纹理主要由8位的sRGB光电传输函数编码来实现,因此在其应用时就需要提前将RGB的值解码为真实的值。
4)透明层(alpha Coverage):
透明层模型由以下定义:
- 不透明——渲染输出完全不透明,任何alpha值都将被忽略。
- 遮挡——透明度的输出主要取决于alpha的值。
- 混合——此模式的支持各不相同。
5)双面
当此属性为假时,正面三角将被渲染。
当此属性为真时,正面照明将启用,背面消隐将禁用。
6)默认材质
当网格没有指定材料时使用的默认材料。
7)点线材质
除了面层外,点线材质的一般性规范为:
- 点和线在视口空间中一般有 1个像素的宽度。
- 具有 NORMAL 和 TANGENT 属性的点或线应使用标准照明进行渲染。
- 具有 NORMAL 但没有 TANGENT 属性的点或线使用标准照明渲染,但忽略材质上的任何法线纹理。
- 没有 NORMAL 属性的点或线应该在没有光照的情况下渲染,而是使用基色值和发射值的总和。
(5)摄像
每个相机都定义了一个 type 属性来指定投影的类型(透视或正交),以及一个透视或正交属性来定义细节。 使用node.camera属性在节点内实例化相机。相机对象定义了将场景坐标从视图空间转换到剪辑空间的投影矩阵。
相机实例的节点定义了将场景坐标从全局空间转换到视图空间的视图矩阵。
1)视图矩阵
相机定义为局部 +X 轴在右侧,“镜头”朝向局部 -Z 轴,相机顶部与局部 +Y 轴对齐。
视图矩阵来自包含相机的节点的全局变换,而忽略了缩放。 如果节点的全局变换是唯一的,则相机的位置在原点。
2)投影方法
投影可以是透视或正交。
透视:无限透视投影、有限透视投影。
(6)动画
所有动画都存储在动画数组中。动画由一组通道(通道属性)和一组采样器组成,这些采样器指定关键帧和插值采样器。
采样器:每个动画的采样器都定义了输入/输出对:一组表示线性时间(以秒为单位)的浮点和一组表示动画属性的向量或标量。
关键帧之间的插值是使用插值属性中指定的插值方法执行的。支持的插值方法包括 LINEAR、STEP 和 CUBICSPLINE。
示例:
