Sign in to follow this  

HLSL mul() and row/column major matricies in directx

This topic is 1123 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

I have my WVP matrix = World * View * Projection in direct3D. If directx stores its matrices in row major style, and the hlsl mul() function can have mul(vertex, matrix) as row major style multiplication, then why must I tranpose the directx matrix before sending to the hlsl vertex shader file? also, how can I have directx send in column major matrices and have those properly multiply out? I've tried WVP matrix = Projection * view * world and then sent that into the vertex shader which uses mul(wvp, vertex) which should be column major and it doesn't work! 

Share this post


Link to post
Share on other sites

Matrix row/column major property doesn't imply specific storage layout. Well, when speaking about math, and not about computer language.

Perhaps you're using some math lib that stores matrices by columns, or maybe you've generated matrices initially transposed.

Edited by vstrakh

Share this post


Link to post
Share on other sites

If I understand your description, you're assuming that you can generate the transpose of a matrix product only by reversing the order of multiplication. However,

 

N.B.: Projection*View*World is NOT equivalent to (World*View*Projection)T

 

(World * View * Projection)T = ProjectionT * ViewT * WorldT, that's the product of the transposes in reverse order (EDIT: not the transpose of the product), and is not equivalent to Proj * View * World.

 

I.e., PT * VT * WT is what you want to use in the shader, but, even using the transpose of Proj * View * World results in WT * VT *PT - not the same.

Edited by Buckeye

Share this post


Link to post
Share on other sites

I am using xnamath, and I think this stores its matrices in row-major order. my view of w*v*p = (w*v*p)T is wrong when wondering if you could multiply pvw * vertex using column major. I am wondering now, why do I have to transpose the wvp matrix before sending to hlsl vertex shader? how does hlsl mul() function work, that is, how is mul(vertex, wvp) different from mul(wvp, vertex)? thanks

Share this post


Link to post
Share on other sites


why do I have to transpose the wvp matrix before sending to hlsl vertex shader?

Because hlsl by default expects column-major packed matrix, and not row-major.

Having single column in one constant register allows to quickly calc resulting vector component with one dot instruction.

Single mul(row-vector, column-major-matrix) will be calculated as:

    dp4 oPos.x, v0, c0
    dp4 oPos.y, v0, c1
    dp4 oPos.z, v0, c2
    dp4 oPos.w, v0, c3

while doing mul(column-major-matrix, row-vector) will be calculated as:

    mul r0, v0.y, c1
    mad r0, c0, v0.x, r0
    mad r0, c2, v0.z, r0
    mad oPos, c3, v0.w, r0

You can change default behavior with fxc options /Zpr, /Zpc.

/Zpr will inform hlsl compiler that matrices will be packed in row-major order, and you will have to to mul(row-major-matrix, column-vector)

Share this post


Link to post
Share on other sites

Btw, see this: http://msdn.microsoft.com/en-us/library/windows/desktop/bb509634%28v=vs.85%29.aspx

HLSL uses row-vector column-major math by default. I.e. it expects matrix to be column-major packed in order to do transform in most efficient way, with dot instructions.

How can I send in the WVP matrix, not having to transpose it? 

Share this post


Link to post
Share on other sites

How can I send in the WVP matrix, not having to transpose it?

 
You can either specify /Zpr when compiling shader, or add "row_major" type modifier to wvp variable.
In both cases you will have to rewrite shader to multiply matrix by vector, and not vector by matrix.

Share this post


Link to post
Share on other sites

On the C++ side, the maths library that you're using will determine both the array storage convention and the mathematical convention.
What math library are you using?

 

I am using xnamath and it's matrices. I believe they are stored row-major because I must transpose them before sending them to the vertex shader. Now, in my vertex shader I have to use mul(vertex, matrix) because with mathematical "row-major" you go from left to right that is, vertex * world * view * projection. I know I must transpose the wvp because hlsl accepts matrices in its column-major storage. 

Edited by blowfish4

Share this post


Link to post
Share on other sites

hodgeman, buckeye, vstrahk, thnks for your help. I'm pretty sure I get it now. i used row_major in front of my float4x4 WVP matrix. i was able to send in my WVP matrix and have the mul(vertex, WVP) work just fine. I was also able to do mul(PtVtWt, vertex) and that worked just fine. PtVtWt being the reversed order matrix if you multiply with a column vector which mul(matrix, vector) does. 

Share this post


Link to post
Share on other sites

This topic is 1123 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this