[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글의 요약 설명 부분. 150자를 적어주세요. 글의 요약 설명 부분. 150자를 적어주세요. 글의 요약 설명 부분. 150자를 적어주세요. 글의 요약 설명 부분. 150자를 적어주세요. 글의 요약 설명 부분. 150자를 적어주세요. 글의 요약 설명 부분. 150자입니다 목차 Collider Shader Framework Objects Collider.h .cpp UnitTest Objects ObbRaycastDemo.h .cpp 생성 Main.h .cpp Collider Collider.h 더보기 #pragma once struct Ray { Ray() : Position(0, 0, 0), Direction(0, 0, 0) { } Ray(Vector3& position, Vector3& directio…
댓글을 사용할 수 없습니다.