Public Group

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

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

## 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 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 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 on other sites

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.

##### 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 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



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 on other sites

how does hlsl mul() function work, that is, how is mul(vertex, wvp) different from mul(wvp, vertex)?

If you google for  "hlsl mul function," you, too, can find this link.

##### Share on other sites

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 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.

1. 1
2. 2
3. 3
Rutin
21
4. 4
5. 5
gaxio
10

• 14
• 30
• 13
• 11
• 11
• ### Forum Statistics

• Total Topics
631778
• Total Posts
3002310
×