javascript - Does WebGL matrix (mat4) notation corresponds to mathematical matrix notation - Stack Overflow

Documentation for The OpenGL ES Shading Language (section 5.11) states that vector and matrix multiplca

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 0
Add a ment  | 

1 Answer 1

Reset to default 10

So, 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 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);

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 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;


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条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信