# Very weird matrix behavior in GLSL

This topic is 2590 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi Everbody,

Just came across a very weird behavior with matrix multiplication in GLSL shaders.
Trying to break this very common line of code:
 gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex; 

into
 vec4 pos = gl_ModelViewMatrix * gl_Vertex; gl_Position = gl_ProjectionMatrix * pos; 

but resulting gl_Position that gets calculated is different in these two samples.

This looks very weird, as matrix multiplication operation is associative (A * B) * C = A * (B * C).

Anybody came across this before? Why does this happen and is there a way to fix it?

Thanks,
Ruben

##### Share on other sites
I had the same issue before but couldn't tell you what I did, I think I just don't use the one that works and any other calculations I have a separate variable. So if you need "pos" variable, then use it but just make sure your gl_Position is always the one that you have that works.

##### Share on other sites
Matrices aren't communitive. You MUST multiply the first two together first, then multiply that result into gl_Vertex (which is acting as a column matrix in this operation). To see this for yourself, try multiplying them the original way, then do it the way you're trying to do it CPU-side, and print the results to the console. You'll see different results. Doing it by hand may also help realize what's going on.

##### Share on other sites

Matrices aren't communitive. You MUST multiply the first two together first, then multiply that result into gl_Vertex (which is acting as a column matrix in this operation). To see this for yourself, try multiplying them the original way, then do it the way you're trying to do it CPU-side, and print the results to the console. You'll see different results. Doing it by hand may also help realize what's going on.

I'm not saying that matrix multiplication is commutative A * B = B * A is not true for matrices. But it is supposed to be associative, which means that for every given matrices A, B, C following statement is true: (A * B) * C = A * (B * C). In my case A can be treated as gl_ProjectionMatrix, B - as gl_ModelViewMatrix, and C - as a gl_Vertex. Quote from wiki: http://en.wikipedia.org/wiki/Matrix_multiplication#Properties

I understand that there is something happening on the GPU side, but from math perspective, no matter what is the sequence of operations, result should be the same. I just did a test with Matlab with various random matrices/vectors and results were same.

##### Share on other sites
Try:

vec4 pos = gl_ModelViewMatrix * gl_Vertex;
gl_Position = gl_ProjectionMatrix * vec4(pos.xyz, 1.0);

Thats the only thing I can think of is something with the w component. Regardless if you need:

vec4 pos = gl_ModelViewMatrix * gl_Vertex;
//Do some calculations with pos variable
gl_Position = gl_ProjectionMatrix * pos;

You would have the same exact amount of lines of code by doing:

vec4 pos = gl_ModelViewMatrix * gl_Vertex;
//Do some calculations with pos variable
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

so just do that anyway.

##### Share on other sites

Try:

vec4 pos = gl_ModelViewMatrix * gl_Vertex;
gl_Position = gl_ProjectionMatrix * vec4(pos.xyz, 1.0);

Thats the only thing I can think of is something with the w component. Regardless if you need:

vec4 pos = gl_ModelViewMatrix * gl_Vertex;
//Do some calculations with pos variable
gl_Position = gl_ProjectionMatrix * pos;

You would have the same exact amount of lines of code by doing:

vec4 pos = gl_ModelViewMatrix * gl_Vertex;
//Do some calculations with pos variable
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

so just do that anyway.

Trick with setting w = 1.0 does not make any difference. I know that I can use gl_ModelViewProjectionMatrix instead, but that makes it very weird and I do not have any confidence when using matrix multiplication any more....

##### Share on other sites
Trying to break this very common line of code:
gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;into vec4 pos = gl_ModelViewMatrix * gl_Vertex; gl_Position = gl_ProjectionMatrix * pos;
Shouldn't you be concatenating the matrices, and then using the result to transform the position?vec4 modelViewProj = gl_ProjectionMatrix * gl_ModelViewMatrix; gl_Position = modelViewProj * gl_Vertex;actually, no, I don't see a problem with your method... transforming a point into view-space, and then projecting it should work too... :/

##### Share on other sites

[quote name='rubenhak' timestamp='1315637398' post='4859902']Trying to break this very common line of code:
gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;into vec4 pos = gl_ModelViewMatrix * gl_Vertex; gl_Position = gl_ProjectionMatrix * pos;
Shouldn't you be concatenating the matrices, and then using the result to transform the position?vec4 modelViewProj = gl_ProjectionMatrix * gl_ModelViewMatrix; gl_Position = modelViewProj * gl_Vertex;actually, no, I don't see a problem with your method... transforming a point into view-space, and then projecting it should work too... :/
[/quote]

That could be another way of doing, but still cannot see a reason why doing my way does not work...

##### Share on other sites
This looks very weird, as matrix multiplication operation is associative (A * B) * C = A * (B * C).

Except that they are talking about matrix multiplcation. That is, C is not a vector when they write that.

The meaning is that (A * B) * C will create the same matrix as A * (B * C).
Using (gl_ModelViewProjectionMatrix * gl_Vertex) is the same as using (gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex) because the result of (gl_ProjectionMatrix * gl_ModelViewMatrix) is a matrix equal to gl_ModelViewProjectionMatrix.

L. Spiro

##### Share on other sites

[quote name='rubenhak' timestamp='1315637398' post='4859902']This looks very weird, as matrix multiplication operation is associative (A * B) * C = A * (B * C).

Except that they are talking about matrix multiplcation. That is, C is not a vector when they write that.

The meaning is that (A * B) * C will create the same matrix as A * (B * C).
Using (gl_ModelViewProjectionMatrix * gl_Vertex) is the same as using (gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex) because the result of (gl_ProjectionMatrix * gl_ModelViewMatrix) is a matrix equal to gl_ModelViewProjectionMatrix.

L. Spiro
[/quote]

Vector is a custom case of a m-by-n matrix where m (or n) is equal to 1.

I need to calculate value of pos:
pos = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;

I just want to do it differently:
p1 = gl_ModelViewMatrix * gl_Vertex;
p2 = gl_ProjectionMatrix * p1;

resulting p2 is not equal to pos. Could you explain me why? Manually I substitute any random values into gl_ProjectionMatrix, gl_ModelViewMatrix and gl_Vertex values and calculate pos and p2 manually and get equal results. However, in GLSL getting different values. Any ideas why?

1. 1
2. 2
3. 3
Rutin
22
4. 4
5. 5

• 13
• 19
• 14
• 9
• 9
• ### Forum Statistics

• Total Topics
632935
• Total Posts
3009304
• ### Who's Online (See full list)

There are no registered users currently online

×