Why does this matrix multiplication order matter?

Started by
29 comments, last by frob 9 years, 10 months ago

This is how I used to do matrix multiplication in my vertex shaders:



	gl_Position = projection * (view * (model * position));

But since I've ported to linux, in at least two of my shaders, only this works:



	gl_Position = projection * view * model * position;

Why?

Advertisement

when you set your uniform matricies in linux, the glsl perhaps assumes opposite majoring order. So in case of column you use row, or vice versa (since you just ported, thus the layout in memory is the same). If you transpose the matricies, it will work with the previous formula (I am not saying you should do that of course, a waste of instructions).

No, this works with all my other shaders.

Also, seems to be a bug:



	float minlight = shadow * diffuse;

	//outfrag = vec4(color.xyz * stexel.xyz * shadow * diffuse + vspecular, alph);	//buggy on linux for some reason
	outfrag = vec4(color.xyz * stexel.xyz * minlight + vspecular, alph);

It produces a reddish colour with blue fragments.

GL_VERSION: 3.0 Mesa 10.3.0-devel (git-96a95f4 saucy-oibaf-ppa)
Renderer1: Mesa DRI Intel(R) Ivybridge Mobile

Maybe it's because I tried to get the latest (experimental?) drivers for my integrated Intel videocard?

GLSL code is platform agnostic for the most part, them difference usually boils down to the shader compiler included with the OpenGL driver. So this may be a driver bug.

No, this works with all my other shaders.

What no? Do you mean shaders on linux that use the first formula work, and only this shader demands second formula on the linux?

Again, GLSL does not make distinction betweeen column or row vectors in its very code, but order of operations is explicit of course (order is actualy equivalent of majoring). you would better use glUniformMatrix4fv with transpose parameter specified, this will interpet matrix in GLSL code as expected, if driver is not totaly mad.

color.xyz * stexel.xyz

this is a cross product, depends on majoring as well.

I myself am not constructing matricies in GLSL code by implicit constructors, but I use explicit more atomic operations to actualy transform vectors by them, safely. (since I do not use glUniformMatrix4fv call to set matricies, but a batched vec4 array where I put everything I need for the shader in one call).

All operations that result in a vector not scalar I perform myself explicitly atomic for they are sensitive for majoring, to make myself sure.(this includes transformation of vector, multiplying matricies, crossing vectors...).

color.xyz * stexel.xyz

this is a cross product, depends on majoring as well.

No, that's a pairwise multiply, not a cross product. The cross product is done with cross() and it does not depend on the row/column majorness of matrices.

polyfrag's code doesn't have matrix memory layout problems. His problem is that associative property of matrix multiplication doesn't hold on his Linux machine. And I don't know the reason for that.

Again, GLSL does not make distinction betweeen column or row vectors in its very code, but order of operations is explicit of course (order is actualy equivalent of majoring).

The difference in the order is whether to multiply the vector first, and have all the other matrixes multiply a vector (reducing the number of operations since a vector is only 4x1), or multiply all the matrixes in order and only multiply the vector at the end.


No, that's a pairwise multiply, not a cross product. The cross product is done with cross() and it does not depend on the row/column majorness of matrices.

polyfrag's code doesn't have matrix memory layout problems. His problem is that associative property of matrix multiplication doesn't hold on his Linux machine. And I don't know the reason for that.

Ah, yes you are right,

But memory layout is not what I am apointing. Majoring of operations has nothing to do with layout in memory. To explain, if you transform a matrix and reverse the majoring (component wisdom), it is then the same matrix and the same oprations- you just have to perform reverse majoring all the time, and, if you return to preveious majoring and keep the new matrix , it is then a different (transposed matrix). Majoring is equivalent of operations comutativity with vectors and matricies.

If memory layout transposes, you simply have only two options to have the same matrix, reverse the majoring (order of not comutaive operations with vectors), or, have matrix components to not tranpose thanks to layout missinterpratation.

The difference in the order is whether to multiply the vector first, and have all the other matrixes multiply a vector (reducing the number of operations since a vector is only 4x1), or multiply all the matrixes in order and only multiply the vector at the end.

yes, first formula is more effective since you transform vector 3 times by a matrix, while second formula performs 2 matrix multiplications and than transforms a vector. I stress again that second formula performs reverse order of transformations, and it results in the same thing since matricies are (diagnosticly) transposed.

Again, GLSL does not make distinction betweeen column or row vectors in its very code, but order of operations is explicit of course (order is actualy equivalent of majoring).

The difference in the order is whether to multiply the vector first, and have all the other matrixes multiply a vector (reducing the number of operations since a vector is only 4x1), or multiply all the matrixes in order and only multiply the vector at the end.

That only saves operations if you are doing only one or two transformations. If you are processing lots of vectors, then the matrix concatenation is clearly more efficient.

Regarding your original question, are you having issues with only one or two shaders, but all of the others are working as you expected (using the same matrix multiplication order)?

This topic is closed to new replies.

Advertisement