# Transpose World Inverse Transpose?

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

## Recommended Posts

Hi all,

Just a short question.
I'm moving away from effects11, first adding manual CBuffer managing.

I've learned that you need to transpose all matrices before you send them to the GPU.
This all works, but I'm not sure how to handle the WorldInverseTranspose.

Since it's already transposed, I could transpose it again or simply send in the WorldInverse. Would this be the way to go?

##### Share on other sites

I've learned that you need to transpose all matrices before you send them to the GPU

Actually you may not transpose them on CPU: just change multiplication order in shader code:

Something like this:

    OUT.position     = mul(IN.wvp, float4(IN.position, 1));
OUT.normalVS     = mul((float3x3)IN.wv, IN.normal);

##### Share on other sites
But would I still need the the WorldInverseTranspose then?

Not sure if I understand you correct, I believe it goes for all matrices.

##### Share on other sites
But would I still need the the WorldInverseTranspose then?

I do not do "WorldInverseTranspose" for any matrix when I place it to a buffer in my code (and Transpose also).

Transpose is often used for OpenGL matrix-vector order multiplication in hlsl code.

There 3 ways to bypass it:

1. transpose matrix on CPU

2. use different order for multiplication (Vec*Mat => Mat*Vec)

3. use row_major pragma

Edited by Serenity79

##### Share on other sites

I've learned that you need to transpose all matrices before you send them to the GPU. This all works, but I'm not sure how to handle the WorldInverseTranspose. Since it's already transposed, I could transpose it again or simply send in the WorldInverse. Would this be the way to go?

What do you mean it's already transposed?

You mean you have:

If so, then yes, you can optimize that to:

However, the only reason that you "have" to transpose matrices before you send them to the GPU is because you're using a CPU-side math library that stores the elements in row-major array order, and by default, GLSL/HLSL interpret matrices using column-major array order... but you can override that default setting and tell GL/D3D that your matrices are stored in using row-major element indices:

//HLSL
float4x4 world;//column major array element indexing
row_major float4x4 world;//row major array element indexing
//GLSL
mat4 world;//column major array element indexing
layout(row_major) mat4 world;//row major array element indexing

Honestly I have no idea why Microsoft decided to make their CPU math library use row-major indexing and their shader language use column-major indexing :(

Or an alternative fix is to use a better math library on the CPU side :lol: :wink:

Actually you may not transpose them on CPU: just change multiplication order in shader code:

IMHO using different mathematical conventions in different parts of your game leads to a lot of confusion in the long run.

This works because as above, your CPU code has been using the computer-science convention of row-major array indexing, while your GPU code is currently using the computer science convention of column-major array indexing.
This mismatch of computer science conventions coincidentally has the side-effect of causing your matrices to become mathematically transposed... which means you can "fix" it by swapping your mathematical conventions as mentioned by Serenity... but it feels much better to me to just avoid ever having a computer-science or mathematical convention mixup in the first place, and especially not flipping two different conventions to coincidentally cancel each other out.

Edited by Hodgman

##### Share on other sites
Or an alternative fix is to use a better math library on the CPU side :lol: :wink:

Hodgman, could you suggest replacement for DirectXMath?

Currently I have own small wrapper upon DirectXMath.

I am looking for:

1. At least 80% functional of DirectXMath (float2/3/4, matrix, Quaternion)

2. Support for SSE4/AVX

3. C++ - friendly.

4. <optional> Not a big, general use, just for computer graphics/physics.

Edited by Serenity79

##### Share on other sites

DXMath isn't actually that bad, I just personally don't like their conventions :lol: It has quite good SIMD code generation from what I've seen.

GLM isn't bad either: http://glm.g-truc.net/0.9.7/index.html but I think it prioritizes functionality over performance (it does have SIMD support though!). IMHO your C++ math code will be a lot prettier (more readable) in GLM than in DXM, but IIRC, it uses opposite mathematical conventions to DXM.

You could check out Sony's library: https://github.com/erwincoumans/sce_vectormath It was originally created for PS3 developers (IIRC), but has grown a lot since then. I've used this a bit in the workplace where people trusted it's SIMD abilities.

Edited by Hodgman

##### Share on other sites

Thanks guys, good discussion.

I've decided not to change orders of multiplication or add row_major in the shaders. If something might change in the future I just have to remember to send in all matrices transposed, to the shaders, as long as I use DirectXMath.

Option 1:

		XMMATRIX worldInvTranspose = CMathHelper::InverseTranspose(world);

DirectX::XMMATRIX CMathHelper::InverseTranspose(const DirectX::CXMMATRIX M)
{
DirectX::XMMATRIX A = M;
A.r[3] = DirectX::XMVectorSet(0.0f, 0.0f, 0.0f, 1.0f);

DirectX::XMVECTOR det = DirectX::XMMatrixDeterminant(A);
return DirectX::XMMatrixTranspose(XMMatrixInverse(&det, A));
}



Option 2:

	XMMATRIX worldInv = XMMatrixInverse(NULL, world);



I'm now using option 2, nice and clean.

##### Share on other sites

What was option 1 supposed to do exactly? The determinant is an output parameter so that stuff you were passing in got discarded anyway.

Edited by Mona2000

##### Share on other sites

You're absolutely right, the determinant is returned/ an output.

So basically this would do the same trick for option 1:

DirectX::XMMATRIX CMathHelper::InverseTranspose(const DirectX::CXMMATRIX M)
{
return DirectX::XMMatrixTranspose(XMMatrixInverse(NULL, M)));
}



1. 1
2. 2
Rutin
24
3. 3
4. 4
JoeJ
18
5. 5

• 14
• 17
• 11
• 11
• 9
• ### Forum Statistics

• Total Topics
631758
• Total Posts
3002155
×