Matrices (DirectX and OpenGL)

Started by
5 comments, last by skytiger 13 years, 5 months ago
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
Advertisement
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.
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.
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.

Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, theHunter, theHunter: Primal, Mad Max, Watch Dogs: Legion

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?
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).
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 MAJOR11  12  13  14      11  12  13  14  21  22  23  24  31  32  33  34  41  42  43  4421  22  23  2431  32  33  34      PHYSICAL COLUMN MAJOR41  42  43  44                    11  21  31  41  12  22  32  42  13  23  33  43  14  24  34  44MATRIX CONVENTIONROW * MATRIX (DIRECTX)X   Y   Z   0       TRANSLATION IS STORED IN LOGICAL 41 42 43X   Y   Z   0X   Y   Z   0TX  TY  TZ  1MATRIX * COL (OPENGL)X   X   X   TX      TRANSLATION IS STORED IN LOGICAL 14 24 34Y   Y   Y   TYZ   Z   Z   TZ0   0   0   1DIRECTX (ROW * MATRIX) PHYSICAL ROW_MAJOR11  12  13  14  21  22  23  24  31  32  33  34  41  42  43  44                                                TX  TY  TZOPENGL (MATRIX * COL) PHYSICAL COLUMN_MAJOR11  21  31  41  12  22  32  42  13  23  33  43  14  24  34  44                                                TX  TY  TZHLSL FLOAT4X4 IS STORED IN COLUMN_MAJORTHIS MEANS THAT MUL(ROW, MATRIX) CAN BE COMPILED AS 4 DOT PRODUCTS


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

This topic is closed to new replies.

Advertisement