Documentation for The OpenGL ES Shading Language (section 5.11) states that vector and matrix multiplcation operations performs in the correct linear algebraic way. Linear algebra teaches if we multiply matrix by vector we get such result:
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
But when I use this mathematical knowledge for multiplication matrix by vector in WebGL vertex-shader I face with problem. When I try multiply analogue of above matrix:
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);
to three verticles: red(x=-1,y=0,z=0,w=1), green(x=0,y=1,z=0,w=1), blue(x=1,y=0,z=0,w=1) of simplest isosceles triangle I get strange practical coordinates: red(-1,-1,0,1), green(0.5,0,0,1), blue(1,1,0,1), instead of the expected from above theoretical calculations: red(-1,-0.5,0,1), green(1,0,0,1), blue(1,0.5,0,1). Source code that demonstrates problem is avaliable here.
These strange coordinates will be matematically correct only if assume that mat4 matrix was auto-transposed before multiplication (documentation for The OpenGL ES Shading Language states that OpenGL stores matrix data in column major order: may be this is the reason?).
So, the question, does WebGL notation
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);
mean in mathematical sense such matrix as:
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
or not? Should I believe my eyes or documentation?
Documentation for The OpenGL ES Shading Language (section 5.11) states that vector and matrix multiplcation operations performs in the correct linear algebraic way. Linear algebra teaches if we multiply matrix by vector we get such result:
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
But when I use this mathematical knowledge for multiplication matrix by vector in WebGL vertex-shader I face with problem. When I try multiply analogue of above matrix:
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);
to three verticles: red(x=-1,y=0,z=0,w=1), green(x=0,y=1,z=0,w=1), blue(x=1,y=0,z=0,w=1) of simplest isosceles triangle I get strange practical coordinates: red(-1,-1,0,1), green(0.5,0,0,1), blue(1,1,0,1), instead of the expected from above theoretical calculations: red(-1,-0.5,0,1), green(1,0,0,1), blue(1,0.5,0,1). Source code that demonstrates problem is avaliable here.
These strange coordinates will be matematically correct only if assume that mat4 matrix was auto-transposed before multiplication (documentation for The OpenGL ES Shading Language states that OpenGL stores matrix data in column major order: may be this is the reason?).
So, the question, does WebGL notation
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);
mean in mathematical sense such matrix as:
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
or not? Should I believe my eyes or documentation?
Share Improve this question edited Sep 2, 2018 at 8:40 Rabbid76 211k30 gold badges157 silver badges200 bronze badges asked Jan 21, 2018 at 14:01 Сергей ИванопулоСергей Иванопуло 1611 gold badge4 silver badges14 bronze badges 01 Answer
Reset to default 10So, the question, does WebGL notation .... mean in mathematical sense such matrix as .... or not?
Yes, it means.
What you actually initialize is a transposed matrix, pared to what you expected. Either you have to change the matrix initialization or you have to multiply the vector to the matrix from the left.
Explanation
See 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);
This means, the following initialization of a 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);
corresponds to the following mathematical matrix:
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 ]
But the memory image of the matrix is:
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 ]
See also Data Type (GLSL) - Matrix constructors
For matrices, construction is rather more plicated.
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 same is the case when accessing the fields of a matrix:
See The OpenGL ES Shading Language, 5.6 Matrix Components, page 45:
The ponents 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
Note, the multiplication of a vector and a matrix is defined as follows:
See 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 ponent-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;
Referring to the 1st example in the question, this means, the result of
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
is:
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
But the result of u_ = v * m
would be:
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
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1742379781a4432897.html
评论列表(0条)