Cornstalks 7030 Report post Posted May 2, 2013 I'm working on a C++11-based math library (for fun) and am thinking about matrices lately. First, I know the difference between row and column major. That's not my question. My questions are: How often do you program in a row/column major dependent way vs how often do you program in a row/column major agnostic way? (for me, I've only found row/column majorness to only matter when passing matrices to my shaders... how often does the importance of row/column majorness pop up for you?) What majorness do you most often use? Have you ever needed to support both row and column major matrices (in the same program)? If you have supported both row and column major matrices, what's your preferred way of distinguishing between the two? Postfixing a "_r" or "_c" on the end of the type name? Adding a template parameter? I'm just trying to think of "the real world" when making this... 1 Share this post Link to post Share on other sites
Hodgman 51223 Report post Posted May 2, 2013 (edited) Ignoring row-major storage vs column-major storage for a moment, there's matrices that have been constructed to transform mathematical row-vectors and matrices that have been constructed to transform mathematical column-vectors. Whether you're using row-vectors or column-vectors simply depends on whether you write vec * mat (mat1x4 * mat4x4), or mat * vec (mat4x4 * mat4x1). With the former type of mathematics, the forward/right/up axes will be in the first 3 rows, whereas with the latter, these axes will be in the first 3 columns (they're the mathematical transpose of each other). Therefore, if you work with row-vectors, I'd prefer to store my matrices in row-major order, so that it's easy to extract the basis vectors (this also makes the matrix multiplication code simpler on a lot of hardware). Likewise if you work with column-vectors, I'd use column-major storage order, for the same reason. Personally, I work with column-vectors (and matrices designed to transform column-vectors), because that's the way that most maths material I've used teaches it -- it seems the be the prevalent convention. Therefore, I prefer column-major storage. One place where I have to mix storage conventions is when saving space. Sometimes you want to pass matrices around as 3rows x 4columns, with a hard-coded/assumed 4th row of [0,0,0,1]. Often your registers (shader uniforms or CPU SIMD) are 4-wide, so this storage format isn't possible with column-major storage (or, it takes the same amount of space: 4 registers). So when storing a 3x4 matrix, I'd use row-major storage (which only uses 3 registers). This same problem presents itself with the opposite convention: with row-vectors + row-major storage, you'd want to use a 4x3 matrix with an assumed 4th column of [0,0,0,1], forcing you to use column-major storage for space efficiency. Edited May 2, 2013 by Hodgman 7 Share this post Link to post Share on other sites
tivolo 1367 Report post Posted May 2, 2013 Ignoring row-major storage vs column-major storage for a moment, there's matrices that have been constructed to transform mathematical row-vectors and matrices that have been constructed to transform mathematical column-vectors. Whether you're using row-vectors or column-vectors simply depends on whether you write vec * mat (mat1x4 * mat4x4), or mat * vec (mat4x4 * mat4x1). With the former type of mathematics, the forward/right/up axes will be in the first 3 rows, whereas with the latter, these axes will be in the first 3 columns (they're the mathematical transpose of each other). Therefore, if you work with row-vectors, I'd prefer to store my matrices in row-major order, so that it's easy to extract the basis vectors (this also makes the matrix multiplication code simpler on a lot of hardware). Likewise if you work with column-vectors, I'd use column-major storage order, for the same reason. Personally, I work with column-vectors (and matrices designed to transform column-vectors), because that's the way that most maths material I've used teaches it -- it seems the be the prevalent convention. Therefore, I prefer column-major storage. One place where I have to mix storage conventions is when saving space. Sometimes you want to pass matrices around as 3rows x 4columns, with a hard-coded/assumed 4th row of [0,0,0,1]. Often your registers (shader uniforms or CPU SIMD) are 4-wide, so this storage format isn't possible with column-major storage (or, it takes the same amount of space: 4 registers). So when storing a 3x4 matrix, I'd use row-major storage (which only uses 3 registers). This same problem presents itself with the opposite convention: with row-vectors + row-major storage, you'd want to use a 4x3 matrix with an assumed 4th column of [0,0,0,1], forcing you to use column-major storage for space efficiency. Very well put. It's often overlooked to differentiate between row vs. column-major matrices regarding operations, and row vs. column-major regarding storage. Here's a bit more food for thought why one should try to go for column vectors and write multiplications like v' = M * v. 4 Share this post Link to post Share on other sites
Cornstalks 7030 Report post Posted May 2, 2013 Huh. Awesome. I had never thought of the mathematical notation. I was going to use column-major notation (u = M * v) because that's standard mathematical notation, but let the matrix be either row or column major... Well that settles it for me. Column major only for my little math library. Thanks guys! 0 Share this post Link to post Share on other sites
unbird 8335 Report post Posted May 2, 2013 (edited) Before you're dead set on using column-vectors, check what your shaders use, because, oh joy, HLSL uses row vectors and GLSL column vectors AFAIK, another major difference (pun indended). Personally I find reading the transformation sequence with row vectors easier (left to right, world, view, projection). I wonder what people with right-to-left languages (hebrew, arabic) think about that Edit: Correction, HLSL can use both, see below. Edited May 2, 2013 by unbird 0 Share this post Link to post Share on other sites
japro 887 Report post Posted May 2, 2013 You can also use column vectors in hlsl if you want to. Just setup you matrices accordingly... This is always a funny conversation since anyone from a math background will be more used to the column vector convention while occasionally non-math-programmers (a concept I never managed to understand :p) argue that "row vectors are the programmers convention" since the transforms appear in the "right order". 0 Share this post Link to post Share on other sites
Cornstalks 7030 Report post Posted May 2, 2013 Before you're dead set on using column-vectors, check what your shaders use, because, oh joy, HLSL uses row vectors and GLSL column vectors AFAIK, another major difference (pun indended). Really? So HLSL uses row vectors but (defaults to) column-major matrices? 1 Share this post Link to post Share on other sites
l0calh05t 1796 Report post Posted May 2, 2013 (edited) Before you're dead set on using column-vectors, check what your shaders use, because, oh joy, HLSL uses row vectors and GLSL column vectors AFAIK, another major difference (pun indended). Really? So HLSL uses row vectors but (defaults to) column-major matrices? HLSL defaults to column-major matrix storage.This is completely unrelated to the use of row or column vectors. IIRC HLSL supports both column- and row vectors. Fun fact: if you store a Matrix used with a column vector system in row-major order and load it in column-major order it is now an equivalent matrix for a row vector system as it was transposed ;) Edited May 2, 2013 by l0calh05t 0 Share this post Link to post Share on other sites
Cornstalks 7030 Report post Posted May 2, 2013 HLSL defaults to column-major matrix storage.This is completely unrelated to the use of row or column vectors. But it is related, at least that was the whole point behind Hodgman's and tivolo's posts, if I understood them correctly. 0 Share this post Link to post Share on other sites