5 gltf:buffer缓存、bufferView视窗、accesors访问器

总目录 >> threejs入门进阶到实战(目前已更新入门篇、基础篇和进阶篇)

5 buffer缓存、bufferView视窗、accesors访问器

buffer, bufferView,和 accessor 对象已经在**3、最小GLTF文件 **提到,本节将会详细解释它们的含义。

Buffers 缓存

缓冲区buffer表示原始二进制数据块,没有内在的结构或含义。缓冲区使用其uri引用此数据。这个URI可以指向外部文件,也可以是直接在JSON文件中编码二进制数据的数据URI。最小的glTF文件包含一个缓冲区示例,其中包含44字节的数据,编码在数据URI中:

"buffers" : [
    {
      "uri" : "data:application/octet-stream;base64,AAABAAIAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAA=",
      "byteLength" : 44
    }
  ],


图5a: 缓冲区数据,包括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字节,如图所示:

图 5b: buffer views缓冲区视图, 指向缓冲区的各部分

浅灰色显示的字节(有2个字节的位置,也就是6-8)是正确对齐访问器accesors所需的填充字节,如下所述。
每个bufferView还包含一个目标target属性。渲染器程序可以稍后使用此属性对缓冲区视图引用的数据的类型或性质进行分类。目标target可以是一个常量,表示数据用于顶点属性(34962,表示数组缓冲区ARRAY_BUFFER),或数据用于顶点索引(34963,表示元素数组缓冲区ELEMENT_ARRAY_BUFFER)。
此时,buffer缓冲区数据被划分为了多个部分,每个部分由一个bufferView描述。但是为了在渲染器中真正使用这些数据,需要有关数据类型和布局的其他信息。

Accessors访问器

访问器accessor对象指向bufferView并包含定义此bufferView的数据类型和布局的属性。

Data type 数据类型

访问器数据的类型在typecomponentType属性中被编码。type属性的值是一个字符串,表示数据元素是标量、向量还是矩阵。例如,对于标量值,使用"SCALAR";对于三维向量,该值可以是"VEC3";对于4×4矩阵,该值可以是"MAT4"
componentType指定这些数据元素的组件的类型。这是一个GL常量,可以是5126FLOAT)或5123UNSIGNED_SHORT),以指示元素分别具有FLOATUNSIGNED 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”,它的componentType5123UNSIGNED_SHORT)。这意味着索引存储为标量无符号短值。
第二个访问器引用索引为1的bufferView,它定义了包含顶点属性(特别是顶点位置)的部分缓冲区数据。其类型为“VEC3”,其组件类型为5126FLOAT)。所以这个访问器用浮点组件来描述三维向量。

Data layout 数据布局

访问器accessor的其他属性进一步指定数据的布局。访问器的count属性指示它包含多少数据元素。在上面的例子中,两个访问器的计数count都是3,分别代表三角形的三个索引和三个顶点。每个访问器也有一个字节偏移量byteOffset属性。对于上面的示例,两个访问器都是0,因为每个bufferView只有一个访问器。但是,当多个访问器引用同一个bufferView时,byteOffset描述访问器的数据相对于它引用的bufferView的起始位置。

Data alignment 数据对齐

访问器accessor引用的数据可以被发送到图形卡进行渲染,或者在主机端用作动画或蒙皮数据。因此,访问器accessor的数据必须根据数据类型进行对齐。例如,当访问器的组件类型componentType5126FLOAT)时,数据必须在4字节边界处对齐,因为单个FLOAT值由4字节组成。accessor访问器的这种对齐要求引用其bufferView和底层缓冲区buffer。对齐的具体要求如下:

  • accessor访问器的字节偏移量byteOffset必须可被其组件类型componentType的大小整除。
  • accessor访问器的字节偏移量byteOffset与其引用的bufferView的字节偏移量byteOffset之和必须可被其组件类型componentType的大小整除。

