矩阵点乘和叉乘的区别_矩阵:行主序、列主序、行向量、列向量

看龙书的时候发现一个矩阵在传入Shader之前都要转置一下,很好奇为什么要有一步这样的操作。

39fde6eecaa8d9d2e7cf114e05d38c2c.png

行主序和列主序

行主序指矩阵在内存中逐行存储,列主序指矩阵在内存中逐列存储。

行主序矩阵内存布局:

3c9d3f49ad3bc6feb1142e02e3d99aba.png

列主序矩阵内存布局:

142d7898f9ddc291c4e68b4920dfa3fd.png

行向量和列向量

行向量指的是把向量当成一个一行n列的矩阵,列向量指的是把向量当成一个n行一列的矩阵。

左乘和右乘

矩阵“左乘”:矩阵和向量相乘时放在左边。

矩阵“右乘”:矩阵和向量相乘时放在右边。

对于同一个矩阵和同一个向量,“左乘”和“右乘”的结果是不一样的,这是因为矩阵不满足交换律。

总结

HLSL中默认是使用列主序存储矩阵的,也就是矩阵的每一列存储在一个常量寄存器中,此时使用矩阵“右乘”效率更高,因为一个float4和一个4x4的矩阵相乘只需要四个点乘就能计算出结果:

5569972d849be4c96fa6fa2b310e4ac9.png

如果使用“左乘”,结果就是:

ff5b51278fb60e81abdd7727a59d8f86.png

HLSL中可以通过 #pragmapack_matrix指令或者row_majorcolumn_major keyword来修改矩阵的存储方式。在Shader执行之前会加载矩阵的数据,行主序还是列主序的设置只会影响Shader读取输入的矩阵数据矩阵读取到Shader后矩阵是行主序还是列主序就不会有其他影响(只会影响计算的效率),比如通过代码获取某个元素的值,我们要获取第一行第三列的值,都是通过_m02来获取。

但是为了使效率最高,对于列主序存储的矩阵我们要“右乘”,对于行主序存储的矩阵我们要“左乘”。

因为DirectXMath中使用行主序矩阵,向量和矩阵相乘使用“左乘”,要想在Shader中读取正确的矩阵,我们就要转置一下,比如一个平移变换,在DirectXMath中是这样:

959db11d30534f012d702a1f9e806584.png

矩阵“左乘”表示平移变换:

cc28286c69085965470114353d66d91b.png

那在HLSL中使用的是列主序矩阵,为了效率我们使用“右乘”,要表示相同的平移变换,就要传入上面矩阵的转置矩阵:

3b1ae58f502346013348d0b21ef86147.png

所以在把DirectXMath的矩阵传入HLSL时需要传入原矩阵的转置。

Reference:

https://docs.microsoft.com/zh-cn/windows/win32/direct3dhlsl/dx-graphics-hlsl-per-component-math?redirectedfrom=MSDN​docs.microsoft.com HLSL mul() and row/column major matricies in directx​www.gamedev.net
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值