Умножение матриц с DirectXMath

Я сделал учебник http://3dgep.com/introduction-to-directx-11.

В уроке 3 матрицы (проекция, вид и мировая матрица) отправляются в вершинный шейдер и там умножаются.

Я хочу умножить 3 матрицы, чтобы получить только одну, которую я должен отправить вершинному шейдеру.

Когда я пытался умножить их с помощью функции XMMatrixMultiply(), я получил ошибку accessviolation.

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

1 ответ

Решение

Скорее всего, вы попали в AV, потому что не правильно учли выравнивание памяти с вашими переменными. DirectXMath (он же XNAMath) имеет два типа SIMD XMVECTOR а также XMMATRIX который всегда должен быть выровнен по 16 байтов. Они правильно выровнены, если размещены как глобальные переменные, статические переменные или в стеке. Они правильно выровнены в выделенной памяти кучи (new или же malloc) только с родными приложениями x64. С 32-битным (x86) или ARM они не по умолчанию. Таким образом, DirectXMath также предоставляет ассортимент типов хранения данных и функций загрузки / хранения для обработки этого, не заботясь о выравнивании (т.е. XMFLOAT4X4 и XMLoadFloat4x4 / 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 ) );

Хотя это немного многословно, оно более точно соответствует тому, что на самом деле делает аппаратное обеспечение, позволяя вам увидеть возможности избежать накладных расходов на загрузку / хранение и продолжать работать с данными, которые, вероятно, будут храниться в регистрах SIMD дольше.

Все, что сказано, если ваш g_ProjectionMatrix, g_worldmatrix, а также g_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 (которое также является обновлением VS 4), если у вас нет бюджета на VS 2013 Pro+.

Обратите внимание, что другой вариант здесь заключается в использовании оболочки SimpleMath в наборе инструментов DirectX, которая использует некоторую "магию" C++, чтобы сделать наивный "математический" код намного проще для таких типов, как Matrix, Vector2, Vector3, Vector4, так далее.

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

Matrix g_ProjectionMatrix;
Matrix g_worldMatrix;
Matrix g_viewMatrix;

...

Matrix wvp = proj * world * view;
Другие вопросы по тегам