glTF BufferView Byte Offsets and Stride Explained
In a glTF asset, the bufferView component bridges raw
binary blobs and high-level 3D model data by carving a contiguous chunk
out of a buffer. It establishes structural boundaries using
properties such as byteOffset to designate the starting
point of data within a file, and byteStride to dictate the
byte distance between consecutive vertex attributes. Together, these
properties tell rendering engines exactly where to read and how to
unpack geometry and animation streams in memory.
The Role of
bufferView in glTF Memory Architecture
A standard glTF file organizes binary data in three tiers:
buffer: The raw, unformatted binary array (often an external.binfile or base64-encoded URI).bufferView: A defined window or segment of abufferthat specifies layout, intended target use (such as an array buffer or element array buffer), and optional byte spacing.accessor: The typed interpretation layer (e.g.,VEC3ofFLOAT) that points into abufferView.
How
byteOffset Establishes Data Starting Points
The byteOffset property inside a bufferView
defines the zero-indexed byte index where the slice begins within the
parent buffer.
- Default Value: If omitted,
byteOffsetdefaults to0. - Alignment Requirements: The offset must align to multiples of the component types stored within it. For standard WebGL/OpenGL compatibility, glTF specifications recommend aligning offsets to 4-byte boundaries.
- Offset Stacking: An individual
accessoralso has an optionalbyteOffset. The true memory location of a given attribute is calculated by summing both offsets:totalOffset = bufferView.byteOffset + accessor.byteOffset.
This separation allows one bufferView to represent a
collection of attributes (such as all data for a single mesh) while
individual accessors pinpoint where specific components (like positions
or normals) reside within that view.
How
byteStride Governs Interleaved Data
The byteStride property sets the byte distance from the
start of one attribute element to the start of the next. It primarily
determines whether vertex data is stored sequentially or
interleaved.
- Tightly Packed Data (Omitted
byteStride): WhenbyteStrideis omitted or left undefined, data elements are assumed to be contiguous. For example, if an accessor reads an array of 12-byteVEC3floats, each new vector immediately follows the previous one. - Interleaved Data (Explicit
byteStride): When multiple vertex attributes share the samebufferViewin an interleaved format (e.g.,[Position, Normal, UV, Position, Normal, UV]),byteStridespecifies the full byte size of one complete vertex record. - Constraints:
byteStridemust be a multiple of 4.- It must fall within the range of 4 to 252 bytes.
- It can only be defined when the
bufferViewis referenced by vertex attribute accessors; it is strictly prohibited for index data (ELEMENT_ARRAY_BUFFER) or animation keyframe data.
Practical Layout Example
Consider a vertex definition containing a 3D position
(VEC3 floats = 12 bytes) and a 2D texture coordinate
(VEC2 floats = 8 bytes) interleaved per vertex:
- A single vertex takes up 20 bytes total.
- The
bufferViewdefinesbyteStride: 20and starts atbyteOffset: 0. - The Position
accessorpoints to thisbufferViewwithbyteOffset: 0. - The Texture Coordinate
accessorpoints to the samebufferViewwithbyteOffset: 12.
During rendering, the graphics pipeline jumps 20 bytes forward for every vertex, reading 12 bytes for position starting at offset 0, and 8 bytes for UV coordinates starting at offset 12, successfully reconstructing the complete mesh geometry from a single continuous stream.