Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GLSL compile fails on a mat4x3 vec4 multiplication

Tags:

opengl

glsl

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.

like image 380
Semicolons and Duct Tape Avatar asked Nov 26 '14 16:11

Semicolons and Duct Tape


People also ask

What is mat4x3 in GLSL?

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.

What is an OpenGL 4×4 matrix in GLSL?

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.

How many values does a GLSL vector constructor take?

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:

What is the HLSL equivalent of the GLSL matrix?

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.


1 Answers

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:

  • Windows 8.1 with Intel HD Graphics 4600.
  • Windows 8.1 with NVIDIA GeForce GT 740M.
  • Mac OS Yosemite with Intel Iris Pro.

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.

like image 53
Reto Koradi Avatar answered Sep 21 '22 15:09

Reto Koradi