Jump to content
  • Advertisement
Sign in to follow this  
rubenhak

Very weird matrix behavior in GLSL

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

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
Share on other sites
Advertisement
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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;
[edit]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 this post


Link to post
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;
[edit]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 this post


Link to post
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 this post


Link to post
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?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!