I have a GLSL shader that works fine, until I add the following lines to it.
"vec4 coord = texture2D(Coordinates,gl_TexCoord[0].st);"
"mat4x3 theMatrix;"
"theMatrix[1][1] = 1.0;"
"vec3 CampProj = theMatrix * coord;"
when I check the error log I am told:
"ERROR: 0:2: '=' : cannot convert from '4-component vector of float' to '3-component vector of float'\n\n"
if I make CampProject a vec4 this compiles fine, but I am very confused as to how a 4 column, 3 row matrix multiplied by a 4 component vector is gonna result in a 4 component vector.
is this a bug, or is it possible that the 4x3 matrix is really just a 4x4 under the hood with a 0,0,0,1 final row? if not can someone explain to me why the compiler is insisting on returning a vec4?
I'm using C++ via VSExpress 2013, win7, Mobile Intel® 4 Series Express Chipset Family
UPDATE:
Reto's answer is what I expect to be the case. That it is a bug in the compilation. Both because that's the only thing that makes sense in a LA context and because the LA definition is what the GLSL documentation references for matrix/matrix and matrix / vec multiplication; however, even after updating my video chipset drivers the compilation is showing me the same behavior. could one other person confirm that behavior Reto describes?
@Reto if nobody has confirmed by 12-05-14 I'll accept your answer as correct as it seems the only real logical possibility.
In the GLSL 3.30 spec document, mat4x3 is described as: The operator is multiply (*), where both operands are matrices or one operand is a vector and the other a matrix. A right vector operand is treated as a column vector and a left vector operand as a row vector.
In C, an OpenGL 4×4 matrix is a 16-float array: In GLSL the same matrix is: Let’s see how to map the C matrix to the GLSL one and vice-versa. Matrices in OpenGL are column-major.
Note: This is only true for GLSL 1.30 and above; older version of GLSL did not guarantee this. Vector constructors take the number of values that they store. So a vec3 takes 3 values. However, all vectors can be constructed from a single value; this results in a vector where all of the values are the value given to the constructor. So:
In your example the HLSL matrix is a transpose of the GLSL matrix. Which means that in HLSL it would be mul (mat, vec) and equivalent in GLSL vec * mat. So even if we change nothing on the 3D framework side, flipping the mul argument should work.
This looks like a bug in your GLSL compiler. This should compile successfully:
mat4x3 mat;
vec3 res = mat * vec4(1.0);
and this should give an error:
mat4x3 mat;
vec4 res = mat * vec4(1.0);
I tested this on 3 configurations, and all of them confirmed this behavior:
This also matches my understanding of the specs. In the GLSL 3.30 spec document, mat4x3
is described as:
a floating-point matrix with 4 columns and 3 rows
and multiplication is defined by (emphasis added):
The operator is multiply (*), where both operands are matrices or one operand is a vector and the other a matrix. A right vector operand is treated as a column vector and a left vector operand as a row vector. In all these cases, it is required that the number of columns of the left operand is equal to the number of rows of the right operand. Then, the multiply (*) operation does a linear algebraic multiply, yielding an object that has the same number of rows as the left operand and the same number of columns as the right operand.
In this example, the "number of columns of the left operand" is 4, which means that the vector needs to have 4 "rows", which is a column vector with 4 elements. Then, since the left operand has 3 rows, the resulting vector has 3 "rows", which is a column vector with 3 elements.
It's also the only thing that makes sense based on standard linear algebra.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With