理解顶点缓冲区交错属性的stride与offset:新增弹跳次数属性对齐问题
问题根源
GLSL std430 内存布局要求结构体的总大小必须对齐到其内部最大成员的基础对齐倍数:
- 你定义的
Particle结构体中最大成员是vec2类型,基础对齐要求为8字节 - CPU侧计算的单粒子大小为
2*4 + 2*4 + 1*4 = 20字节,20不是8的整数倍 - 因此GLSL编译器会自动在每个
Particle结构体末尾补充4字节的填充位,单粒子实际占用大小为24字节,和CPU侧的20字节步长不匹配,导致数据错位。
修复方案
选择以下任意一种方案即可,推荐第一种兼容性最好:
方案1:CPU侧主动补充填充位对齐
- 在构造交错属性列表时,每个粒子追加1个无用的float作为填充,保证单粒子大小为24字节:
// 原属性追加逻辑 particleAttribList.append(p.pos.x); particleAttribList.append(p.pos.y); particleAttribList.append(p.vel.x); particleAttribList.append(p.vel.y); particleAttribList.append(p.nbr_bounces); // 新增填充位 particleAttribList.append(0.0f);
- 修改顶点属性配置的步长参数为24:
// 位置属性 gl.glVertexAttribPointer(0, 2, GL4.GL_FLOAT, false, 24, 0); // 速度属性 gl.glVertexAttribPointer(1, 2, GL4.GL_FLOAT, false, 24, 8); // 弹跳次数属性 gl.glVertexAttribPointer(2, 1, GL4.GL_FLOAT, false, 24, 16);
方案2:修改SSBO布局为packed(不推荐)
将SSBO的布局声明改为layout(packed, binding = 0) buffer particlesBuffer,强制编译器关闭自动填充。但该布局的内存排布依赖编译器实现,跨平台兼容性差,不建议生产环境使用。
额外说明
代码注释中写的「2 vec2变量 + 1 int」属于笔误,实际nbr_bounces在CPU和GLSL侧均为float类型,不影响运行但建议修正。
内容的提问来源于stack exchange,提问作者Frank Weslien
相关产品推荐
相关产品推荐

