使用 DirectXMath 进行矩阵乘法

Matrixmultiplication with DirectXMath

我完成了教程 http://3dgep.com/introduction-to-directx-11

在教程中,3 个矩阵(投影、视图和世界矩阵)被发送到顶点着色器并在那里相乘。

我想将 3 个矩阵相乘只得到一个我必须发送到顶点着色器的矩阵。

当我尝试将它们与 XMMatrixMultiply() 函数相乘时,出现访问冲突错误。

XMMatrix wvp=XMMatrixMultiply(g_ProjectionMatrix,XMMatrixMultiply(g_worldmatrix,g_viewmatrix));

您可能会遇到 AV,因为您没有正确考虑变量与内存的对齐情况。 DirectXMath(又名 XNAMath)有两种 'SIMD' 类型 XMVECTORXMMATRIX,它们必须始终为 16 字节对齐。如果分配为全局变量、静态变量或在堆栈上,它们将正确对齐。它们在堆分配内存(newmalloc)中正确对齐,仅适用于 x64 本机应用程序。对于 32 位 (x86) 或 ARM,默认情况下它们不是。因此,DirectXMath 还提供了各种数据存储类型和 load/store 函数来处理此问题而无需担心对齐(即 XMFLOAT4X4XMLoadFloat4x4 / XMStoreFloat4x4 函数)。 MSDN 上的程序员指南对此进行了介绍,我强烈建议您花时间通读。

所以不要使用 XMMATRIX 作为数据存储变量,你可以这样做:

XMFLOAT4X4 g_ProjectionMatrix;
XMFLOAT4X4 g_worldMatrix;
XMFLOAT4X4 g_viewMatrix;

...

XMMATRIX proj = XMLoadFloat4x4( &g_ProjectionMatrix );
XMMATRIX world = XMLoadFloat4x4( &g_worldMatrix );
XMMATRIX view = XMLoadFloat4x4( &g_viewMatrix );
XMMATRIX wvp = XMMatrixMultiply( proj, XMMatrixMultiply( world, view ) );

虽然这有点冗长,但它更直接地映射到硬件实际在做什么,让您看到机会避免 load/store 开销并继续处理可能保存在 SIMD 寄存器中的数据更长。

综上所述,如果您的 g_ProjectionMatrixg_worldmatrixg_viewmatrix 变量确实是全局的,如该教程所示,并且您正在点击 AV,那么您可能也会点击编译器错误。你用的是什么版本的VS? VS 2008 和 VS 2010 有点问题 w.r.t。到内在。 VS 2010 Service Pack 1 比 VS 2010 RTM 好一点。 VS 2012 和 VS 2013 好多了。确保您使用的是 VS 2012 或 VS 2013 的最新更新。如果您没有 VS 2013 Pro+ 的预算,我建议您转到 VS 2013 Community(也是 VS Update 4)。

请注意,这里的另一种选择是使用 SimpleMath wrapper in the DirectX Tool Kit,它使用一些 C++ 'magic' 来编写 'naive' 数学代码,使用 [=25] 这样的类型更加宽容=]、Vector2Vector3Vector4

#include "SimpleMath.h"
using namespace DirectX::SimpleMath;

Matrix g_ProjectionMatrix;
Matrix g_worldMatrix;
Matrix g_viewMatrix;

...

Matrix wvp = proj * world * view;