Buffers,BufferViews,Accessors

glTF系列教程05

Posted by WunWun on July 22, 2017

又复习了一下glTF模型,发现了一个很好的英文教程,讲解的非常详细。没有图形学知识背景的人也可以听懂。学习的时候,就顺便翻译成中文,来和大家分享 。当然,更推荐看英文教程

Buffers, BufferViews, Accessors

buffer, bufferViewaccessor 的示例已经 最小glTF文件部分中给出。 本节将更详细地解释这些概念。

Buffers

buffer 表示原始二进制数据的块,没有固有的结构或含义, 可以通过 uri 来引用这个数据。 此URI可以指向外部文件,也可以指向直接在JSON文件中对二进制数据进行编码的 data URI最小glTF文件 包含一个 buffer示例,它包含42个字节的,编码在 data URI中的数据,

"buffers" : {
  "buffer0" : {
    "uri" : "data:application/octet-stream;base64,AAABAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAA",
    "byteLength" : 42
  }
},

java-javascript 图 5a: buffer 数据

buffer 的部分数据可以作为顶点属性、索引,或者包含蒙皮信息、动画关键帧的数据。传递到渲染器, 为了能够使用该数据,需要关于该数据的结构和类型的附加信息。

BufferViews

buffer 构造数据的第一步是使用 bufferView对象。 bufferView 表示一个缓冲区的数据的“切片”, 此切片使用偏移和长度(以字节为单位)定义。 最小glTF文件中定义了两个 bufferView 对象:

"bufferViews" : {
  "indicesBufferView" : {
    "buffer" : "buffer0",
    "byteOffset" : 0,
    "byteLength" : 6,
    "target" : 34963
  },
  "positionsBufferView" : {
    "buffer" : "buffer0",
    "byteOffset" : 6,
    "byteLength" : 36,
    "target" : 34962
  }
},

如图所示:第一个bufferView引用缓冲区数据的前6个字节,第二个bufferView引用剩余的36个字节,

java-javascript 图 5b: 指向部分 buffer 的buffer views

每个 bufferView 包含一个 target 属性. 这个属性稍后可以被渲染器用来确定数据的类型和属性。 target 可以是常量,表示数据用于顶点属性(34962,代表GL_ARRAY_BUFFER),或者数据用于顶点索引(34963,代表GL_ELEMENT_ARRAY_BUFFER)。

此时,buffer数据已被分成多个部分,每个部分由一个bufferView描述。 但为了在渲染器中真正使用此数据,还需要有关数据类型和布局的其他信息。

Accessors

一个 accessor对象引用 bufferView,并且包含定义此bufferView的数据类型和布局的属性。

数据类型

accessor的数据类型信息编码在 typecomponentType 属性中。 type 属性的值是一个字符串,指定数据元素是标量,向量还是矩阵。例如, "SCALAR" 表示标量值; "VEC3" 表示三维矢量;"MAT4" 表示 4x4 矩阵;

componentType 指定数据分量的类型。这是一个GL常量,比如 5126 (GL_FLOAT ) 表示浮点数; 5123 (GL_UNSIGNED_SHORT)表示无符号短整型。

这些属性的不同组合可用于描述任意数据类型。 例如, 最小 glTF 文件包含两个accessor

"accessors" : {
  "indicesAccessor" : {
    "bufferView" : "indicesBufferView",
    "byteOffset" : 0,
    "componentType" : 5123,
    "count" : 3,
    "type" : "SCALAR",
    "max" : [ 2.0 ],
    "min" : [ 0.0 ]
  },
  "positionsAccessor" : {
    "bufferView" : "positionsBufferView",
    "byteOffset" : 0,
    "componentType" : 5126,
    "count" : 3,
    "type" : "VEC3",
    "max" : [ 1.0, 1.0, 0.0 ],
    "min" : [ 0.0, 0.0, 0.0 ]
  }
},

第一个accessor引用 "indicesBufferView",它的 type"SCALAR"componentType5123 (GL_UNSIGNED_SHORT)。这表示该索引以无符号短整型的标量形式存储。第二个accessor引用 "positionsBufferView",它的 type"VEC3"componentType5126 (GL_FLOAT)。这个访问器描述了一个分量为浮点类型的三维矢量。下图说明了如何使用bufferView 对象构造缓冲区的原始数据,并使用 accessor对象扩展数据类型信息:

java-javascript 图 5c: accessors 定义了如何解析 buffer views

数据布局

accessor 的附加属性还指定数据布局。 accessorcount 属性表示它包含多少个数据元素。 在上面的例子中,两个 accessorcount都为3,分别代表三角形的3个索引和3个顶点。

每个accessor也可以定义 byteOffsetbyteStride 属性。 对于作为结构数组存储(Array-Of-Structures)的数据,这些属性是必需的:例如单个 bufferView 可以以交织方式存储顶点位置的数据和顶点法线的数据。 byteOffset定义第一相关数据元素的开始。 byteStride定义直到下一个相关数据元素开始的字节数:

java-javascript 图 5d: 访问器的偏移和步幅

数据内容

accessor还包含汇总其数据内容的minmax属性。 它们是包含在访问器中的所有数据元素分量的最小值和最大值。 对于顶点位置的情况,minmax属性因此定义对象的包围框。 这对于确定下载的优先级或可见性检测很有用。 一般来说,此信息对于存储和处理量子化数据(quantized data)也非常有用(量子化数据在运行时被渲染器解析),但是该量子化的细节超出了本教程的范围。

著作权声明

作者 陈兴旺,首次发布于 WunWun Blog,转载请保留以上链接