컴퓨팅 셰이더(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