WebGL矩阵(mat4)符号是否对应于数学矩阵符号
Does WebGL matrix (mat4) notation corresponds to mathematical matrix notation
The OpenGL ES Shading Language 的文档(第 5.11 节)指出向量和矩阵乘法运算以正确的线性代数方式执行。
线性代数告诉我们,如果我们将矩阵乘以向量,我们会得到这样的结果:
1.0 1.0 0.0 -1.0 (1.0*-1.0)+(1.0*0.0)+(0.0*0.0)=-1.0
0.5 0.0 0.0 * 0.0 = (0.5*-1.0)+(0.0*0.0)+(0.0*0.0)=-0.5
0.0 0.0 0.0 0.0 (0.0*-1.0)+(0.0*0.0)+(0.0*0.0)= 0.0
1.0 1.0 0.0 0.0 1.0
0.5 0.0 0.0 * 1.0 = 0.0
0.0 0.0 0.0 0.0 0.0
1.0 1.0 0.0 1.0 1.0
0.5 0.0 0.0 * 0.0 = 0.5
0.0 0.0 0.0 0.0 0.0
但是,当我在 WebGL 顶点着色器中使用这些数学知识将矩阵乘以向量时,我遇到了问题。
当我尝试乘以上述矩阵的模拟时:
mat4 matrix=mat4(
1.0, 1.0, 0.0, 0.0,
0.5, 0.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
三个顶点:红色(x=-1,y=0,z=0,w=1),绿色(x=0,y=1,z=0,w=1),蓝色( x=1,y=0,z=0,w=1) 最简单的等腰三角形我得到奇怪的实用坐标:红色(-1,-1,0,1),绿色(0.5,0,0,1), blue(1,1,0,1),而不是上面理论计算的预期:red(-1,-0.5,0,1), green(1,0,0,1), blue(1,0.5, 0,1).演示问题的源代码是 avaliable here.
只有假设 mat4 矩阵在乘法之前自动转置,这些奇怪的坐标才会在数学上是正确的(OpenGL ES 着色语言的文档指出 OpenGL 按列主要顺序存储矩阵数据:这可能是原因吗? ).
所以,问题是 WebGL 表示法
mat4 matrix=mat4(
1.0, 1.0, 0.0, 0.0,
0.5, 0.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
在数学意义上表示这样的矩阵:
1.0 0.5 0.0 0.0
1.0 0.0 0.0 0.0
0.0 0.0 1.0 0.0
0.0 0.0 0.0 1.0
有没有?我应该相信自己的眼睛还是文档?
So, the question, does WebGL notation .... mean in mathematical sense such matrix as .... or not?
是的,就是这个意思。
与您预期的相比,您实际初始化的是一个转置矩阵。要么必须更改矩阵初始化,要么必须将向量与左侧的矩阵相乘。
说明
见The OpenGL ES Shading Language, 5.4.2 Vector and Matrix Constructors, page 43:
To initialize a matrix by specifying vectors, or by all 4, 9, or 16 floats for mat2
, mat3
and mat4
respectively. The floats are assigned to elements in column major order.
mat2(vec2, vec2);
mat3(vec3, vec3, vec3);
mat4(vec4, vec4, vec4, vec4);
mat2(float, float,
float, float);
mat3(float, float, float,
float, float, float,
float, float, float);
mat4(float, float, float, float,
float, float, float, float,
float, float, float, float,
float, float, float, float);
这意味着,下面初始化一个mat4
mat4 matrix=mat4(
1.0, 1.0, 0.0, 0.0,
0.5, 0.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
对应如下数学矩阵:
c0 c1 c2 c3 c0 c1 c2 c3
[ Xx Yx Zx Tx ] [ 1.0 0.5 0.0 0.0 ]
[ Xy Yy Zy Ty ] [ 1.0 0.0 0.0 0.0 ]
[ Xz Yz Zz Tz ] [ 0.0 0.0 1.0 0.0 ]
[ 0 0 0 1 ] [ 0.0 0.0 0.0 1.0 ]
但是矩阵的内存映像是:
Xx, Xy, Xz, 0, Yx, Yy, Yz, 0, Zx, Zy, Zz, 0, Tx, Ty, Tz, 1
[ 1.0, 1.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ]
另见 Data Type (GLSL) - Matrix constructors
For matrices, construction is rather more complicated.
If a matrix is constructed with a single scalar value, then that value is used to initialize all the values along the diagonal of the matrix; the rest are given zeros. Therefore, mat4(1.0) is a 4x4 identity matrix.
For multiple values, matrices are filled in in column-major order. That is, the first X values are the first column, the second X values are the next column, and so forth. Examples:
mat2(
float, float, // first column
float, float); // second column
访问矩阵的字段时也是如此:
见The OpenGL ES Shading Language, 5.6 Matrix Components, page 45:
The components of a matrix can be accessed using array subscripting syntax. Applying a single subscript to a matrix treats the matrix as an array of column vectors, and selects a single column, whose type is a vector of the same size as the matrix. The leftmost column is column 0. A second subscript would then operate on the column vector, as defined earlier for vectors. Hence, two subscripts select a column and then a row.
mat4 m;
m[1] = vec4(2.0); // sets the second column to all 2.0
m[0][0] = 1.0; // sets the upper left element to 1.0
m[2][3] = 2.0; // sets the 4th element of the third column to 2.0
注意,向量与矩阵的乘法定义如下:
参见The OpenGL ES Shading Language, 5.11 Vector and Matrix Operations, page 50:
.... The exceptions are matrix multiplied by vector, vector multiplied by matrix, and matrix multiplied by matrix. These do not operate component-wise, but rather perform the correct linear algebraic multiply. They require the size of the operands match.
vec3 v, u;
mat3 m;
u = v * m;
is equivalent to
u.x = dot(v, m[0]); // m[0] is the left column of m
u.y = dot(v, m[1]); // dot(a,b) is the inner (dot) product of a and b
u.z = dot(v, m[2]);
And u = m * v;
is equivalent to
u.x = m[0].x * v.x + m[1].x * v.y + m[2].x * v.z;
u.y = m[0].y * v.x + m[1].y * v.y + m[2].y * v.z;
u.z = m[0].z * v.x + m[1].z * v.y + m[2].z * v.z;
参考问题中的第一个示例,这意味着
的结果
mat4 m = mat4(
1.0, 1.0, 0.0, 0.0,
0.5, 0.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
vec4 v = vec4( -1.0, 0.0, 0.0, 1.0 );
u = m * v
是:
u.x = m[0].x * v.x + m[1].x * v.y + m[2].x * v.z + m[3].x * v.w;
u.y = m[0].y * v.x + m[1].y * v.y + m[2].y * v.z + m[3].y * v.w;
u.z = m[0].z * v.x + m[1].z * v.y + m[2].z * v.z + m[3].z * v.w;
u.w = m[0].w * v.x + m[1].w * v.y + m[2].w * v.z + m[3].w * v.w;
u.x = 1.0 * -1.0 + 0.5 * 0.0 + 0.0 * 0.0 + 0.0 * 1.0 = -1.0
u.y = 1.0 * -1.0 + 0.0 * 0.0 + 0.0 * 0.0 + 0.0 * 1.0 = -1.0
u.z = 0.0 * -1.0 + 0.0 * 0.0 + 1.0 * 0.0 + 0.0 * 1.0 = 0.0
u.w = 0.0 * -1.0 + 0.0 * 0.0 + 0.0 * 0.0 + 1.0 * 1.0 = 1.0
但是 u_ = v * m
的结果是:
u_.x = dot(v, m[0]);
u_.y = dot(v, m[1]);
u_.z = dot(v, m[2]);
u_.w = dot(v, m[3]);
u_.x = dot( vec4( -1.0, 0.0, 0.0, 1.0 ), vec4( 1.0, 1.0, 0.0, 0.0 ) ) = -1.0
u_.y = dot( vec4( -1.0, 0.0, 0.0, 1.0 ), vec4( 0.5, 0.0, 0.0, 0.0 ) ) = -0.5
u_.z = dot( vec4( -1.0, 0.0, 0.0, 1.0 ), vec4( 0.0, 0.0, 1.0, 0.0 ) ) = 0.0
u_.w = dot( vec4( -1.0, 0.0, 0.0, 1.0 ), vec4( 0.0, 0.0, 0.0, 1.0 ) ) = 1.0
The OpenGL ES Shading Language 的文档(第 5.11 节)指出向量和矩阵乘法运算以正确的线性代数方式执行。 线性代数告诉我们,如果我们将矩阵乘以向量,我们会得到这样的结果:
1.0 1.0 0.0 -1.0 (1.0*-1.0)+(1.0*0.0)+(0.0*0.0)=-1.0
0.5 0.0 0.0 * 0.0 = (0.5*-1.0)+(0.0*0.0)+(0.0*0.0)=-0.5
0.0 0.0 0.0 0.0 (0.0*-1.0)+(0.0*0.0)+(0.0*0.0)= 0.0
1.0 1.0 0.0 0.0 1.0
0.5 0.0 0.0 * 1.0 = 0.0
0.0 0.0 0.0 0.0 0.0
1.0 1.0 0.0 1.0 1.0
0.5 0.0 0.0 * 0.0 = 0.5
0.0 0.0 0.0 0.0 0.0
但是,当我在 WebGL 顶点着色器中使用这些数学知识将矩阵乘以向量时,我遇到了问题。 当我尝试乘以上述矩阵的模拟时:
mat4 matrix=mat4(
1.0, 1.0, 0.0, 0.0,
0.5, 0.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
三个顶点:红色(x=-1,y=0,z=0,w=1),绿色(x=0,y=1,z=0,w=1),蓝色( x=1,y=0,z=0,w=1) 最简单的等腰三角形我得到奇怪的实用坐标:红色(-1,-1,0,1),绿色(0.5,0,0,1), blue(1,1,0,1),而不是上面理论计算的预期:red(-1,-0.5,0,1), green(1,0,0,1), blue(1,0.5, 0,1).演示问题的源代码是 avaliable here.
只有假设 mat4 矩阵在乘法之前自动转置,这些奇怪的坐标才会在数学上是正确的(OpenGL ES 着色语言的文档指出 OpenGL 按列主要顺序存储矩阵数据:这可能是原因吗? ).
所以,问题是 WebGL 表示法
mat4 matrix=mat4(
1.0, 1.0, 0.0, 0.0,
0.5, 0.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
在数学意义上表示这样的矩阵:
1.0 0.5 0.0 0.0
1.0 0.0 0.0 0.0
0.0 0.0 1.0 0.0
0.0 0.0 0.0 1.0
有没有?我应该相信自己的眼睛还是文档?
So, the question, does WebGL notation .... mean in mathematical sense such matrix as .... or not?
是的,就是这个意思。
与您预期的相比,您实际初始化的是一个转置矩阵。要么必须更改矩阵初始化,要么必须将向量与左侧的矩阵相乘。
说明
见The OpenGL ES Shading Language, 5.4.2 Vector and Matrix Constructors, page 43:
To initialize a matrix by specifying vectors, or by all 4, 9, or 16 floats for
mat2
,mat3
andmat4
respectively. The floats are assigned to elements in column major order.mat2(vec2, vec2); mat3(vec3, vec3, vec3); mat4(vec4, vec4, vec4, vec4); mat2(float, float, float, float); mat3(float, float, float, float, float, float, float, float, float); mat4(float, float, float, float, float, float, float, float, float, float, float, float, float, float, float, float);
这意味着,下面初始化一个mat4
mat4 matrix=mat4(
1.0, 1.0, 0.0, 0.0,
0.5, 0.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
对应如下数学矩阵:
c0 c1 c2 c3 c0 c1 c2 c3
[ Xx Yx Zx Tx ] [ 1.0 0.5 0.0 0.0 ]
[ Xy Yy Zy Ty ] [ 1.0 0.0 0.0 0.0 ]
[ Xz Yz Zz Tz ] [ 0.0 0.0 1.0 0.0 ]
[ 0 0 0 1 ] [ 0.0 0.0 0.0 1.0 ]
但是矩阵的内存映像是:
Xx, Xy, Xz, 0, Yx, Yy, Yz, 0, Zx, Zy, Zz, 0, Tx, Ty, Tz, 1
[ 1.0, 1.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ]
另见 Data Type (GLSL) - Matrix constructors
For matrices, construction is rather more complicated.
If a matrix is constructed with a single scalar value, then that value is used to initialize all the values along the diagonal of the matrix; the rest are given zeros. Therefore, mat4(1.0) is a 4x4 identity matrix.
For multiple values, matrices are filled in in column-major order. That is, the first X values are the first column, the second X values are the next column, and so forth. Examples:
mat2( float, float, // first column float, float); // second column
访问矩阵的字段时也是如此:
见The OpenGL ES Shading Language, 5.6 Matrix Components, page 45:
The components of a matrix can be accessed using array subscripting syntax. Applying a single subscript to a matrix treats the matrix as an array of column vectors, and selects a single column, whose type is a vector of the same size as the matrix. The leftmost column is column 0. A second subscript would then operate on the column vector, as defined earlier for vectors. Hence, two subscripts select a column and then a row.
mat4 m; m[1] = vec4(2.0); // sets the second column to all 2.0 m[0][0] = 1.0; // sets the upper left element to 1.0 m[2][3] = 2.0; // sets the 4th element of the third column to 2.0
注意,向量与矩阵的乘法定义如下:
参见The OpenGL ES Shading Language, 5.11 Vector and Matrix Operations, page 50:
.... The exceptions are matrix multiplied by vector, vector multiplied by matrix, and matrix multiplied by matrix. These do not operate component-wise, but rather perform the correct linear algebraic multiply. They require the size of the operands match.
vec3 v, u; mat3 m;
u = v * m;
is equivalent tou.x = dot(v, m[0]); // m[0] is the left column of m u.y = dot(v, m[1]); // dot(a,b) is the inner (dot) product of a and b u.z = dot(v, m[2]);
And
u = m * v;
is equivalent tou.x = m[0].x * v.x + m[1].x * v.y + m[2].x * v.z; u.y = m[0].y * v.x + m[1].y * v.y + m[2].y * v.z; u.z = m[0].z * v.x + m[1].z * v.y + m[2].z * v.z;
参考问题中的第一个示例,这意味着
mat4 m = mat4(
1.0, 1.0, 0.0, 0.0,
0.5, 0.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
vec4 v = vec4( -1.0, 0.0, 0.0, 1.0 );
u = m * v
是:
u.x = m[0].x * v.x + m[1].x * v.y + m[2].x * v.z + m[3].x * v.w;
u.y = m[0].y * v.x + m[1].y * v.y + m[2].y * v.z + m[3].y * v.w;
u.z = m[0].z * v.x + m[1].z * v.y + m[2].z * v.z + m[3].z * v.w;
u.w = m[0].w * v.x + m[1].w * v.y + m[2].w * v.z + m[3].w * v.w;
u.x = 1.0 * -1.0 + 0.5 * 0.0 + 0.0 * 0.0 + 0.0 * 1.0 = -1.0
u.y = 1.0 * -1.0 + 0.0 * 0.0 + 0.0 * 0.0 + 0.0 * 1.0 = -1.0
u.z = 0.0 * -1.0 + 0.0 * 0.0 + 1.0 * 0.0 + 0.0 * 1.0 = 0.0
u.w = 0.0 * -1.0 + 0.0 * 0.0 + 0.0 * 0.0 + 1.0 * 1.0 = 1.0
但是 u_ = v * m
的结果是:
u_.x = dot(v, m[0]);
u_.y = dot(v, m[1]);
u_.z = dot(v, m[2]);
u_.w = dot(v, m[3]);
u_.x = dot( vec4( -1.0, 0.0, 0.0, 1.0 ), vec4( 1.0, 1.0, 0.0, 0.0 ) ) = -1.0
u_.y = dot( vec4( -1.0, 0.0, 0.0, 1.0 ), vec4( 0.5, 0.0, 0.0, 0.0 ) ) = -0.5
u_.z = dot( vec4( -1.0, 0.0, 0.0, 1.0 ), vec4( 0.0, 0.0, 1.0, 0.0 ) ) = 0.0
u_.w = dot( vec4( -1.0, 0.0, 0.0, 1.0 ), vec4( 0.0, 0.0, 0.0, 1.0 ) ) = 1.0