컴퓨팅 셰이더(Compute Shader)는 그래픽 렌더링에 주로 사용되는 정점 및 픽셀 셰이더와 같은 다른 유형의 셰이더와 달리, Compute Shader는 더 유연하고 다용도적으로 설계되어 있다.

 

 

 


 

 

 

Animation Instancing

 

Shader
  RawBuffer.fx
GetAnimationBone.fx 
Framework
  Model
  ModeAnimator.h .cpp
  Objects
  Collider.h .cpp
  Renders
  Buffer.h .cpp
Render2D.h .cpp 
UnitTest
  DirectCompute
  RawBufferDemo.h .cpp
GetAnimationBoneDemo.h .cpp
  Instancing
  InstancingFrameworkDemo.h .cpp
  Main.h .cpp

 


fx

 

어제만든 GetAnimationBone.fx 사용


 

Instancing Framework Demo

 

InstancingFrameworkDemo.h

더보기
#pragma once
#include "Systems/IExecute.h"
class InstancingFrameworkDemo : 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 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;
vector<MeshRender *> meshes;
vector<ModelRender *> models;
vector<ModelAnimator *> animators;
};

 

 

InstancingFrameworkDemo.cpp

더보기
#include "stdafx.h"
#include "InstancingFrameworkDemo.h"
void InstancingFrameworkDemo::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();
}
void InstancingFrameworkDemo::Update()
{
sky->Update();
cube->Update();
grid->Update();
cylinder->Update();
sphere->Update();
airplane->Update();
kachujin->Update();
}
void InstancingFrameworkDemo::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();
}
void InstancingFrameworkDemo::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 InstancingFrameworkDemo::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 InstancingFrameworkDemo::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 InstancingFrameworkDemo::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);
}

 


 

Get Animation Bone Demo

 

GetAnimationBoneDemo.h

더보기
#pragma once
#include "Systems/IExecute.h"
class GetAnimationBoneDemo : 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();//Kachujin 충돌체
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;
ColliderObject** colliders; //충돌체를 몇개 쓸지 모르니 2차 포인터 사용
vector<MeshRender *> meshes;
vector<ModelRender *> models;
vector<ModelAnimator *> animators;
};

 

 

GetAnimationBoneDemo.cpp

더보기
#include "stdafx.h"
#include "GetAnimationBoneDemo.h"
void GetAnimationBoneDemo::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();
}
void GetAnimationBoneDemo::Update()
{
sky->Update();
cube->Update();
grid->Update();
cylinder->Update();
sphere->Update();
airplane->Update();
kachujin->Update();
//collider 계산
for (UINT i = 0; i < kachujin->GetTransformCount(); i++)
{
Matrix attach;
kachujin->GetAttachTransform(i, &attach);
colliders[i]->Collider->GetTransform()->World(attach);
colliders[i]->Collider->Update();
}
}
void GetAnimationBoneDemo::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();
for (UINT i = 0; i < kachujin->GetTransformCount(); i++)
colliders[i]->Collider->Render();
}
void GetAnimationBoneDemo::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 GetAnimationBoneDemo::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 GetAnimationBoneDemo::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();
kachujin->SetAttachTransform(40);//kachujin 오른손 Bone
animators.push_back(kachujin);
}
void GetAnimationBoneDemo::KachujinCollider()
{
UINT count = kachujin->GetTransformCount(); //Instancing 개수 가져옴.
colliders = new ColliderObject*[count]; //collider 할당. 2차 포인터로 생성해서 포인터 하나 들어간다.
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);
}
}
void GetAnimationBoneDemo::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);
}

 


 

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(); }//Instancing 개수 가져옴.
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 SetAttachTransform(UINT boneIndex);
void GetAttachTransform(UINT instance, Matrix* outResult);
private:
void CreateTexture();
void CreateClipTransform(UINT index);
void CreateComputeBuffer();
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;
};
struct AttachDesc
{
UINT BoneIndex = 0;
float Padding[3];
} attachDesc;
private:
Shader* computeShader;
StructuredBuffer* computeBuffer = NULL;
CS_InputDesc* csInput = NULL;
CS_OutputDesc* csOutput = NULL;
ID3DX11EffectShaderResourceVariable* sInputSRV;
ID3DX11EffectUnorderedAccessViewVariable* sOutputUAV;
ConstantBuffer* computeAttachBuffer;
ID3DX11EffectConstantBuffer* sComputeAttachBuffer;
ID3DX11EffectConstantBuffer* sComputeTweenBuffer;
ID3DX11EffectConstantBuffer* sComputeBlendBuffer;
};

 

 

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);
computeShader = new Shader(L"63_GetAnimationBone.fx");
computeAttachBuffer = new ConstantBuffer(&attachDesc, sizeof(AttachDesc));
sInputSRV = computeShader->AsSRV("Input");
sOutputUAV = computeShader->AsUAV("Output");
sComputeAttachBuffer = computeShader->AsConstantBuffer("CB_AttachBone");
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(computeBuffer);
SafeDeleteArray(csInput);
SafeDeleteArray(csOutput);
SafeDelete(computeAttachBuffer);
}
void ModelAnimator::Update()
{
if (texture == NULL)
{
for (ModelMesh* mesh : model->Meshes())
mesh->SetShader(shader);
CreateTexture();
CreateComputeBuffer();
}
for (UINT i = 0; i < transforms.size(); i++)
blendDesc[i].Mode == 0 ? UpdateTweenMode(i) : UpdateBlendMode(i);
tweenBuffer->Render();
blendBuffer->Render();
//computeBuffer 정보를 넘긴다.
if (computeBuffer != NULL)
{
computeAttachBuffer->Render();
sComputeAttachBuffer->SetConstantBuffer(computeAttachBuffer->Buffer());
sComputeTweenBuffer->SetConstantBuffer(tweenBuffer->Buffer());
sComputeBlendBuffer->SetConstantBuffer(blendBuffer->Buffer());
sInputSRV->SetResource(computeBuffer->SRV());
sOutputUAV->SetUnorderedAccessView(computeBuffer->UAV());
computeShader->Dispatch(0, 0, 1, 1, 1);
computeBuffer->CopyFromOutput(csOutput);
}
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::SetAttachTransform(UINT boneIndex)
{
attachDesc.BoneIndex = boneIndex;
}
void ModelAnimator::GetAttachTransform(UINT instance, Matrix * outResult)
{
if (csOutput == NULL)
{
D3DXMatrixIdentity(outResult);
return;
}
Matrix transform = model->BoneByIndex(attachDesc.BoneIndex)->Transform(); //기준 본 행렬
Matrix result = csOutput[instance].Result; //애니메이션 행렬
Matrix world = GetTransform(instance)->World();
*outResult = transform * result * world; //기준에서 애니메이션이 얼마나 됬는지 모델이 얼마나 움직였는지
}
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)
}
void ModelAnimator::CreateComputeBuffer()
{
UINT clipCount = model->ClipCount();
UINT inSize = clipCount * MAX_MODEL_KEYFRAMES * MAX_MODEL_TRANSFORMS;
UINT outSize = MAX_MODEL_INSTANCE;
csInput = new CS_InputDesc[inSize];
UINT count = 0;
for (UINT clipIndex = 0; clipIndex < clipCount; clipIndex++)
{
for (UINT frameIndex = 0; frameIndex < MAX_MODEL_KEYFRAMES; frameIndex++)
{
for (UINT boneIndex = 0; boneIndex < MAX_MODEL_TRANSFORMS; boneIndex++)
{
csInput[count].Bone = clipTransforms[clipIndex].Transform[frameIndex][boneIndex];
count++;
}
}//for(frameIndex)
}//for(clipIndex)
computeBuffer = new StructuredBuffer(csInput, sizeof(CS_InputDesc), inSize, sizeof(CS_OutputDesc), outSize);
csOutput = new CS_OutputDesc[outSize];
//초기값이 없어서 Identity 시켜준다.
for (UINT i = 0; i < outSize; i++)
D3DXMatrixIdentity(&csOutput[i].Result);
}
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);
}
  • computeShader
  • computeBuffer
  • csInput
  • csOutput
  • computeAttachBuffer

