gltf教程系列-缓冲区,缓冲区视图和访问器(五)
目录
buffer
,bufferView
以及accessor
对象
已经在最小glTF文件部分提到。本节将更详细地解释这些概念。
buffers缓冲区
buffer
表示原始二进制数据块,没有固有的结构或含义。该数据通过其引用uri
由
缓冲区使用。此URI可以指向外部文件,也可以是直接在JSON文件中编码二进制数据的数据URI。最小glTF文件包含的一个buffer
例子,具有44个字节的数据,就是在数据URI编码:
"buffers" : [
{
"uri" : "data:application/octet-stream;base64,AAABAAIAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAA=",
"byteLength" : 44
}
],

buffer
数据的一部分可能必须作为顶点属性或索引,或者可能包含皮肤信息或动画关键帧的数据传递给渲染器。为了能够使用此数据,需要有关此数据的结构和类型的其他信息。
BufferViews
buffer
构造数据的第一步是使用bufferView
对象。一个bufferView
表示一个缓冲区的数据的“切片”。使用偏移量和长度(以字节为单位)定义此切片。最小glTF文件定义了两个bufferView
对象:
"bufferViews" : [
{
"buffer" : 0,
"byteOffset" : 0,
"byteLength" : 6,
"target" : 34963
},
{
"buffer" : 0,
"byteOffset" : 8,
"byteLength" : 36,
"target" : 34962
}
],
第一个bufferView
是指缓冲区数据的前6个字节。第二个引用缓冲区的36个字节,偏移量为8个字节,如下图所示:

以浅灰色显示的字节是正确对齐访问器所需的填充字节,如下所述。
每个bufferView
附加包含一个target
属性。随后渲染器可以使用此属性来分类缓冲区视图所引用的数据的类型或性质。target
可以是一个常量指示数据是用于顶点属性(34962
,表示ARRAY_BUFFER
),或者该数据被用于顶点索引(34963
,表示ELEMENT_ARRAY_BUFFER
)。
此时,buffer
数据已被分成多个部分,每个部分由一个部分描述bufferView
。但是要真正在渲染器中使用此数据,需要有关数据类型和布局的其他信息。
accessor访问器
一个accessor
对象是指一种bufferView
,它
包含定义本数据的类型和布局的属性。
数据类型
访问器的数据类型在type
和componentType
属性中编码。type
属性的值是一个字符串,它指定数据元素是标量,向量还是矩阵。例如,该值可以是"SCALAR"-
标量值,"VEC3"-
3D矢量或"MAT4"-
4×4矩阵。
在componentType
指定了这些数据元素的组分的类型。例如GL常数可以是5126
(FLOAT
)或5123
(UNSIGNED_SHORT
),以分别指示元素具有float
或unsigned short
成分。
可以使用这些不同的属性组合来描述任意数据类型。例如,最小glTF文件包含两个访问器:
"accessors" : [
{
"bufferView" : 0,
"byteOffset" : 0,
"componentType" : 5123,
"count" : 3,
"type" : "SCALAR",
"max" : [ 2 ],
"min" : [ 0 ]
},
{
"bufferView" : 1,
"byteOffset" : 0,
"componentType" : 5126,
"count" : 3,
"type" : "VEC3",
"max" : [ 1.0, 1.0, 0.0 ],
"min" : [ 0.0, 0.0, 0.0 ]
}
],
第一个访问器引用索引0的bufferView
,它定义buffer
数据包含索引的部分。它type
是"SCALAR"
,它componentType
是5123
(UNSIGNED_SHORT
)。这意味着索引存储为标无符号短整型unsigned short
值。
第二个访问器引用索引1的bufferView
,它定义buffer
数据包含顶点属性的部分– 特别是顶点位置。它的类型是"VEC3"
,它componentType
是 5126
(FLOAT
)。因此,该访问器描述了具有浮点值的3D矢量。
数据布局
accessor
其他属性进一步指定数据的布局。accessor
的count
属性表示它包含多少数据元素。在上面的示例中,计数为
3
表示
两个accessor
的计数分别代表三个索引和三角形的三个顶点。每个accessor
也有一个byteOffset
属性。上例中两个accessor
都是
0
,因为每个accessor
只有一个bufferView
。但是当多个accessor
引用相同时bufferView
,则byteOffset
描述accessor相对于bufferView
它所引用的数据的开始位置。
数据对齐
accessor
引用的数据可以被发送到图形卡用于渲染,或者在主机用作动画或蒙皮数据。因此,accessor
必须根据数据的类型对齐数据。例如,当一个accessor
的
componentType
a为5126
(FLOAT
)时,数据必须以4字节边界对齐,因为单个float
值由4个字节组成。accessor
这种对齐要求指的是它的bufferView
和它的基础buffer
。特别的,对准要求如下:
accessor
的偏移值
必须能被它的componentType
大小整除。accessor
的偏移值及其指向的
bufferView
的偏移值之和
必须能被它的componentType
大小整除。
在上面的例子中,索引为1的bufferView
(它指的是顶点属性)的偏移值
为8
,以便对齐accessor
中顶点数据的4字节边界位置。Buffer
的
6
和7
字节因此填充不相关数据。
图5c示出了如何使用bufferView
对象来构造buffer
的原始数据,并且使用accessor
对象来扩充数据类型信息。