在上面的示例中,bufferView的索引1 的字节偏移量byteOffset(指顶点属性)的选择为8,以便将顶点位置的访问器数据与4字节边界对齐。因此,缓冲区的字节6和7填充了不携带相关数据的字节。
图5c说明了如何使用bufferView对象构造缓冲区的原始数据,并使用访问器对象用数据类型信息进行扩充。

图5c: accessors访问器定义了如何去解释缓存区视窗中的数据
(此处的indices 也是occ这一块需要加强的部分)

Data interleaving 数据交织

The data of the attributes that are stored in a single bufferView may be stored as an Array-Of-Structures. A single bufferView may, for example, contain the data for vertex positions and for vertex normals in an interleaved fashion. In this case, the byteOffset of an accessor defines the start of the first relevant data element for the respective attribute, and the bufferView defines an additional byteStride property. This is the number of bytes between the start of one element of its accessors, and the start of the next one. An example of how interleaved position and normal attributes are stored inside a bufferView is shown in Image 5d.

存储在单个bufferView中的属性数据可以存储为结构数组(Array-Of-Structures.)。例如,单个bufferView可以以交错方式包含顶点位置(position)和顶点法线(normal)的数据。在这种情况下,访问器的字节偏移量byteOffset定义了相应属性的第一个相关数据元素的开始,bufferView定义了一个额外的byteStride属性。这是访问器的一个元素开始与下一个元素开始之间的字节数。图5d显示了一个如何在bufferView中存储交错位置和正常属性的示例。

Image 5d: Interleaved acessors 访问器交织在 缓冲视窗

Data contents 数据内容

访问器accessor还包含总结其数据内容的最小min和最大max属性。它们是访问器中包含的所有数据元素的组件最小值和最大值。在顶点位置的情况下,“最小”和“最大”属性定义对象的边界框。这对于确定下载的优先级或可见性检测非常有用。通常,此信息对于存储和处理渲染器在运行时取消量化的量化数据也很有用,但是此量化的详细信息超出了本教程的范围。

Sparse accessors 稀疏访问器(暂不考虑)

(两个数据块只是几个顶点数据不同的情况下才会用。)
在2.0版中,glTF引入了稀疏访问器的概念。这是一种特殊的数据表示形式,允许非常紧凑地存储只有几个不同条目的多个数据块。例如,当存在包含顶点位置的几何数据时,该几何数据可用于多个对象。这可以通过引用来自两个对象的相同访问器来实现。如果两个对象的顶点位置基本相同,只是几个顶点不太同,则不必将整个几何数据存储两次。相反,可以只存储一次数据,并使用稀疏访问器只存储第二个对象不同的顶点位置。
以下是一个完整的glTF资产,以嵌入式表示,显示了稀疏访问器的示例:

{
  "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所示:
image.png
图 5e: 呈现简单稀疏访问器资源的结果。

该示例包含两个访问器:一个用于网格索引,另一个用于顶点位置。引用顶点位置的属性定义了一个附加的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
      }
    }
  } ],

This sparse object itself defines the count of elements that will be affected by the substitution. The sparse.indices property refers to a bufferView that contains the indices of the elements which will be replaced. The sparse.values refers to a bufferView that contains the actual data.
In the example, the original geometry data is stored in the bufferView with index 1. It describes a rectangular array of vertices. The sparse.indices refer to the bufferView with index 2, which contains the indices [8, 10, 12]. The sparse.values refers to the bufferView with index 3, which contains new vertex positions, namely, [(1,2,0), (3,3,0), (5,4,0)]. The effect of applying the corresponding substitution is shown in Image 5f.

sparse稀疏对象本身定义将受替换影响的元素的计数countsparse.indexs属性引用一个bufferView,它包含将被替换的元素的索引。sparse.values引用包含实际数据的bufferView
在本例中,原始几何数据存储在带有索引1的bufferView中。它描述了一个顶点的矩形数组。sparse.index是指带有索引2的bufferView,它包含索引[8、10、12]。sparse.values是指索引为3的bufferView,它包含新的顶点位置,即[(1,2,0),(3,3,0),(5,4,0)]。应用相应替换的效果如图5f所示。
image.png
Image 5f: The substitution that is done with the sparse accessor.

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值