OpenGL顶点着色器中使用列主序矩阵乘法无法正确绘制三角形
问题分析与解决方案
核心问题:列主序平移矩阵构造错误
你定义的列主序平移矩阵结构是正确的(第四列存储Tx、Ty、Tz),但在mat4_column_translation函数中,错误地将平移分量放到了每一列的第四个元素(data[3]、data[7]、data[11]),而正确的列主序平移矩阵应该将Tx、Ty、Tz放在第四列的前三个元素,对应数组索引data[12]、data[13]、data[14]。
OpenGL的mat4默认按列主序存储,内存中矩阵的列依次排列:
- 第0列:
data[0], data[1], data[2], data[3] - 第1列:
data[4], data[5], data[6], data[7] - 第2列:
data[8], data[9], data[10], data[11] - 第3列:
data[12], data[13], data[14], data[15]
标准列主序平移矩阵的结构是:
1 0 0 Tx 0 1 0 Ty 0 0 1 Tz 0 0 0 1
对应到数组中就是修改第3列的前三个元素,而非前3列的第四个元素。
次要问题:平移函数未利用传入的矩阵参数
当前mat4_column_translation函数直接返回一个新的平移矩阵,完全忽略了传入的参数a,这意味着无法实现矩阵的组合变换(比如先旋转再平移),需要修改函数实现矩阵乘法。
修正后的代码
修正列主序平移函数(支持矩阵组合)
// Translate Mat4 using column-major order(修正版,支持矩阵组合) Mat4 mat4_column_translation(Mat4 a, float x, float y, float z) { // 创建基础平移矩阵 Mat4 translation = mat4_identity(); translation.data[12] = x; translation.data[13] = y; translation.data[14] = z; // 列主序矩阵乘法:result = a * translation(变换顺序为先平移再应用原有矩阵a) Mat4 result = {0}; for (int col = 0; col < 4; col++) { for (int row = 0; row < 4; row++) { float sum = 0.0f; for (int k = 0; k < 4; k++) { sum += a.data[k * 4 + row] * translation.data[col * 4 + k]; } result.data[col * 4 + row] = sum; } } return result; }
如果仅需生成单纯的平移矩阵(无需和传入矩阵相乘),可简化为:
// 生成单纯的列主序平移矩阵 Mat4 mat4_column_translation(float x, float y, float z) { Mat4 m = mat4_identity(); m.data[12] = x; m.data[13] = y; m.data[14] = z; return m; }
修正后的调用代码
// 生成列主序平移矩阵 Mat4 trans = mat4_column_translation(0.5f, 0.5f, 0.0f); unsigned int transformLoc = glGetUniformLocation(shader, "transform"); // GL_FALSE表示传入的是列主序矩阵,无需转置 glUniformMatrix4fv(transformLoc, 1, GL_FALSE, trans.data);
验证逻辑
修正后,列主序平移矩阵的第四列是[0.5, 0.5, 0.0, 1.0],与着色器中的transform * vec4(aPos, 1.0)乘法逻辑完全匹配,顶点会被正确平移到目标位置。
内容的提问来源于stack exchange,提问作者Leonardo Fadul
相关产品推荐
相关产品推荐

