C语言OpenGL 2D批处理中4x4 MVP矩阵作为顶点layout的正确存储顺序
问题原因与修复方案
1. 顶点属性配置错误
你当前glVertexAttribPointer直接配置16个分量的写法不符合OpenGL规范:OpenGL单个顶点属性最多仅支持4个分量(对应vec4的大小),mat4类型的顶点属性需要拆分为4个连续的vec4属性分别配置,每个vec4对应矩阵的一列。
2. 矩阵存储顺序要求
GLSL中矩阵默认是列主序存储,你需要按「先列后行」的顺序把矩阵数据填入顶点数组:先放第0列的4个元素bar[0][0], bar[0][1], bar[0][2], bar[0][3],再放第1列的4个元素bar[1][0], bar[1][1], bar[1][2], bar[1][3],之后依次放第2列、第3列的4个元素,16个元素完整排列即可。
修复后的代码示例
顶点属性配置部分
/* 自定义属性,偏移量0 */ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 19 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); /* mat4拆为4个连续的vec4属性,对应location 1/2/3/4,偏移依次增加4*sizeof(float) */ glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 19 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1); glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 19 * sizeof(float), (void*)(7 * sizeof(float))); glEnableVertexAttribArray(2); glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, 19 * sizeof(float), (void*)(11 * sizeof(float))); glEnableVertexAttribArray(3); glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, 19 * sizeof(float), (void*)(15 * sizeof(float))); glEnableVertexAttribArray(4);
顶点数组填充部分
GLfloat vertices[] = { foo, foo1, foo2, // 按列完整存储mat4的16个元素,不要缺项 bar[0][0], bar[0][1], bar[0][2], bar[0][3], // 第0列 bar[1][0], bar[1][1], bar[1][2], bar[1][3], // 第1列 bar[2][0], bar[2][1], bar[2][2], bar[2][3], // 第2列 bar[3][0], bar[3][1], bar[3][2], bar[3][3], // 第3列 // 后续其他顶点数据 };
顶点着色器对应声明
layout(location = 0) in vec3 aCustomAttr; layout(location = 1) in vec4 aMVPCol0; layout(location = 2) in vec4 aMVPCol1; layout(location = 3) in vec4 aMVPCol2; layout(location = 4) in vec4 aMVPCol3; void main() { mat4 mvp = mat4(aMVPCol0, aMVPCol1, aMVPCol2, aMVPCol3); // 后续坐标计算逻辑 gl_Position = mvp * vec4(aPos, 1.0); }
提示:如果你使用的数学库默认生成行主序矩阵,不需要修改填充逻辑,只要在着色器中把矩阵组装代码改为
transpose(mat4(aMVPCol0, aMVPCol1, aMVPCol2, aMVPCol3))即可。
内容的提问来源于stack exchange,提问作者Shadoww
相关产品推荐
相关产品推荐

