BufferLayout
描述缓冲区内存与着色器属性的对应关系:谁在哪个偏移、用什么格式读、逐顶点还是逐实例。 在 v9 里它是一个类型别名,不是类,也没有构造函数。
luma.BufferLayout 在运行期不存在,写 new BufferLayout() 会抛错。
正确做法是给管线或模型的 bufferLayout 传一个对象数组。
字段
| 字段 | 说明 |
|---|---|
name | 缓冲区名,属性名与它同名时可直接映射 |
format | 单个属性使用的顶点格式,如 float32x3 |
stepMode | vertex 逐顶点步进,instance 逐实例步进 |
byteStride | 相邻元素之间的字节跨度,省略时按紧密排列计算 |
attributes | 交错布局的成员数组,每项含 attribute、format、byteOffset |
一个缓冲区一个属性
最常见的形式:属性名与缓冲区名相同,格式直接写在条目上。
着色器里声明 in vec3 positions,这里就写 float32x3。
const bufferLayout = [
{ name: 'positions', stepMode: 'vertex', format: 'float32x3' },
{ name: 'colors', stepMode: 'vertex', format: 'float32x3' }
];
交错布局
位置、法线、颜色交错在同一段内存里时,用 attributes 描述每个成员的偏移,
再用 byteStride 指明一条记录的长度。偏移与跨度对不上,
画面会整体错位而不报错。
/* 每条记录 32 字节:位置 12 + 法线 12 + 颜色 8 */
const bufferLayout = [
{
name: 'vertexData',
stepMode: 'vertex',
byteStride: 32,
attributes: [
{ attribute: 'positions', format: 'float32x3', byteOffset: 0 },
{ attribute: 'normals', format: 'float32x3', byteOffset: 12 },
{ attribute: 'colors', format: 'float32x2', byteOffset: 24 }
]
}
];
实例属性
stepMode 设成 instance,每个实例读一条记录,
绘制调用仍然只有一次。省略 stepMode 时 WebGL 后端会按属性名里是否含
instance 推断,显式写出来更稳。
const bufferLayout = [
{ name: 'positions', stepMode: 'vertex', format: 'float32x3' },
{
name: 'instanceData',
stepMode: 'instance',
byteStride: 16,
attributes: [
{ attribute: 'instanceOffsets', format: 'float32x3', byteOffset: 0 },
{ attribute: 'instanceOpacity', format: 'float32', byteOffset: 12 }
]
}
];
与 shaderLayout 的分工
| 回答的问题 | 来源 | |
|---|---|---|
shaderLayout | 着色器暴露了哪些属性、位置在哪、类型是什么 | 由着色器源码解析得到 |
bufferLayout | 内存里这些属性怎么排布、从哪个缓冲读 | 由应用声明 |
两者在创建管线与顶点数组时合并使用:管线用它们编译固定状态,
device.createVertexArray({ shaderLayout, bufferLayout }) 用它们建立属性绑定。
相关辅助函数
| 函数 | 作用 |
|---|---|
getBufferLayoutAttributeNames(bufferLayout) | 列出布局里声明的全部属性名 |
getBufferLayoutMinAttributeLocation(bufferLayout) | 取属性占用的最小位置编号 |
getLogicalBufferSlots(bufferLayout) | 取逻辑缓冲区槽位 |
getShaderAttributeLocationMap(shaderLayout) | 取属性名到位置编号的映射 |
getAttributeInfosFromLayouts(shaderLayout, bufferLayout) | 合并两边的声明,得到每个属性的完整信息 |
格式字符串必须与着色器类型逐字对应。
float32x2 对 vec2,float32x3 对 vec3,
uint8x4 只能对 uvec4 或按归一化声明的输入。
分量数写错时模型不会报错,属性读到的是一片零。
经纬志(2026)。《BufferLayout》。https://www.jingweizhi.com/lumagl/api/buffer-layout.html(访问日期 2026-11-03)。