void CreateTexture();
void CreateClipTransform(UINT index);
void CreateComputeBuffer();

 


 

 

Collider

 

Collider.h

더보기
#pragma once
struct ColliderObject
{
class Transform* Init = NULL;
class Transform* Transform = NULL;
class Collider* Collider = NULL;
};
class Collider //충돌체
{
public:
Collider(Transform* transform, Transform* init = NULL);
~Collider();
void Update();
void Render(Color color = Color(0, 1, 0, 1)); //충돌체 녹색 설정
Transform* GetTransform() { return transform; } //transform을 리턴하는 함수
private:
Transform* init = NULL; //기준
Transform* transform; //기준에서 얼마나 움직였는지
Vector3 lines[8];
};

 

 

Collider.cpp

더보기
#include "Framework.h"
#include "Collider.h"
Collider::Collider(Transform * transform, Transform * init)
: transform(transform), init(init)
{
//육면체 //충돌작업에 0번과 7번을 사용할 것이다.
lines[0] = Vector3(-0.5f, -0.5f, -0.5f);
lines[1] = Vector3(-0.5f, +0.5f, -0.5f);
lines[2] = Vector3(+0.5f, -0.5f, -0.5f);
lines[3] = Vector3(+0.5f, +0.5f, -0.5f);
lines[4] = Vector3(-0.5f, -0.5f, +0.5f);
lines[5] = Vector3(-0.5f, +0.5f, +0.5f);
lines[6] = Vector3(+0.5f, -0.5f, +0.5f);
lines[7] = Vector3(+0.5f, +0.5f, +0.5f);
}
Collider::~Collider()
{
}
void Collider::Update()
{
}
void Collider::Render(Color color)
{
Transform temp;
temp.World(transform->World());
if (init != NULL)
temp.World(init->World() * transform->World());
Matrix world = temp.World();
Vector3 dest[8]; //선 8개 선언
for (UINT i = 0; i < 8; i++)
D3DXVec3TransformCoord(&dest[i], &lines[i], &world); //선의 위치를 그려준다.
//Front
DebugLine::Get()->RenderLine(dest[0], dest[1], color);
DebugLine::Get()->RenderLine(dest[1], dest[3], color);
DebugLine::Get()->RenderLine(dest[3], dest[2], color);
DebugLine::Get()->RenderLine(dest[2], dest[0], color);
//Backward
DebugLine::Get()->RenderLine(dest[4], dest[5], color);
DebugLine::Get()->RenderLine(dest[5], dest[7], color);
DebugLine::Get()->RenderLine(dest[7], dest[6], color);
DebugLine::Get()->RenderLine(dest[6], dest[4], color);
//Side
DebugLine::Get()->RenderLine(dest[0], dest[4], color);
DebugLine::Get()->RenderLine(dest[1], dest[5], color);
DebugLine::Get()->RenderLine(dest[2], dest[6], color);
DebugLine::Get()->RenderLine(dest[3], dest[7], color);
}

 


 

 

Get Animation Bone Demo