数据交织
存储在单个bufferView
中的属性数据可以存储为结构阵列。例如单个bufferView
可以以交错的方式包含顶点位置和顶点法线的数据。在这种情况下,accessor
的偏移值
定义了相应属性的第一个相关数据元素的开始,并bufferView
额外定义了一个byteStride
属性。这是accessor
中一个元素起始到下一个元素起始之间的字节数。图5d为交错位置和普通属性如何存储在bufferView
中的一个示例。

数据内容
accessor
还包含汇总其数据内容的min
和max
属性。它表示accessor访问器中所有数据元素的最小值和最大值。在顶点位置accessor
中
,min
和max
属性定义了对象的边界框bounding box。这对于下载优先级或可见性检测非常有用。通常,此信息对于渲染器存储和处理量化数据(在运行时非量化)也很有用,但此量化的详细信息超出了本教程的范围。
稀疏accessor
在2.0版本中,glTF引入了稀疏accessor访问器的概念。这是数据的特殊表示,允许将仅具有少量不同条目的多个数据块极大压缩存储。例如,当存了包含顶点位置的几何数据时,此几何数据可用于多个对象。这可以通过两个对象引用相同的accessor
来实现。如果两个对象的顶点位置大部分相同且仅在几个顶点上不同,则不必将整个几何数据存储两次。相反,可以仅存储一次数据,并使用稀疏存取器仅存储第二个对象不同的顶点位置。
以下是嵌入式表示中的完整glTF结构,它显示了稀疏存取器 sparse accessors的示例:
{
"scenes" : [ {
"nodes" : [ 0 ]
} ],
"nodes" : [ {
"mesh" : 0
} ],
"meshes" : [ {
"primitives" : [ {
"attributes" : {
"POSITION" : 1
},
"indices" : 0
} ]
} ],
"buffers" : [ {
"uri" : "data:application/gltf-buffer;base64,AAAIAAcAAAABAAgAAQAJAAgAAQACAAkAAgAKAAkAAgADAAoAAwALAAoAAwAEAAsABAAMAAsABAAFAAwABQANAAwABQAGAA0AAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAQAAAAAAAAAAAAABAQAAAAAAAAAAAAACAQAAAAAAAAAAAAACgQAAAAAAAAAAAAADAQAAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAQAAAgD8AAAAAAABAQAAAgD8AAAAAAACAQAAAgD8AAAAAAACgQAAAgD8AAAAAAADAQAAAgD8AAAAACAAKAAwAAAAAAIA/AAAAQAAAAAAAAEBAAABAQAAAAAAAAKBAAACAQAAAAAA=",
"byteLength" : 284
} ],
"bufferViews" : [ {
"buffer" : 0,
"byteOffset" : 0,
"byteLength" : 72,
"target" : 34963
}, {
"buffer" : 0,
"byteOffset" : 72,
"byteLength" : 168
}, {
"buffer" : 0,
"byteOffset" : 240,
"byteLength" : 6
}, {
"buffer" : 0,
"byteOffset" : 248,
"byteLength" : 36
} ],
"accessors" : [ {
"bufferView" : 0,
"byteOffset" : 0,
"componentType" : 5123,
"count" : 36,
"type" : "SCALAR",
"max" : [ 13 ],
"min" : [ 0 ]
}, {
"bufferView" : 1,
"byteOffset" : 0,
"componentType" : 5126,
"count" : 14,
"type" : "VEC3",
"max" : [ 6.0, 4.0, 0.0 ],
"min" : [ 0.0, 0.0, 0.0 ],
"sparse" : {
"count" : 3,
"indices" : {
"bufferView" : 2,
"byteOffset" : 0,
"componentType" : 5123
},
"values" : {
"bufferView" : 3,
"byteOffset" : 0
}
}
} ],
"asset" : {
"version" : "2.0"
}
}
渲染此结构的结果如图5e所示:

该示例包含两个accessor访问器:一个用于格网的索引,另一个用于顶点位置。引用顶点位置的那个定义了一个附加accessor.sparse
属性,其中包含有关应该应用的稀疏数据替换的信息:
"accessors" : [
...
{
"bufferView" : 1,
"byteOffset" : 0,
"componentType" : 5126,
"count" : 14,
"type" : "VEC3",
"max" : [ 6.0, 4.0, 0.0 ],
"min" : [ 0.0, 0.0, 0.0 ],
"sparse" : {
"count" : 3,
"indices" : {
"bufferView" : 2,
"byteOffset" : 0,
"componentType" : 5123
},
"values" : {
"bufferView" : 3,
"byteOffset" : 0
}
}
} ],
sparse
对象本身定义了将受替换影响的元素个数。sparse.indices
属性指的是包含将被替换元素索引的bufferView
。sparse.values
指bufferView
包含实际数据。
在该示例中,原始几何数据存储在索引1的bufferView
with中。它描述了一个矩形的顶点数组。sparse.indices
指向索引为2的bufferView
,其中包含[8, 10, 12]
的索引。sparse.values
指索引为3的bufferView
,其中包含新的顶点位置,即[(1,2,0), (3,3,0), (5,4,0)]
。应用相应取代的效果如图5f所示。

转载自:https://blog.csdn.net/xiaowanzi29/article/details/84623972