Order of linear algebra in GLSL

DirectX had a funny way of dealing with this. I wonder if OGL is the same…

Are vectors in OGL and GLSL column or row vectors?

For instance, usually:

/ 1 2 0 2 \ / 1 \ / 11 + 22 + 40 + 32
| 3 0 1 3 | | 2 | = | 13 + 20 + 41 + 33 |
| 5 6 1 0 | | 4 | | 15 + 26 + 41 + 30 |
\ 1 0 0 2 / \ 3 / \ 11 + 20 + 40 + 32 /

but if GLSL is treating vectors as row vectors then most of the short cuts I’ve prepared suddenly go out the window. DX used column vectors in C++ and row vectors in shaders, so it was necessary to pass the inverse transpose model-view-projection matrix to the shader. I really hope OGL doesn’t do anything similar.

If I multiply a vector by a matrix, will GLSL treat it as the same operation as multiplying a matrix by a vector? Or does it not care about premultiplication and postmultiplication?

In GLSL you can use both:

gl_Position = gl_Vertex * gl_ModelViewProjectionMatrix;

gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

In the first example gl_Vertex is threated as a row vector. In the second example gl_Vertex is a row vector.

But because OGL uses row vectors the second example is quite faster!

You got a typo in the second sentence and the last statement is completely wrong.

matrix * vector in math terminology is multiplying row * column, means vector is a column vector as all vectors in OpenGL.
Matrices are downloaded in column-major order which makes OpenGL different from C notations.
The performance should be the same because you need four instructions for both of the above calculations.

You got a typo in the second sentence and the last statement is completely wrong.

Damn… knockmyheadonthetable
Thanks a lot for correcting me!

Thanks for clarifying. I’ve done a few expansions on paper too and it’s becoming a lot clearer now.

How much overhead is associated with switching Shaders? My skysphere renderer is using one Shader for sky, one for planets, and one for planet rings. Will switching between these (as little as possible, mind you) incur a great deal of overhead and, more importantly, do I have to set up Projection and Camera matrices again after changing Shaders?

If I multiply a vector by a matrix, will GLSL treat it as the same operation as multiplying a matrix by a vector? Or does it not care about premultiplication and postmultiplication?

Just to be clear

vector * matrix != matrix * vector

If this is the case with D3D, then it’s broken.

For transforming the vertex into clipspace, you do
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

There is some significant overhead. If you can avoid redundent switches by reordering how you render, it would be better.

Projection and Modelview (Camera?) are uniforms and they belong to the state engine.
They don’t change unless you change them.
Changing shaders or anything else doesn’t change them.

I don’t think D3D Shaders let you choose which order you multiply in anyway. I haven’t used the DirectX HLSL. DX Shader Assembly has an m4x4 instruction, which only allows you to multiply vector * matrix. And this has just answered my eternal question: why do DirectX Shaders need the Inverse Transpose Model-View-Projection matrix…

Answer: DirectX Shader handling is broken.

Originally posted by Descenterace:
…why do DirectX Shaders need the Inverse Transpose Model-View-Projection matrix…

Because tranforming normals can cause problems if you multiply a normal with the Model-View Matrix:
For example take the matrix:

(1 0 0 0)
(0 2 0 0)
(0 0 2 0)
(0 0 0 1)

if you multiply a normal with that matrix the normal isn’t correct transformed. The inverse-transpose Model-View Matrix handels that (this matrix is also call normal matrix in GLSL).

“m4x4 instruction”

They can always change the compiler so that it handles both cases. The problem is that you would need the transpose.

matrix * vector == vector * (matrix)^T

“Inverse Transpose Model-View-Projection”

This is for transforming vertices? No, they do use the mvp.

One strange thing I noticed about D3D shaders is that some people were transforming the normal with the modelview matrix and it seemed to work. I’m not sure what the explanation for that is either.

Anyway, in this forum, we pour whiskey, not orange juice.

If you want to transform your normal in GL,

//ARBvp
DP3 result.x, state.matrix.modelview.invtrans[0], normal;
DP3 result.y, state.matrix.modelview.invtrans[1], normal;
DP3 result.z, state.matrix.modelview.invtrans[2], normal;

//GLSL
result = gl_NormalMatrix * gl_Normal;

One strange thing I noticed about D3D shaders is that some people were transforming the normal with the modelview matrix and it seemed to work. I’m not sure what the explanation for that is either.

If you only use rigid body transformations (rotation and translation) than the inverse transpose model-view matrix is equal to the model view matrix:

((MV)^T)^(-1) = MV

This is only the case if you use tranformation where the elementar tranformation matrix has this property ( ((M)^T)^(-1) = M ). As said, this is true for rotation and translation matrices.

>>If you only use rigid body transformations (rotation and translation) than the inverse transpose model-view matrix is equal to the model view matrix<<

Man, do read what you are writing?

Look, the inverse of rotational matrix is equal to its transposed matrix.
The inverse of a translation is the matrix with the negative translation coefficients.
The inverse of a scale matrix is the matrix with the reciprocal scales.

To make it clearer:

Rotations (2D):
cos -sin // transposed == inverse
sin cos
// Inverse transposed == original matrix.

Translations: (1D! )
1 t transpose 1 0 and inverse 1 0
0 1 t 1 -t 1
// Inverse transposed != original matrix.

Scale: (2D)
sx 0 transpose sx 0 and inverse: 1/sx 0
0 sy 0 sy 0 1/sy
// Inverse transposed != original matrix

[This message has been edited by Relic (edited 03-17-2004).]

Man, do read what you are writing?

Look, the inverse of rotational matrix is equal to its transposed matrix.
The inverse of a translation is the matrix with the negative translation coefficients.
The inverse of a scale matrix is the matrix with the reciprocal scales.

Damnit… I should really better read before I post… :slight_smile:
Sorry, ok, but applying the inverse-transpose model-view matrix on a normal vector (nx, ny, nz, 0) has the same result as applying the model-view matrix on the normal (for rotation and translation matrices).

Oh, normals. Maybe I should read more carefully, too.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.