MultiBone
현재 만들었던 모델에서 원하는 본의 위치를 알기 위해 본을 ComputeShader로 넘겨서 만들어준다.
ModelAnimator
ModelAnimator::ModelAnimator(Shader * shader)
: shader(shader)
{
model = new Model();
tweenBuffer = new ConstantBuffer(&tweenDesc, sizeof(TweenDesc) * MAX_MODEL_INSTANCE);
sTweenBuffer = shader->AsConstantBuffer("CB_TweenFrame");
blendBuffer = new ConstantBuffer(&blendDesc, sizeof(BlendDesc) * MAX_MODEL_INSTANCE);
sBlendBuffer = shader->AsConstantBuffer("CB_BlendFrame");
instanceBuffer = new VertexBuffer(worlds, MAX_MODEL_INSTANCE, sizeof(Matrix), 1, true);
// Create Compute Shader
{
computeShader = new Shader(L"71_GetMultiBones.fx");
inputWorldBuffer = new StructuredBuffer(worlds, sizeof(Matrix), MAX_MODEL_INSTANCE);
sInputWorldSRV = computeShader->AsSRV("InputWorlds");
inputBoneBuffer = new StructuredBuffer(NULL, sizeof(Matrix), MAX_MODEL_TRANSFORMS);
sInputBoneSRV = computeShader->AsSRV("InputBones");
ID3D11Texture2D* texture;
D3D11_TEXTURE2D_DESC desc;
ZeroMemory(&desc, sizeof(D3D11_TEXTURE2D_DESC));
desc.Width = MAX_MODEL_TRANSFORMS * 4;
desc.Height = MAX_MODEL_INSTANCE;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
desc.MipLevels = 1;
desc.SampleDesc.Count = 1;
Check(D3D::GetDevice()->CreateTexture2D(&desc, NULL, &texture));
outputBuffer = new TextureBuffer(texture);
SafeRelease(texture);
sOutputUAV = computeShader->AsUAV("Output");
sTransformsSRV = computeShader->AsSRV("TransformsMap");
sComputeTweenBuffer = computeShader->AsConstantBuffer("CB_TweenFrame");
sComputeBlendBuffer = computeShader->AsConstantBuffer("CB_BlendFrame");
}
}
일단 만들 쉐이더의 변수에 맞게 InputOutput값을 갖고온다.
그리고
if (texture == NULL)
{
for (ModelMesh* mesh : model->Meshes())
{
mesh->SetShader(shader);
}
CreateTexture();
Matrix bones[MAX_MODEL_TRANSFORMS];
for (UINT i = 0; i < model->BoneCount(); i++)
{
bones[i] = model->BoneByIndex(i)->Transform();
}
inputBoneBuffer->CopyToInput(bones);
}
Update문에서 값을 갖고오게 바꿔준다.
void ModelAnimator::GetAttachTransform(UINT instance, Matrix * outResult)
{
ID3D11Texture2D* texture = outputBuffer->Result();
D3D11_MAPPED_SUBRESOURCE subResource;
D3D::GetDC()->Map(texture, 0, D3D11_MAP_READ, 0, &subResource);
{
memcpy(outResult, (BYTE *)subResource.pData + (instance * subResource.RowPitch), sizeof(Matrix) * MAX_MODEL_TRANSFORMS);
}
D3D::GetDC()->Unmap(texture, 0);
}
현재 본의 위치를 instance로 바꿔서 갖고올 수 있게 해준다.
현재 받아온 데이터의 원하는 클립의 y축 좌표를 갖고 곱해서 갖고온다.
마지막으로
void ModelAnimator::UpdateTransforms()
{
for (UINT i = 0; i < transforms.size(); i++)
memcpy(worlds[i], transforms[i]->World(), sizeof(Matrix));
D3D11_MAPPED_SUBRESOURCE subResource;
D3D::GetDC()->Map(instanceBuffer->Buffer(), 0, D3D11_MAP_WRITE_DISCARD, 0, &subResource);
{
memcpy(subResource.pData, worlds, sizeof(Matrix) * MAX_MESH_INSTANCE);
}
D3D::GetDC()->Unmap(instanceBuffer->Buffer(), 0);
inputWorldBuffer->CopyToInput(worlds);
}
현재 Transform을 넘겨준 값을 갖고오고 위치를 업데이트 시켜준다.