これはおそらく時期尚早の最適化の下で提出される可能性がありますが、頂点シェーダーは各フレームの各頂点で実行されるため、実行する価値があるように思えます (ピクセル シェーダーに行く前に乗算する必要がある変数がたくさんあります)。
基本的に、頂点シェーダーはこの操作を実行して、次のようにベクトルを投影空間に変換します。
// Transform the vertex position into projected space.
pos = mul(pos, model);
pos = mul(pos, view);
pos = mul(pos, projection);
output.pos = pos;
シェーダーで複数のベクトルに対してこの操作を行っているため、これらの行列を CPU で累積行列に結合し、それを計算のために GPU にフラッシュすることは理にかなっています。
// VertexShader.hlsl
cbuffer ModelViewProjectionConstantBuffer : register (b0)
{
matrix model;
matrix view;
matrix projection;
matrix cummulative;
float3 eyePosition;
};
...
// Transform the vertex position into projected space.
pos = mul(pos, cummulative);
output.pos = pos;
そしてCPU上:
// Renderer.cpp
// now is also the time to update the cummulative matrix
m_constantMatrixBufferData->cummulative =
m_constantMatrixBufferData->model *
m_constantMatrixBufferData->view *
m_constantMatrixBufferData->projection;
// NOTE: each of the above vars is an XMMATRIX
私の直感では、行優先/列優先の不一致がありましたが、XMMATRIX は行優先の構造体であり (そしてそのすべての演算子はそれをそのように扱います)、mul(...) はその行列パラメーターを行として解釈します-選考科目。それは問題ではないようですが、おそらくまだ私には理解できない方法です。
累積マトリックスの内容も確認しましたが、それらは正しいように見え、さらに混乱を招きました。
読んでくれてありがとう、私はあなたが私に与えることができるヒントを本当に感謝します.
編集 (コメントで要求される追加情報): これは、行列定数バッファーとして使用している構造体です。
// a constant buffer that contains the 3 matrices needed to
// transform points so that they're rendered correctly
struct ModelViewProjectionConstantBuffer
{
DirectX::XMMATRIX model;
DirectX::XMMATRIX view;
DirectX::XMMATRIX projection;
DirectX::XMMATRIX cummulative;
DirectX::XMFLOAT3 eyePosition;
// and padding to make the size divisible by 16
float padding;
};
次のように、(他の定数バッファーと共に) CreateDeviceResources でマトリックス スタックを作成します。
void ModelRenderer::CreateDeviceResources()
{
Direct3DBase::CreateDeviceResources();
// Let's take this moment to create some constant buffers
... // creation of other constant buffers
// and lastly, the all mighty matrix buffer
CD3D11_BUFFER_DESC constantMatrixBufferDesc(sizeof(ModelViewProjectionConstantBuffer), D3D11_BIND_CONSTANT_BUFFER);
DX::ThrowIfFailed(
m_d3dDevice->CreateBuffer(
&constantMatrixBufferDesc,
nullptr,
&m_constantMatrixBuffer
)
);
... // and the rest of the initialization (reading in the shaders, loading assets, etc)
}
作成したマトリックス スタック クラス内のマトリックス バッファーに書き込みます。行列の変更が完了すると、クラスのクライアントは Update() を呼び出します。
void MatrixStack::Update()
{
// then update the buffers
m_constantMatrixBufferData->model = model.front();
m_constantMatrixBufferData->view = view.front();
m_constantMatrixBufferData->projection = projection.front();
// NOTE: the eye position has no stack, as it's kept updated by the trackball
// now is also the time to update the cummulative matrix
m_constantMatrixBufferData->cummulative =
m_constantMatrixBufferData->model *
m_constantMatrixBufferData->view *
m_constantMatrixBufferData->projection;
// and flush
m_d3dContext->UpdateSubresource(
m_constantMatrixBuffer.Get(),
0,
NULL,
m_constantMatrixBufferData,
0,
0
);
}