Во-первых, в вашем шейдере вы захотите поместить свои матрицы в постоянный буфер:
cbuffer CameraBuffer : register( b0 ) {
float4x4 World;
float4x4 View;
float4x4 Projection;
}
Если вы не объявляете постоянный буфер, они создаются за вас, но гораздо лучше объявить их явно и сгруппировать по частоте обновления. Например, сгруппируйте вместе все константы, которые обновляются для каждого кадра, и все константы, которые устанавливаются только один раз. Это позволяет вам обновлять только те константы, которые вам нужно обновить, без отправки дополнительных данных в GPU.
Несмотря на то, что они находятся внутри этой структуры cbuffer, доступ к ним в вашем шейдере остается таким же.
В вашем коде C++ вы захотите объявить аналогичную структуру для хранения ваших матриц:
struct CameraConstants {
XMFLOAT4X4 world;
XMFLOAT4X4 view;
XMFLOAT4X4 projection;
};
Очень важно позаботиться о правила упаковки для постоянных переменных. У этой структуры не будет проблем, но в некоторых случаях вам может потребоваться добавить дополнительное заполнение к вашим структурам C++, чтобы учесть тот факт, что буферы шейдера упаковывают данные так, чтобы они не пересекали 16-байтовые границы из-за 16-байтовой природы структуры. Регистры графического процессора.
Во время инициализации вам также потребуется создать постоянный буфер. Процесс такой же, как и для буфера вершин, за исключением того, что вам нужно будет использовать следующие флаги, чтобы объявить постоянный буфер, доступный для записи ЦП:
cbDesc.Usage = D3D11_USAGE_DYNAMIC;
cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
Всякий раз, когда вы обновляете свои матрицы, вам необходимо загрузить их в GPU. Для этого вы сопоставляете буфер констант с процессором и копируете свою структуру CameraConstants
:
D3D11_MAPPED_SUBRESOURCE resource;
m_deviceContext->Map( cameraCbuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource );
memcpy( resource.pData, cameraConstants, sizeof( CameraConstants ) );
m_deviceContext->Unmap( cameraCbuffer, 0 );
Теперь просто привяжите буфер констант к вашему вершинному шейдеру:
m_deviceContext->VSSetConstantBuffers( 0, 1, &cameraCbuffer );
Обратите внимание, что первый параметр сопоставляется с регистром, который вы использовали в объявлении буфера шейдера (в данном случае b0
).
Еще одна вещь: матрицы в hlsl по умолчанию являются основными по столбцам. Если ваши матрицы являются основными строками в C++ (вероятно), вам нужно либо транспонировать их перед отправкой на графический процессор, либо объявить ваши матрицы как row_major
в шейдере.
Ознакомьтесь с примерами DirectX, чтобы найти исходный код всего этого: https://code.msdn.microsoft.com/windowsdesktop/Direct3D-Tutorial-Win32-829979ef
person
megadan
schedule
27.10.2014