0

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

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

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

当我尝试将它们与 XMMatrixMultiply() 函数相乘时,我得到一个访问违规错误。

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

1 回答 1

0

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

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 ) );

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

综上所述,如果您的g_ProjectionMatrix,g_worldmatrixg_viewmatrix变量是真正的全局变量,如该教程中所示,并且您遇到了 AV,那么您可能还会遇到编译器错误。你用的是什么版本的VS?VS 2008 和 VS 2010 对于内在函数来说有点问题。VS 2010 Service Pack 1 比 VS 2010 RTM 好一点。VS 2012 和 VS 2013 好很多。确保您使用的是 VS 2012 或 VS 2013 的最新更新。如果您没有 VS 2013 Pro+ 的预算,我建议您转到 VS 2013 社区(也是 VS 更新 4)。

请注意,这里的另一个选项是使用DirectX 工具包中的SimpleMath包装器,它使用一些 C++“魔术”来使编写“天真的”数学代码更加宽容,例如, , ,等类型。MatrixVector2Vector3Vector4

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

Matrix g_ProjectionMatrix;
Matrix g_worldMatrix;
Matrix g_viewMatrix;

...

Matrix wvp = proj * world * view;
于 2015-01-07T19:17:35.873 回答