[DirectX11] 071~73 Get MultiBones
DirectX 11에서 Multibones는 스켈레탈 애니메이션을 구현하는 데 사용되는 기술이다. 스켈레탈 애니메이션은 3D 모델의 뼈대와 관련된 것으로, 모델이 움직이는 동안 뼈대가 움직이며 모델을 변형시킨다. Multibones는 여러 개의 뼈대를 사용하여 더욱 자연스러운 애니메이션을 만들어낸다. 이를 통해 모델의 각 부분에 대해 다양한 뼈대를 지정할 수 있으며, 더 복잡한 동작을 만들어낼 수 있다.
Get Multibones
DirectX 11에서 Multibones는 스켈레탈 애니메이션을 구현하는 데 사용되는 기술이다. 스켈레탈 애니메이션은 3D 모델의 뼈대와 관련된 것으로, 모델이 움직이는 동안 뼈대가 움직이며 모델을 변형시킨다.
Multibones는 여러 개의 뼈대를 사용하여 더욱 자연스러운 애니메이션을 만들어낸다. 이를 통해 모델의 각 부분에 대해 다양한 뼈대를 지정할 수 있으며, 더 복잡한 동작을 만들어낼 수 있다.
Multibones를 구현하려면 각 뼈대의 정보를 정의하는 뼈대 행렬들을 생성해야 한다. 이 행렬들은 모델의 뼈대들 사이의 계층 구조와 연관되어 있다. 이러한 뼈대 행렬들은 GPU에서 계산되며, 각 프레임마다 각 뼈대의 위치와 회전을 계산하여 모델의 애니메이션을 만든다.
Multibones를 사용하여 더욱 자연스러운 애니메이션을 만들 수 있지만, 이를 구현하기 위해서는 더 많은 계산이 필요하며, 따라서 프로세서와 그래픽 카드의 성능이 더욱 중요해진다.
Shader | |
GetMultiBones.fx | |
Framework | |
Model | |
ModelAnimator.h .cpp | |
Renders | |
Buffers.h .cpp | |
UnitTest | |
DirectCompute | |
GetMultiBoneDemo |
GetMultiBones.fx
GetMultiBones.fx
#include "00_Global.fx" #include "00_Light.fx" #include "00_Render.fx" struct WorldDesc { matrix Transform; }; StructuredBuffer<WorldDesc> InputWorlds;//inputWorldBuffer //Model Animator에 있는 Compute Shader struct BoneDesc { matrix Transform; }; StructuredBuffer<BoneDesc> InputBones;//inputBoneBuffer // 한장인데 그냥 2DArray사용 RWTexture2DArray<float4> Output; void SetTweenBones(inout matrix world, uint3 id) { // 공간을 계산할꺼라 가중치가 필요없음 int clip[2]; int currFrame[2]; int nextFrame[2]; float time[2]; clip[0] = TweenFrames[id.y].Curr.Clip; currFrame[0] = TweenFrames[id.y].Curr.CurrFrame; nextFrame[0] = TweenFrames[id.y].Curr.NextFrame; time[0] = TweenFrames[id.y].Curr.Time; clip[1] = TweenFrames[id.y].Next.Clip; currFrame[1] = TweenFrames[id.y].Next.CurrFrame; nextFrame[1] = TweenFrames[id.y].Next.NextFrame; time[1] = TweenFrames[id.y].Next.Time; float4 c0, c1, c2, c3; float4 n0, n1, n2, n3; matrix curr = 0, next = 0; matrix currAnim = 0; matrix nextAnim = 0; // 본은 x에 매핑 c0 = TransformsMap.Load(int4(id.x * 4 + 0, currFrame[0], clip[0], 0)); c1 = TransformsMap.Load(int4(id.x * 4 + 1, currFrame[0], clip[0], 0)); c2 = TransformsMap.Load(int4(id.x * 4 + 2, currFrame[0], clip[0], 0)); c3 = TransformsMap.Load(int4(id.x * 4 + 3, currFrame[0], clip[0], 0)); curr = matrix(c0, c1, c2, c3); n0 = TransformsMap.Load(int4(id.x * 4 + 0, nextFrame[0], clip[0], 0)); n1 = TransformsMap.Load(int4(id.x * 4 + 1, nextFrame[0], clip[0], 0)); n2 = TransformsMap.Load(int4(id.x * 4 + 2, nextFrame[0], clip[0], 0)); n3 = TransformsMap.Load(int4(id.x * 4 + 3, nextFrame[0], clip[0], 0)); next = matrix(n0, n1, n2, n3); currAnim = lerp(curr, next, time[0]); [flatten] if (clip[1] > -1) { c0 = TransformsMap.Load(int4(id.x * 4 + 0, currFrame[1], clip[1], 0)); c1 = TransformsMap.Load(int4(id.x * 4 + 1, currFrame[1], clip[1], 0)); c2 = TransformsMap.Load(int4(id.x * 4 + 2, currFrame[1], clip[1], 0)); c3 = TransformsMap.Load(int4(id.x * 4 + 3, currFrame[1], clip[1], 0)); curr = matrix(c0, c1, c2, c3); n0 = TransformsMap.Load(int4(id.x * 4 + 0, nextFrame[1], clip[1], 0)); n1 = TransformsMap.Load(int4(id.x * 4 + 1, nextFrame[1], clip[1], 0)); n2 = TransformsMap.Load(int4(id.x * 4 + 2, nextFrame[1], clip[1], 0)); n3 = TransformsMap.Load(int4(id.x * 4 + 3, nextFrame[1], clip[1], 0)); next = matrix(n0, n1, n2, n3); nextAnim = lerp(curr, next, time[1]); currAnim = lerp(currAnim, nextAnim, TweenFrames[id.y].TweenTime); } world = mul(currAnim, world); } void SetBlendBones(inout matrix world, uint3 id) { float4 c0, c1, c2, c3; float4 n0, n1, n2, n3; matrix curr = 0, next = 0; matrix currAnim[3]; matrix anim = 0; BlendFrame frame = BlendFrames[id.y]; [unroll(3)] for (int k = 0; k < 3; k++) { c0 = TransformsMap.Load(int4(id.x * 4 + 0, frame.Clip[k].CurrFrame, frame.Clip[k].Clip, 0)); c1 = TransformsMap.Load(int4(id.x * 4 + 1, frame.Clip[k].CurrFrame, frame.Clip[k].Clip, 0)); c2 = TransformsMap.Load(int4(id.x * 4 + 2, frame.Clip[k].CurrFrame, frame.Clip[k].Clip, 0)); c3 = TransformsMap.Load(int4(id.x * 4 + 3, frame.Clip[k].CurrFrame, frame.Clip[k].Clip, 0)); curr = matrix(c0, c1, c2, c3); n0 = TransformsMap.Load(int4(id.x * 4 + 0, frame.Clip[k].NextFrame, frame.Clip[k].Clip, 0)); n1 = TransformsMap.Load(int4(id.x * 4 + 1, frame.Clip[k].NextFrame, frame.Clip[k].Clip, 0)); n2 = TransformsMap.Load(int4(id.x * 4 + 2, frame.Clip[k].NextFrame, frame.Clip[k].Clip, 0)); n3 = TransformsMap.Load(int4(id.x * 4 + 3, frame.Clip[k].NextFrame, frame.Clip[k].Clip, 0)); next = matrix(n0, n1, n2, n3); currAnim[k] = lerp(curr, next, frame.Clip[k].Time); } int clipA = (int) frame.Alpha; int clipB = clipA + 1; float alpha = frame.Alpha; if (alpha >= 1.0f) { alpha = frame.Alpha - 1.0f; if (frame.Alpha >= 2.0f) { clipA = 1; clipB = 2; } } anim = lerp(currAnim[clipA], currAnim[clipB], alpha); world = mul(anim, world); } [numthreads(MAX_MODEL_TRANSFORMS, 1, 1)] void CS(uint3 id : SV_DispatchThreadID) { //기준본 * 애니메이션 * 월드 // SV_DispatchThreadID을 사용하면 그룹에 상관없이 번호가 이어짐 1대1로 // y가 트랜스폼 ID와 일치함 matrix world = InputWorlds[id.y].Transform; if (BlendFrames[id.y].Mode == 0) SetTweenBones(world, id); else SetBlendBones(world, id); world = mul(InputBones[id.x].Transform, world); // desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; float4 m0 = world._11_12_13_14; float4 m1 = world._21_22_23_24; float4 m2 = world._31_32_33_34; float4 m3 = world._41_42_43_44; Output[int3(id.x * 4 + 0, id.y, id.z)] = m0; Output[int3(id.x * 4 + 1, id.y, id.z)] = m1; Output[int3(id.x * 4 + 2, id.y, id.z)] = m2; Output[int3(id.x * 4 + 3, id.y, id.z)] = m3; } technique11 T0 { pass P0 { SetVertexShader(NULL); SetPixelShader(NULL); SetComputeShader(CompileShader(cs_5_0, CS())); } }
Dispatcher Thread ID를 사용하면 그룹에 상관없이 ID와 Texture를 펼친것(=Instance Id)이 1:1로 대응하게 된다.
Model Animator
ModelAnimator.h
#pragma once class ModelAnimator { public: ModelAnimator(Shader* shader); ~ModelAnimator(); void Update(); private: void UpdateTweenMode(UINT index); void UpdateBlendMode(UINT index); public: void Render(); public: void ReadMesh(wstring file); void ReadMaterial(wstring file); void ReadClip(wstring file); Model* GetModel() { return model; } void Pass(UINT pass); Transform* AddTransform(); Transform* GetTransform(UINT index) { return transforms[index]; } void UpdateTransforms(); UINT GetTransformCount() { return transforms.size(); } void PlayTweenMode(UINT index, UINT clip, float speed = 1.0f, float takeTime = 1.0f); void PlayBlendMode(UINT index, UINT clip, UINT clip1, UINT clip2); void SetBlendAlpha(UINT index, float alpha); void GetAttachTransform(UINT instance, Matrix* outResult); private: void CreateTexture(); void CreateClipTransform(UINT index); private: struct ClipTransform { Matrix** Transform; ClipTransform() { Transform = new Matrix*[MAX_MODEL_KEYFRAMES]; for (UINT i = 0; i < MAX_MODEL_KEYFRAMES; i++) Transform[i] = new Matrix[MAX_MODEL_TRANSFORMS]; } ~ClipTransform() { for (UINT i = 0; i < MAX_MODEL_KEYFRAMES; i++) SafeDeleteArray(Transform[i]); SafeDeleteArray(Transform); } }; ClipTransform* clipTransforms = NULL; ID3D11Texture2D* texture = NULL; ID3D11ShaderResourceView* srv = NULL; private: struct KeyframeDesc { int Clip = 0; UINT CurrFrame = 0; UINT NextFrame = 0; float Time = 0.0f; float RunningTime = 0.0f; float Speed = 1.0f; Vector2 Padding; }; // keyframeDesc; struct TweenDesc { float TakeTime = 1.0f; float TweenTime = 0.0f; float ChangeTime = 0.0f; float Padding; KeyframeDesc Curr; KeyframeDesc Next; TweenDesc() { Curr.Clip = 0; Next.Clip = -1; } } tweenDesc[MAX_MODEL_INSTANCE]; ConstantBuffer* tweenBuffer; ID3DX11EffectConstantBuffer* sTweenBuffer; private: struct BlendDesc { UINT Mode = 0; float Alpha = 0; Vector2 Padding; KeyframeDesc Clip[3]; } blendDesc[MAX_MODEL_INSTANCE]; ConstantBuffer* blendBuffer; ID3DX11EffectConstantBuffer* sBlendBuffer; private: Shader* shader; Model* model; vector<Transform *> transforms; Matrix worlds[MAX_MODEL_INSTANCE]; VertexBuffer* instanceBuffer; private: struct CS_InputDesc { Matrix Bone; }; struct CS_OutputDesc { Matrix Result; }; private: const float frameRate = 30.0f; //매 프레임 마다 계산하면 계산양이 많아서 30프레임으로 설정. float frameTime = 0.0f; Shader* computeShader; ID3DX11EffectShaderResourceVariable* sTransformsSRV; StructuredBuffer* inputWorldBuffer; ID3DX11EffectShaderResourceVariable* sInputWorldSRV; //입력용 버퍼 StructuredBuffer* inputBoneBuffer; ID3DX11EffectShaderResourceVariable* sInputBoneSRV; //입력용 버퍼 TextureBuffer* outputBuffer; ID3DX11EffectUnorderedAccessViewVariable* sOutputUAV;//출력용 버퍼 ID3DX11EffectConstantBuffer* sComputeTweenBuffer; //Tween 정보 ID3DX11EffectConstantBuffer* sComputeBlendBuffer; //Blend 정보 };
ModelAnimator.cpp
#include "Framework.h" #include "ModelAnimator.h" 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"); } } ModelAnimator::~ModelAnimator() { SafeDelete(model); SafeDeleteArray(clipTransforms); SafeRelease(texture); SafeRelease(srv); SafeDelete(tweenBuffer); SafeDelete(blendBuffer); SafeDelete(instanceBuffer); SafeDelete(computeShader); SafeDelete(inputWorldBuffer); SafeDelete(inputBoneBuffer); SafeDelete(outputBuffer); } void ModelAnimator::Update() { 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(); //최초의 기준Bone에서 현재 애니메이션의 행렬을 계산 inputBoneBuffer->CopyToInput(bones);//계산해서 넣어줌 } for (UINT i = 0; i < transforms.size(); i++) blendDesc[i].Mode == 0 ? UpdateTweenMode(i) : UpdateBlendMode(i); tweenBuffer->Render(); blendBuffer->Render(); frameTime += Time::Delta(); if (frameTime > (1.0f / frameRate)) { sComputeTweenBuffer->SetConstantBuffer(tweenBuffer->Buffer()); sComputeBlendBuffer->SetConstantBuffer(blendBuffer->Buffer()); sTransformsSRV->SetResource(srv); //srv는 ClipTransform의 정보를 가지고 있다. sInputWorldSRV->SetResource(inputWorldBuffer->SRV()); sInputBoneSRV->SetResource(inputBoneBuffer->SRV()); sOutputUAV->SetUnorderedAccessView(outputBuffer->UAV()); computeShader->Dispatch(0, 0, 1, MAX_MODEL_INSTANCE, 1);//y를 instance로 사용 outputBuffer->CopyFromOutput(); } frameTime = fmod(frameTime, (1.0f / frameRate)); if (Keyboard::Get()->Down(VK_SPACE)) { ID3D11Texture2D* temp = outputBuffer->CopyFromOutput(); FILE* src; fopen_s(&src, "../src.csv", "w"); Matrix id[MAX_MODEL_TRANSFORMS]; for (UINT y = 0; y < MAX_MODEL_INSTANCE; y++) { D3D11_MAPPED_SUBRESOURCE subResource; D3D::GetDC()->Map(temp, 0, D3D11_MAP_READ, 0, &subResource); { void* p = (BYTE *)subResource.pData + y * subResource.RowPitch; memcpy(id, p, MAX_MODEL_TRANSFORMS * sizeof(Matrix)); } D3D::GetDC()->Unmap(temp, 0); for (UINT x = 0; x < MAX_MODEL_TRANSFORMS; x++) { Matrix destMatrix = id[x]; fprintf(src, "%f,%f,%f,%f,", destMatrix._11, destMatrix._12, destMatrix._13, destMatrix._14); fprintf(src, "%f,%f,%f,%f,", destMatrix._21, destMatrix._22, destMatrix._23, destMatrix._24); fprintf(src, "%f,%f,%f,%f,", destMatrix._31, destMatrix._32, destMatrix._33, destMatrix._34); fprintf(src, "%f,%f,%f,%f\n", destMatrix._41, destMatrix._42, destMatrix._43, destMatrix._44); } } fclose(src); } for (ModelMesh* mesh : model->Meshes()) mesh->Update(); } void ModelAnimator::UpdateTweenMode(UINT index) { TweenDesc& desc = tweenDesc[index]; //현재 애니메이션 { ModelClip* clip = model->ClipByIndex(desc.Curr.Clip); desc.Curr.RunningTime += Time::Delta(); float time = 1.0f / clip->FrameRate() / desc.Curr.Speed; if (desc.Curr.Time >= 1.0f) { desc.Curr.RunningTime = 0; desc.Curr.CurrFrame = (desc.Curr.CurrFrame + 1) % clip->FrameCount(); desc.Curr.NextFrame = (desc.Curr.CurrFrame + 1) % clip->FrameCount(); } desc.Curr.Time = desc.Curr.RunningTime / time; } if (desc.Next.Clip > -1) { desc.ChangeTime += Time::Delta(); desc.TweenTime = desc.ChangeTime / desc.TakeTime; if (desc.TweenTime >= 1.0f) { desc.Curr = desc.Next; desc.Next.Clip = -1; desc.Next.CurrFrame = 0; desc.Next.NextFrame = 0; desc.Next.Time = 0; desc.Next.RunningTime = 0.0f; desc.ChangeTime = 0.0f; desc.TweenTime = 0.0f; } else { ModelClip* clip = model->ClipByIndex(desc.Next.Clip); desc.Next.RunningTime += Time::Delta(); float time = 1.0f / clip->FrameRate() / desc.Next.Speed; if (desc.Next.Time >= 1.0f) { desc.Next.RunningTime = 0; desc.Next.CurrFrame = (desc.Next.CurrFrame + 1) % clip->FrameCount(); desc.Next.NextFrame = (desc.Next.CurrFrame + 1) % clip->FrameCount(); } desc.Next.Time = desc.Next.RunningTime / time; } } } void ModelAnimator::UpdateBlendMode(UINT index) { BlendDesc& desc = blendDesc[index]; for (UINT i = 0; i < 3; i++) { ModelClip* clip = model->ClipByIndex(desc.Clip[i].Clip); desc.Clip[i].RunningTime += Time::Delta(); float time = 1.0f / clip->FrameRate() / desc.Clip[i].Speed; if (desc.Clip[i].Time >= 1.0f) { desc.Clip[i].RunningTime = 0; desc.Clip[i].CurrFrame = (desc.Clip[i].CurrFrame + 1) % clip->FrameCount(); desc.Clip[i].NextFrame = (desc.Clip[i].CurrFrame + 1) % clip->FrameCount(); } desc.Clip[i].Time = desc.Clip[i].RunningTime / time; } } void ModelAnimator::Render() { sTweenBuffer->SetConstantBuffer(tweenBuffer->Buffer()); sBlendBuffer->SetConstantBuffer(blendBuffer->Buffer()); instanceBuffer->Render(); for (ModelMesh* mesh : model->Meshes()) mesh->Render(transforms.size()); } void ModelAnimator::ReadMesh(wstring file) { model->ReadMesh(file); } void ModelAnimator::ReadMaterial(wstring file) { model->ReadMaterial(file); } void ModelAnimator::ReadClip(wstring file) { model->ReadClip(file); } void ModelAnimator::Pass(UINT pass) { for (ModelMesh* mesh : model->Meshes()) mesh->Pass(pass); } void ModelAnimator::PlayTweenMode(UINT index, UINT clip, float speed, float takeTime) { blendDesc[index].Mode = 0; tweenDesc[index].TakeTime = takeTime; tweenDesc[index].Next.Clip = clip; tweenDesc[index].Next.Speed = speed; } void ModelAnimator::PlayBlendMode(UINT index, UINT clip, UINT clip1, UINT clip2) { blendDesc[index].Mode = 1; blendDesc[index].Clip[0].Clip = clip; blendDesc[index].Clip[1].Clip = clip1; blendDesc[index].Clip[2].Clip = clip2; } void ModelAnimator::SetBlendAlpha(UINT index, float alpha) { alpha = Math::Clamp(alpha, 0.0f, 2.0f); blendDesc[index].Alpha = alpha; } 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); { //instance 크기 만큼 이동한 후에 한줄의 크기(sizeof(Matrix)*MAX_MODEL_TRANSFORMS) 만큼 가져온다. memcpy(outResult, (BYTE *)subResource.pData + (instance * subResource.RowPitch), sizeof(Matrix) * MAX_MODEL_TRANSFORMS); } D3D::GetDC()->Unmap(texture, 0); } void ModelAnimator::CreateTexture() { //Matrix matrix[MAX_MODEL_KEYFRAMES][MAX_MODEL_TRANSFORMS]; clipTransforms = new ClipTransform[model->ClipCount()]; for (UINT i = 0; i < model->ClipCount(); i++) CreateClipTransform(i); //Create Texture { D3D11_TEXTURE2D_DESC desc; ZeroMemory(&desc, sizeof(D3D11_TEXTURE2D_DESC)); desc.Width = MAX_MODEL_TRANSFORMS * 4; desc.Height = MAX_MODEL_KEYFRAMES; desc.ArraySize = model->ClipCount(); desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; //16Byte * 4 = 64Byte desc.Usage = D3D11_USAGE_IMMUTABLE; desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; desc.MipLevels = 1; desc.SampleDesc.Count = 1; UINT pageSize = MAX_MODEL_TRANSFORMS * 4 * 16 * MAX_MODEL_KEYFRAMES; //void* p = malloc(pageSize * model->ClipCount()); void* p = VirtualAlloc(NULL, pageSize * model->ClipCount(), MEM_RESERVE, PAGE_READWRITE); //MEMORY_BASIC_INFORMATION, VirtualQuery for (UINT c = 0; c < model->ClipCount(); c++) { UINT start = c * pageSize; for (UINT k = 0; k < MAX_MODEL_KEYFRAMES; k++) { void* temp = (BYTE *)p + MAX_MODEL_TRANSFORMS * k * sizeof(Matrix) + start; VirtualAlloc(temp, MAX_MODEL_TRANSFORMS * sizeof(Matrix), MEM_COMMIT, PAGE_READWRITE); memcpy(temp, clipTransforms[c].Transform[k], MAX_MODEL_TRANSFORMS * sizeof(Matrix)); } }//for(c) D3D11_SUBRESOURCE_DATA* subResources = new D3D11_SUBRESOURCE_DATA[model->ClipCount()]; for (UINT c = 0; c < model->ClipCount(); c++) { void* temp = (BYTE *)p + c * pageSize; subResources[c].pSysMem = temp; subResources[c].SysMemPitch = MAX_MODEL_TRANSFORMS * sizeof(Matrix); subResources[c].SysMemSlicePitch = pageSize; } Check(D3D::GetDevice()->CreateTexture2D(&desc, subResources, &texture)); SafeDeleteArray(subResources); VirtualFree(p, 0, MEM_RELEASE); } //Create SRV { D3D11_SHADER_RESOURCE_VIEW_DESC desc; ZeroMemory(&desc, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC)); desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; desc.Texture2DArray.MipLevels = 1; desc.Texture2DArray.ArraySize = model->ClipCount(); Check(D3D::GetDevice()->CreateShaderResourceView(texture, &desc, &srv)); } for (ModelMesh* mesh : model->Meshes()) mesh->TransformsSRV(srv); } void ModelAnimator::CreateClipTransform(UINT index) { Matrix* bones = new Matrix[MAX_MODEL_TRANSFORMS]; ModelClip* clip = model->ClipByIndex(index); for (UINT f = 0; f < clip->FrameCount(); f++) { for (UINT b = 0; b < model->BoneCount(); b++) { ModelBone* bone = model->BoneByIndex(b); Matrix parent; Matrix invGlobal = bone->Transform(); D3DXMatrixInverse(&invGlobal, NULL, &invGlobal); int parentIndex = bone->ParentIndex(); if (parentIndex < 0) D3DXMatrixIdentity(&parent); else parent = bones[parentIndex]; Matrix animation; ModelKeyframe* frame = clip->Keyframe(bone->Name()); if (frame != NULL) { ModelKeyframeData& data = frame->Transforms[f]; Matrix S, R, T; D3DXMatrixScaling(&S, data.Scale.x, data.Scale.y, data.Scale.z); D3DXMatrixRotationQuaternion(&R, &data.Rotation); D3DXMatrixTranslation(&T, data.Translation.x, data.Translation.y, data.Translation.z); animation = S * R * T; } else { D3DXMatrixIdentity(&animation); } bones[b] = animation * parent; clipTransforms[index].Transform[f][b] = invGlobal * bones[b]; }//for(b) }//for(f) } Transform * ModelAnimator::AddTransform() { Transform* transform = new Transform(); transforms.push_back(transform); return transform; } 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); }
Buffers
Buffers.h
#pragma once class VertexBuffer { public: VertexBuffer(void* data, UINT count, UINT stride, UINT slot = 0, bool bCpuWrite = false, bool bGpuWrite = false); ~VertexBuffer(); UINT Count() { return count; } UINT Stride() { return stride; } ID3D11Buffer* Buffer() { return buffer; } void Render(); private: ID3D11Buffer* buffer; void* data; UINT count; UINT stride; UINT slot; bool bCpuWrite; bool bGpuWrite; }; class IndexBuffer { public: IndexBuffer(void* data, UINT count); ~IndexBuffer(); UINT Count() { return count; } ID3D11Buffer* Buffer() { return buffer; } void Render(); private: ID3D11Buffer* buffer; void* data; UINT count; }; class ConstantBuffer { public: ConstantBuffer(void* data, UINT dataSize); ~ConstantBuffer(); ID3D11Buffer* Buffer() { return buffer; } void Render(); private: ID3D11Buffer* buffer; void* data; UINT dataSize; }; class CsResource { public: CsResource(); virtual ~CsResource(); protected: virtual void CreateInput() {} virtual void CreateSRV() {} virtual void CreateOutput() {} virtual void CreateUAV() {} virtual void CreateResult() {} void CreateBuffer(); public: ID3D11ShaderResourceView* SRV() { return srv; } ID3D11UnorderedAccessView* UAV() { return uav; } protected: ID3D11Resource* input = NULL; ID3D11ShaderResourceView* srv = NULL; //Input ID3D11Resource* output = NULL; ID3D11UnorderedAccessView* uav = NULL; //Output ID3D11Resource* result = NULL; }; class RawBuffer : public CsResource { public: RawBuffer(void* inputData, UINT inputByte, UINT outputByte); ~RawBuffer(); private: void CreateInput() override; void CreateSRV() override; void CreateOutput() override; void CreateUAV() override; void CreateResult() override; public: void CopyToInput(void* data); void CopyFromOuput(void* data); private: void* inputData; UINT inputByte; UINT outputByte; }; class StructuredBuffer : public CsResource { public: StructuredBuffer(void* inputData, UINT inputStride, UINT inputCount, UINT outputStride = 0, UINT outputCount = 0); ~StructuredBuffer(); private: void CreateInput() override; void CreateSRV() override; void CreateOutput() override; void CreateUAV() override; void CreateResult() override; public: UINT InputByteWidth() { return inputStride * inputCount; } UINT OutputByteWidth() { return outputStride * outputCount; } void CopyToInput(void* data); void CopyFromOutput(void* data); private: void* inputData; UINT inputStride; UINT inputCount; UINT outputStride; UINT outputCount; }; class TextureBuffer : public CsResource { public: TextureBuffer(ID3D11Texture2D* src); ~TextureBuffer(); private: void CreateSRV() override; void CreateOutput() override; void CreateUAV() override; void CreateResult() override; public: UINT Width() { return width; } UINT Height() { return height; } UINT ArraySize() { return arraySize; } ID3D11Texture2D* Output() { return (ID3D11Texture2D *)output; } ID3D11ShaderResourceView* OutputSRV() { return outputSRV; } void CopyToInput(ID3D11Texture2D* texture); ID3D11Texture2D* CopyFromOutput(); ID3D11Texture2D* Result() { return (ID3D11Texture2D *)result; } private: UINT width, height, arraySize; DXGI_FORMAT format; ID3D11ShaderResourceView* outputSRV; };
Buffers.cpp
#include "Framework.h" #include "Buffers.h" VertexBuffer::VertexBuffer(void * data, UINT count, UINT stride, UINT slot, bool bCpuWrite, bool bGpuWrite) : data(data), count(count), stride(stride), slot(slot) , bCpuWrite(bCpuWrite), bGpuWrite(bGpuWrite) { D3D11_BUFFER_DESC desc; ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC)); desc.ByteWidth = stride * count; desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; if (bCpuWrite == false && bGpuWrite == false) { desc.Usage = D3D11_USAGE_IMMUTABLE; //GPU 읽기 } else if (bCpuWrite == true && bGpuWrite == false) { desc.Usage = D3D11_USAGE_DYNAMIC; //CPU 쓰기, GPU 읽기 desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; } else if (bCpuWrite == false && bGpuWrite == true) { //CPU 쓰기 가능 - UpdateSubResource desc.Usage = D3D11_USAGE_DEFAULT; } else { desc.Usage = D3D11_USAGE_STAGING; desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; } D3D11_SUBRESOURCE_DATA subResource = { 0 }; subResource.pSysMem = data; Check(D3D::GetDevice()->CreateBuffer(&desc, &subResource, &buffer)); } VertexBuffer::~VertexBuffer() { SafeRelease(buffer); } void VertexBuffer::Render() { UINT offset = 0; D3D::GetDC()->IASetVertexBuffers(slot, 1, &buffer, &stride, &offset); } IndexBuffer::IndexBuffer(void * data, UINT count) : data(data), count(count) { D3D11_BUFFER_DESC desc; ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC)); desc.ByteWidth = sizeof(UINT) * count; desc.BindFlags = D3D11_BIND_INDEX_BUFFER; desc.Usage = D3D11_USAGE_IMMUTABLE; D3D11_SUBRESOURCE_DATA subResource = { 0 }; subResource.pSysMem = data; Check(D3D::GetDevice()->CreateBuffer(&desc, &subResource, &buffer)); } IndexBuffer::~IndexBuffer() { SafeRelease(buffer); } void IndexBuffer::Render() { D3D::GetDC()->IASetIndexBuffer(buffer, DXGI_FORMAT_R32_UINT, 0); } /////////////////////////////////////////////////////////////////////////////// ConstantBuffer::ConstantBuffer(void * data, UINT dataSize) : data(data), dataSize(dataSize) { D3D11_BUFFER_DESC desc; ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC)); desc.ByteWidth = dataSize; desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; desc.Usage = D3D11_USAGE_DYNAMIC; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; Check(D3D::GetDevice()->CreateBuffer(&desc, NULL, &buffer)); } ConstantBuffer::~ConstantBuffer() { SafeRelease(buffer); } void ConstantBuffer::Render() { D3D11_MAPPED_SUBRESOURCE subResource; D3D::GetDC()->Map(buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &subResource); { memcpy(subResource.pData, data, dataSize); } D3D::GetDC()->Unmap(buffer, 0); } CsResource::CsResource() { } CsResource::~CsResource() { SafeRelease(input); SafeRelease(srv); SafeRelease(output); SafeRelease(uav); SafeRelease(result); } void CsResource::CreateBuffer() { CreateInput(); CreateSRV(); CreateOutput(); CreateUAV(); CreateResult(); } RawBuffer::RawBuffer(void * inputData, UINT inputByte, UINT outputByte) : CsResource() , inputData(inputData), inputByte(inputByte), outputByte(outputByte) { CreateBuffer(); } RawBuffer::~RawBuffer() { } void RawBuffer::CreateInput() { if (inputByte < 1) return; ID3D11Buffer* buffer = NULL; D3D11_BUFFER_DESC desc; ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC)); desc.ByteWidth = inputByte; desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; desc.Usage = D3D11_USAGE_DYNAMIC; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; D3D11_SUBRESOURCE_DATA subResource = { 0 }; subResource.pSysMem = inputData; Check(D3D::GetDevice()->CreateBuffer(&desc, inputData != NULL ? &subResource : NULL, &buffer)); input = (ID3D11Resource *)buffer; } void RawBuffer::CreateSRV() { if (inputByte < 1) return; ID3D11Buffer* buffer = (ID3D11Buffer *)input; D3D11_BUFFER_DESC desc; buffer->GetDesc(&desc); D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC)); srvDesc.Format = DXGI_FORMAT_R32_TYPELESS; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX; srvDesc.BufferEx.Flags = D3D11_BUFFEREX_SRV_FLAG_RAW; srvDesc.BufferEx.NumElements = desc.ByteWidth / 4; Check(D3D::GetDevice()->CreateShaderResourceView(buffer, &srvDesc, &srv)); } void RawBuffer::CreateOutput() { ID3D11Buffer* buffer = NULL; D3D11_BUFFER_DESC desc; ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC)); desc.ByteWidth = outputByte; desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; Check(D3D::GetDevice()->CreateBuffer(&desc, NULL, &buffer)); output = (ID3D11Resource *)buffer; } void RawBuffer::CreateUAV() { ID3D11Buffer* buffer = (ID3D11Buffer *)output; D3D11_BUFFER_DESC desc; buffer->GetDesc(&desc); D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; ZeroMemory(&uavDesc, sizeof(D3D11_UNORDERED_ACCESS_VIEW_DESC)); uavDesc.Format = DXGI_FORMAT_R32_TYPELESS; uavDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; uavDesc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW; uavDesc.Buffer.NumElements = desc.ByteWidth / 4; Check(D3D::GetDevice()->CreateUnorderedAccessView(buffer, &uavDesc, &uav)); } void RawBuffer::CreateResult() { ID3D11Buffer* buffer; D3D11_BUFFER_DESC desc; ((ID3D11Buffer *)output)->GetDesc(&desc); desc.Usage = D3D11_USAGE_STAGING; desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; desc.BindFlags = D3D11_USAGE_DEFAULT; desc.MiscFlags = 0; Check(D3D::GetDevice()->CreateBuffer(&desc, NULL, &buffer)); result = (ID3D11Resource *)buffer; } void RawBuffer::CopyToInput(void * data) { D3D11_MAPPED_SUBRESOURCE subResource; D3D::GetDC()->Map(input, 0, D3D11_MAP_WRITE_DISCARD, 0, &subResource); { memcpy(subResource.pData, data, inputByte); } D3D::GetDC()->Unmap(input, 0); } void RawBuffer::CopyFromOuput(void * data) { D3D::GetDC()->CopyResource(result, output); D3D11_MAPPED_SUBRESOURCE subResource; D3D::GetDC()->Map(result, 0, D3D11_MAP_READ, 0, &subResource); { memcpy(data, subResource.pData, outputByte); } D3D::GetDC()->Unmap(result, 0); } StructuredBuffer::StructuredBuffer(void* inputData, UINT inputStride, UINT inputCount, UINT outputStride, UINT outputCount) : CsResource() , inputData(inputData) , inputStride(inputStride), inputCount(inputCount) , outputStride(outputStride), outputCount(outputCount) { if (outputStride == 0 || outputCount == 0) { this->outputStride = inputStride; this->outputCount = inputCount; } CreateBuffer(); } StructuredBuffer::~StructuredBuffer() { } void StructuredBuffer::CreateInput() { ID3D11Buffer* buffer = NULL; D3D11_BUFFER_DESC desc; ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC)); desc.ByteWidth = InputByteWidth(); desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; desc.StructureByteStride = inputStride; desc.Usage = D3D11_USAGE_DYNAMIC; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; D3D11_SUBRESOURCE_DATA subResource = { 0 }; subResource.pSysMem = inputData; Check(D3D::GetDevice()->CreateBuffer(&desc, inputData != NULL ? &subResource : NULL, &buffer)); input = (ID3D11Resource *)buffer; } void StructuredBuffer::CreateSRV() { ID3D11Buffer* buffer = (ID3D11Buffer *)input; D3D11_BUFFER_DESC desc; buffer->GetDesc(&desc); D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC)); srvDesc.Format = DXGI_FORMAT_UNKNOWN; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX; srvDesc.BufferEx.NumElements = inputCount; Check(D3D::GetDevice()->CreateShaderResourceView(buffer, &srvDesc, &srv)); } void StructuredBuffer::CreateOutput() { ID3D11Buffer* buffer = NULL; D3D11_BUFFER_DESC desc; ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC)); desc.ByteWidth = OutputByteWidth(); desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; desc.StructureByteStride = outputStride; Check(D3D::GetDevice()->CreateBuffer(&desc, NULL, &buffer)); output = (ID3D11Resource *)buffer; } void StructuredBuffer::CreateUAV() { ID3D11Buffer* buffer = (ID3D11Buffer *)output; D3D11_BUFFER_DESC desc; buffer->GetDesc(&desc); D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; ZeroMemory(&uavDesc, sizeof(D3D11_UNORDERED_ACCESS_VIEW_DESC)); uavDesc.Format = DXGI_FORMAT_UNKNOWN; uavDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; uavDesc.Buffer.NumElements = outputCount; Check(D3D::GetDevice()->CreateUnorderedAccessView(buffer, &uavDesc, &uav)); } void StructuredBuffer::CreateResult() { ID3D11Buffer* buffer; D3D11_BUFFER_DESC desc; ((ID3D11Buffer *)output)->GetDesc(&desc); desc.Usage = D3D11_USAGE_STAGING; desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; desc.BindFlags = 0; desc.MiscFlags = 0; Check(D3D::GetDevice()->CreateBuffer(&desc, NULL, &buffer)); result = (ID3D11Resource *)buffer; } void StructuredBuffer::CopyToInput(void * data) { D3D11_MAPPED_SUBRESOURCE subResource; D3D::GetDC()->Map(input, 0, D3D11_MAP_WRITE_DISCARD, 0, &subResource); { memcpy(subResource.pData, data, InputByteWidth()); } D3D::GetDC()->Unmap(input, 0); } void StructuredBuffer::CopyFromOutput(void * data) { D3D::GetDC()->CopyResource(result, output); D3D11_MAPPED_SUBRESOURCE subResource; D3D::GetDC()->Map(result, 0, D3D11_MAP_READ, 0, &subResource); { memcpy(data, subResource.pData, OutputByteWidth()); } D3D::GetDC()->Unmap(result, 0); } TextureBuffer::TextureBuffer(ID3D11Texture2D * src) { D3D11_TEXTURE2D_DESC srcDesc; src->GetDesc(&srcDesc); width = srcDesc.Width; height = srcDesc.Height; arraySize = srcDesc.ArraySize; format = srcDesc.Format; D3D11_TEXTURE2D_DESC desc; ZeroMemory(&desc, sizeof(D3D11_TEXTURE2D_DESC)); desc.Width = width; desc.Height = height; desc.ArraySize = arraySize; desc.Format = format; desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; desc.MipLevels = 1; desc.SampleDesc.Count = 1; ID3D11Texture2D* texture = NULL; Check(D3D::GetDevice()->CreateTexture2D(&desc, NULL, &texture)); D3D::GetDC()->CopyResource(texture, src); input = (ID3D11Resource *)texture; CreateBuffer(); } TextureBuffer::~TextureBuffer() { } void TextureBuffer::CreateSRV() { ID3D11Texture2D* texture = (ID3D11Texture2D *)input; D3D11_TEXTURE2D_DESC desc; texture->GetDesc(&desc); D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC)); srvDesc.Format = desc.Format; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; srvDesc.Texture2DArray.MipLevels = 1; srvDesc.Texture2DArray.ArraySize = arraySize; Check(D3D::GetDevice()->CreateShaderResourceView(texture, &srvDesc, &srv)); } void TextureBuffer::CreateOutput() { ID3D11Texture2D* texture = NULL; D3D11_TEXTURE2D_DESC desc; ZeroMemory(&desc, sizeof(D3D11_TEXTURE2D_DESC)); desc.Width = width; desc.Height = height; desc.ArraySize = arraySize; desc.Format = format; desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE; desc.MipLevels = 1; desc.SampleDesc.Count = 1; Check(D3D::GetDevice()->CreateTexture2D(&desc, NULL, &texture)); output = (ID3D11Resource *)texture; D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC)); srvDesc.Format = desc.Format; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; srvDesc.Texture2DArray.MipLevels = 1; srvDesc.Texture2DArray.ArraySize = arraySize; Check(D3D::GetDevice()->CreateShaderResourceView(texture, &srvDesc, &outputSRV)); } void TextureBuffer::CreateUAV() { ID3D11Texture2D* texture = (ID3D11Texture2D*)output; D3D11_TEXTURE2D_DESC desc; texture->GetDesc(&desc); D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; ZeroMemory(&uavDesc, sizeof(D3D11_UNORDERED_ACCESS_VIEW_DESC)); uavDesc.Format = DXGI_FORMAT_UNKNOWN; uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY; uavDesc.Texture2DArray.ArraySize = arraySize; Check(D3D::GetDevice()->CreateUnorderedAccessView(texture, &uavDesc, &uav)); } void TextureBuffer::CreateResult() { ID3D11Texture2D* texture; D3D11_TEXTURE2D_DESC desc; ((ID3D11Texture2D *)output)->GetDesc(&desc); desc.Usage = D3D11_USAGE_STAGING; desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; desc.BindFlags = 0; desc.MiscFlags = 0; Check(D3D::GetDevice()->CreateTexture2D(&desc, NULL, &texture)); result = (ID3D11Resource *)texture; } void TextureBuffer::CopyToInput(ID3D11Texture2D * texture) { D3D::GetDC()->CopyResource(input, texture); } ID3D11Texture2D * TextureBuffer::CopyFromOutput() { D3D::GetDC()->CopyResource(result, output); return (ID3D11Texture2D *)result; }
GetMultiBoneDemo
GetMultiBoneDemo.h
#pragma once #include "Systems/IExecute.h" class GetMultiBoneDemo : public IExecute { public: virtual void Initialize() override; virtual void Ready() override {} virtual void Destroy() override {} virtual void Update() override; virtual void PreRender() override {} virtual void Render() override; virtual void PostRender() override {} virtual void ResizeScreen() override {} private: void Mesh(); void Airplane(); void Kachujin(); void KachujinCollider(); void KachujinWeapon(); void Pass(UINT mesh, UINT model, UINT anim); private: Shader* shader; CubeSky* sky; Material* floor; Material* stone; Material* brick; Material* wall; MeshRender* cube; MeshRender* cylinder; MeshRender* sphere; MeshRender* grid; ModelRender* airplane = NULL; ModelAnimator* kachujin = NULL; Transform* colliderInitTransforms; //무기에 대한 Transform ColliderObject** colliders; ModelRender* weapon = NULL; Transform* weaponInitTransform; vector<MeshRender *> meshes; vector<ModelRender *> models; vector<ModelAnimator *> animators; };
GetMultiBoneDemo.cpp
#include "stdafx.h" #include "GetMultiBoneDemo.h" void GetMultiBoneDemo::Initialize() { Context::Get()->GetCamera()->RotationDegree(20, 0, 0); Context::Get()->GetCamera()->Position(1, 36, -85); shader = new Shader(L"55_Render.fx"); sky = new CubeSky(L"Environment/GrassCube1024.dds"); Mesh(); Airplane(); Kachujin(); KachujinCollider(); KachujinWeapon(); } void GetMultiBoneDemo::Update() { //Weapon { Vector3 position; weaponInitTransform->Position(&position); ImGui::SliderFloat3("Weapon Position", position, -20, 20); Vector3 scale; weaponInitTransform->Scale(&scale); ImGui::SliderFloat3("Weapon Scale", scale, 0.1f, 3.0f); Vector3 rotation; weaponInitTransform->Rotation(&rotation); ImGui::SliderFloat3("Weapon Rotation", rotation, -1.0f, 1.0f); weaponInitTransform->Position(position); weaponInitTransform->Scale(scale); weaponInitTransform->Rotation(rotation); } //Collider { Vector3 position; colliderInitTransforms->Position(&position); ImGui::SliderFloat3("Collider Position", position, -20, 20); Vector3 scale; colliderInitTransforms->Scale(&scale); ImGui::SliderFloat3("Collider Scale", scale, 10.0f, 100.0f); Vector3 rotation; colliderInitTransforms->Rotation(&rotation); ImGui::SliderFloat3("Collider Rotation", rotation, -1.0f, 1.0f); colliderInitTransforms->Position(position); colliderInitTransforms->Scale(scale); colliderInitTransforms->Rotation(rotation); } sky->Update(); cube->Update(); grid->Update(); cylinder->Update(); sphere->Update(); airplane->Update(); kachujin->Update(); Matrix worlds[MAX_MODEL_TRANSFORMS]; for (UINT i = 0; i < kachujin->GetTransformCount(); i++) { kachujin->GetAttachTransform(i, worlds); colliders[i]->Collider->GetTransform()->World(worlds[40]); colliders[i]->Collider->Update(); //만들어둔 기준(weaponInitTransform->World())에서 이동한 만큼(worlds[40]) 곱해준다. weapon->GetTransform(i)->World(weaponInitTransform->World() * worlds[40]); } weapon->UpdateTransforms(); weapon->Update(); } void GetMultiBoneDemo::Render() { sky->Render(); Pass(0, 1, 2); wall->Render(); sphere->Render(); brick->Render(); cylinder->Render(); stone->Render(); cube->Render(); floor->Render(); grid->Render(); airplane->Render(); kachujin->Render(); weapon->Render(); for (UINT i = 0; i < kachujin->GetTransformCount(); i++) colliders[i]->Collider->Render(); } void GetMultiBoneDemo::Mesh() { //Create Material { floor = new Material(shader); floor->DiffuseMap("Floor.png"); //floor->SpecularMap("Floor_Specular.png"); //floor->NormalMap("Floor_Normal.png"); //floor->Specular(1, 1, 1, 20); stone = new Material(shader); stone->DiffuseMap("Stones.png"); //stone->SpecularMap("Stones_Specular.png"); //stone->NormalMap("Stones_Normal.png"); //stone->Specular(1, 1, 1, 20); brick = new Material(shader); brick->DiffuseMap("Bricks.png"); //brick->SpecularMap("Bricks_Specular.png"); //brick->NormalMap("Bricks_Normal.png"); //brick->Specular(1, 0.3f, 0.3f, 20); wall = new Material(shader); wall->DiffuseMap("Wall.png"); //wall->SpecularMap("Wall_Specular.png"); //wall->NormalMap("Wall_Normal.png"); //wall->Specular(1, 1, 1, 20); } //Create Mesh { Transform* transform = NULL; cube = new MeshRender(shader, new MeshCube()); transform = cube->AddTransform(); transform->Position(0, 5, 0); transform->Scale(20, 10, 20); grid = new MeshRender(shader, new MeshGrid(5, 5)); transform = grid->AddTransform(); transform->Position(0, 0, 0); transform->Scale(12, 1, 12); cylinder = new MeshRender(shader, new MeshCylinder(0.5f, 3.0f, 20, 20)); sphere = new MeshRender(shader, new MeshSphere(0.5f, 20, 20)); for (UINT i = 0; i < 5; i++) { transform = cylinder->AddTransform(); transform->Position(-30, 6, -15.0f + (float)i * 15.0f); transform->Scale(5, 5, 5); transform = cylinder->AddTransform(); transform->Position(30, 6, -15.0f + (float)i * 15.0f); transform->Scale(5, 5, 5); transform = sphere->AddTransform(); transform->Position(-30, 15.5f, -15.0f + (float)i * 15.0f); transform->Scale(5, 5, 5); transform = sphere->AddTransform(); transform->Position(30, 15.5f, -15.0f + (float)i * 15.0f); transform->Scale(5, 5, 5); } } sphere->UpdateTransforms(); cylinder->UpdateTransforms(); cube->UpdateTransforms(); grid->UpdateTransforms(); meshes.push_back(sphere); meshes.push_back(cylinder); meshes.push_back(cube); meshes.push_back(grid); } void GetMultiBoneDemo::Airplane() { airplane = new ModelRender(shader); airplane->ReadMesh(L"B787/Airplane"); airplane->ReadMaterial(L"B787/Airplane"); Transform* transform = airplane->AddTransform(); transform->Position(2.0f, 9.91f, 2.0f); transform->Scale(0.004f, 0.004f, 0.004f); airplane->UpdateTransforms(); models.push_back(airplane); } void GetMultiBoneDemo::Kachujin() { kachujin = new ModelAnimator(shader); kachujin->ReadMesh(L"Kachujin/Mesh"); kachujin->ReadMaterial(L"Kachujin/Mesh"); kachujin->ReadClip(L"Kachujin/Sword And Shield Idle"); kachujin->ReadClip(L"Kachujin/Sword And Shield Walk"); kachujin->ReadClip(L"Kachujin/Sword And Shield Run"); kachujin->ReadClip(L"Kachujin/Sword And Shield Slash"); kachujin->ReadClip(L"Kachujin/Salsa Dancing"); Transform* transform = NULL; transform = kachujin->AddTransform(); transform->Position(0, 0, -30); transform->Scale(0.075f, 0.075f, 0.075f); kachujin->PlayTweenMode(0, 0, 1.0f); transform = kachujin->AddTransform(); transform->Position(-15, 0, -30); transform->Scale(0.075f, 0.075f, 0.075f); kachujin->PlayTweenMode(1, 1, 1.0f); transform = kachujin->AddTransform(); transform->Position(-30, 0, -30); transform->Scale(0.075f, 0.075f, 0.075f); kachujin->PlayTweenMode(2, 2, 0.75f); transform = kachujin->AddTransform(); transform->Position(15, 0, -30); transform->Scale(0.075f, 0.075f, 0.075f); kachujin->PlayBlendMode(3, 0, 1, 2); kachujin->SetBlendAlpha(3, 1.5f); transform = kachujin->AddTransform(); transform->Position(30, 0, -32.5f); transform->Scale(0.075f, 0.075f, 0.075f); kachujin->PlayTweenMode(4, 4, 0.75f); kachujin->UpdateTransforms(); animators.push_back(kachujin); } void GetMultiBoneDemo::KachujinCollider() { UINT count = kachujin->GetTransformCount(); colliders = new ColliderObject*[count]; colliderInitTransforms = new Transform(); colliderInitTransforms->Position(-2.9f, 1.45f, -50.0f); colliderInitTransforms->Scale(5, 5, 75); for (UINT i = 0; i < count; i++) { colliders[i] = new ColliderObject(); //colliders[i]->Init = new Transform(); //colliders[i]->Init->Position(0, 0, 0); //colliders[i]->Init->Scale(10, 30, 10); colliders[i]->Transform = new Transform(); //colliders[i]->Collider = new Collider(colliders[i]->Transform, colliders[i]->Init); colliders[i]->Collider = new Collider(colliders[i]->Transform, colliderInitTransforms); } } void GetMultiBoneDemo::KachujinWeapon() { weapon = new ModelRender(shader); weapon->ReadMesh(L"Weapon/Sword"); weapon->ReadMaterial(L"Weapon/Sword"); UINT count = kachujin->GetTransformCount(); for (UINT i = 0; i < count; i++) weapon->AddTransform(); weapon->UpdateTransforms(); models.push_back(weapon); weaponInitTransform = new Transform(); weaponInitTransform->Position(-2.9f, 1.45f, -6.45f); weaponInitTransform->Scale(0.5f, 0.5f, 0.75f); weaponInitTransform->Rotation(0, 0, 1); } void GetMultiBoneDemo::Pass(UINT mesh, UINT model, UINT anim) { for (MeshRender* temp : meshes) temp->Pass(mesh); for (ModelRender* temp : models) temp->Pass(model); for (ModelAnimator* temp : animators) temp->Pass(anim); }
무기에 Collider를 붙여주었다.
실행화면

'⭐ DirectX > DirectX11 3D' 카테고리의 다른 글
[DirectX11] 075~77 Lighting, HLSL (0) | 2023.03.18 |
---|---|
[DirectX11] 074 Instancing (0) | 2023.03.18 |
[DirectX11] 070 OBB(Oriented Bounding Box) collision (4) | 2023.03.14 |
[DirectX11] 069 Collider (0) | 2023.03.13 |
[DirectX11] 068 Unprojection - 2D 좌표를 3D 좌표로 변환 (0) | 2023.03.13 |
댓글
이 글 공유하기
다른 글
-
[DirectX11] 075~77 Lighting, HLSL
[DirectX11] 075~77 Lighting, HLSL
2023.03.18 -
[DirectX11] 074 Instancing
[DirectX11] 074 Instancing
2023.03.18 -
[DirectX11] 070 OBB(Oriented Bounding Box) collision
[DirectX11] 070 OBB(Oriented Bounding Box) collision
2023.03.14 -
[DirectX11] 069 Collider
[DirectX11] 069 Collider
2023.03.13
댓글을 사용할 수 없습니다.