Sign in to follow this  
steviedisco

Matrices (DirectX and OpenGL)

Recommended Posts

Hi,

I've had a frustrating night. I'm writing a dual-api render engine and am trying to settle on a matrix handling implementation.

What I have has started to get a bit hairy, so I've decided to down tools for the night and start afresh tomorrow with a clean slate.

Two things:

As DirectX stores matrices in row-major format and OpenGL in column-major, I can keep my intermediate storage in just one of these formats, do my operations and then transpose it at the last minute before it is applied, correct?

Second, at more importantly, when multiple matrices are stacked together, do both APIs expect the matrices to be multiplied in opposite orders to get the same end result?

Simple Example:

DirectX: World Transform x Object Rotate x Object Translate
OpenGL : ObjectTranslate x Object Rotate x World Transform

Tbh I'm having difficulty getting opengl to render at all, and am testing in wireframe mode at the moment.

Thanks

Share this post


Link to post
Share on other sites
OpenGL and Direct3D use different view volumes. (For OpenGL see the chapter "Primitive Clipping" in the specification)
In OpenGL the view volume is given by
-w <= x <= w
-w <= y <= w
-w <= z <= w
but Direct3D uses
-w < x <= w
-w < y <= w
0 < z <= w
you have to take this into account.

Share this post


Link to post
Share on other sites
Both DirectX and OpenGL have exact same memory layout for a matrix. IIRC, the difference comes in the order you preform multiplications.
In GLSL you'd end up with the equivelent of (maybe you pre-multiply some of these before sending them to the shader):
outVetex = perspective * camera * model * inVertex;

But I can't be positive about the directX side as I haven't used it.

Share this post


Link to post
Share on other sites
Quote:
Original post by KulSeran
Both DirectX and OpenGL have exact same memory layout for a matrix. IIRC, the difference comes in the order you preform multiplications.
In GLSL you'd end up with the equivelent of (maybe you pre-multiply some of these before sending them to the shader):
outVetex = perspective * camera * model * inVertex;

But I can't be positive about the directX side as I haven't used it.


HLSL doesn't care which multiplication method you use the intrinsic functions support both as long as you are consistant.
You have to pass your projection, view and world(GL combines the last two into the modelview matrix) as uniforms they are not built in like in GLSL.

As long as you do your operations before you transpose you can keep the order the same for both OGL and D3D, be carefull with any operations on transposed matrices though as it is easy to forget if they are or not.

Share this post


Link to post
Share on other sites
Quote:
Original post by steviedisco
So, if I'm using glLoadMatrix* to copy my matrix into memory, does that mean I *don't* need to transpose it before doing so?
If you're using glLoad/MultMatrix*(), then the only requirement is that data be arranged in memory as OpenGL expects it, which is as 16 consecutive floats/doubles/etc., with basis vector elements arranged contiguously in memory.

In practical terms, this means you can use row-basis matrices with row-major storage, or column-basis matrices with column-major storage (whichever you prefer).

Share this post


Link to post
Share on other sites
the other thing to consider, with dx effects
is that matrices will be passed to effects with column_major packing

because this allows the compiler to convert:

mul(row, matrix)

into 4 dot products

but the HLSL *syntax* for matrix declaration and component access is unaffected by this and will always be in row_major packing

so if you mix and match row_major and column_major packing in HLSL
there are no syntax changes required - but the asm output will be different

this lets you tweak the packing to match your syntax and find the best performance

(afaik)

this helps me understand it:

LOGICAL             PHYSICAL ROW MAJOR

11 12 13 14 11 12 13 14 21 22 23 24 31 32 33 34 41 42 43 44
21 22 23 24
31 32 33 34 PHYSICAL COLUMN MAJOR
41 42 43 44
11 21 31 41 12 22 32 42 13 23 33 43 14 24 34 44

MATRIX CONVENTION

ROW * MATRIX (DIRECTX)

X Y Z 0 TRANSLATION IS STORED IN LOGICAL 41 42 43
X Y Z 0
X Y Z 0
TX TY TZ 1

MATRIX * COL (OPENGL)

X X X TX TRANSLATION IS STORED IN LOGICAL 14 24 34
Y Y Y TY
Z Z Z TZ
0 0 0 1

DIRECTX (ROW * MATRIX) PHYSICAL ROW_MAJOR

11 12 13 14 21 22 23 24 31 32 33 34 41 42 43 44
TX TY TZ

OPENGL (MATRIX * COL) PHYSICAL COLUMN_MAJOR

11 21 31 41 12 22 32 42 13 23 33 43 14 24 34 44
TX TY TZ

HLSL FLOAT4X4 IS STORED IN COLUMN_MAJOR

THIS MEANS THAT MUL(ROW, MATRIX) CAN BE COMPILED AS 4 DOT PRODUCTS


[Edited by - skytiger on November 12, 2010 6:29:33 AM]

Share this post


Link to post
Share on other sites

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