Adventure of 빠타박스
article thumbnail
Published 2021. 12. 10. 01:00
[C++] DirectX Animation_Test 카테고리 없음
728x90
728x90
SMALL

ImGui 활용한 DirectX 11 3D를 이용한 2D를 만드는 내용입니다.
본 내용은 똑같이 사용할 수 없음을 알립니다. (참고 및 공부자료로 만들어진 내용임을 밝힙니다.)
전 과정에 대해 이해를 해야 다음 이 부분에 대한 이해를 할 수 있음을 밝힙니다

이전 자료) https://ppatabox.tistory.com/63

 



21.12.07~

 


Rect.hlsl 복사후 Line.hlsl 만들기 (빌드에서 제외 시키기 (속성-> 빌드에서 제외(예))

Line.은 NDC공간 사용했음 

 

이미지 _Textures / MetalSlug / Player.png 로 저장

사용될 이미지 파일

 

 

237-2372791_google-search-2d-game-art-video-game-art.png
0.08MB

 

045_UvCutting_last.zip
0.02MB

 

 

 

 

 

 

현재 코드와 함께 텍스쳐 2D이미지의 관리 및 객체를 받는 과정에 대해 이해하기 바란다.

코드를 분석해보고 지금까지 건너 왔던 것들을 확인해보자 

 

월드를 지정하여 캐릭터 애니메이션을 띄워 보았다. 

아래  메탈슬러그 캐릭터가 움직이는 모습을 볼 수 있다. 

각 프레임당 움직일 값을 주었고

png파일을 Player.cpp에서 각각 위치한 것을 포토샵으로 정점위치와 값을 입력해서 떼어준 값이다. Uv 부분이 잘못되면 값이 튀틀리니 주의 하자

 

 

 

 

 

 

 

 

 

 

Texture.h

더보기
#pragma once

class Texture
{
public:
	struct Vertex
	{
		Vector3 Position;
		Vector2 Uv;
		Color4 Color;
	};

public:
	static Texture* Make
	(
		wstring fileName,
		Vector2 cutStart = Vector2(0, 0),
		Vector2 cutSize = Vector2(0, 0),
		Color4 color = Color4(1, 1, 1, 1)
	);

private:
	static map<wstring, ID3D11ShaderResourceView*> textureMap;
	static vector<Texture *> textures;

public:
	Texture(ID3D11ShaderResourceView* srv, Vector2 cutStart, Vector2 cutEnd, Color4 color);
	~Texture();

	ID3D11ShaderResourceView* GetSrv() { return srv; }

	void Render();

private:
	void CreateBuffer();

private:
	ID3D11ShaderResourceView* srv;
	VertexBuffer* vertexBuffer;
	Shader* shader;

	Vector2 textureSize;

	Vector2 cutStart;
	Vector2 cutEnd;

	Vector2 uvStart;
	Vector2 uvEnd;
	
	Color4 color;
};

 

Texture.cpp

더보기
#include "stdafx.h"
#include "Texture.h"

map<wstring, ID3D11ShaderResourceView*> Texture::textureMap;
vector<Texture *> Texture::textures;

Texture * Texture::Make(wstring fileName, Vector2 cutStart, Vector2 cutSize, Color4 color)
{
	HRESULT hr;
	ID3D11ShaderResourceView* srv;
	if (textureMap.count(fileName) < 1)
	{
		wstring fullPath = L"../_Textures/" + fileName;

		D3DX11CreateShaderResourceViewFromFile
		(
			Device,
			fullPath.c_str(),
			NULL,
			NULL,
			&srv,
			&hr
		);
		assert(SUCCEEDED(hr));
		
		textureMap.insert(pair<wstring, ID3D11ShaderResourceView*>(fileName, srv));
	}

	srv = textureMap[fileName];

	Vector2 cutEnd;
	cutEnd.x = cutStart.x + cutSize.x;
	cutEnd.y = cutStart.y + cutSize.y;

	Texture* texture = new Texture(srv, cutStart, cutEnd, color);
	textures.push_back(texture);


	return texture;
}


Texture::Texture(ID3D11ShaderResourceView * srv, Vector2 cutStart, Vector2 cutEnd, Color4 color)
	: srv(srv), color(color)
{
	shader = new Shader(L"Texture.hlsl");

	D3D11_INPUT_ELEMENT_DESC layoutDesc[] =
	{
		"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0,
		"UV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0,
		"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 20, D3D11_INPUT_PER_VERTEX_DATA, 0,
	};
	shader->CreateInputLayout(layoutDesc, ARRAYSIZE(layoutDesc));



	ID3D11Texture2D* texture;
	srv->GetResource((ID3D11Resource **)&texture);

	D3D11_TEXTURE2D_DESC textureDesc;
	texture->GetDesc(&textureDesc);

	
	textureSize = Vector2((float)textureDesc.Width, (float)textureDesc.Height);


	uvStart.x = (cutStart.x > 0) ? cutStart.x / textureSize.x : 0;
	uvStart.y = (cutStart.y > 0) ? cutStart.y / textureSize.y : 0;
	uvEnd.x = (cutEnd.x > 0) ? cutEnd.x / textureSize.x : 1;
	uvEnd.y = (cutEnd.y > 0) ? cutEnd.y / textureSize.y : 1;

	this->cutStart = cutStart;
	this->cutEnd.x = (cutEnd.x < 1) ? textureSize.x : cutEnd.x;
	this->cutEnd.y = (cutEnd.y < 1) ? textureSize.y : cutEnd.y;

	CreateBuffer();
}

void Texture::CreateBuffer()
{

	Vertex* vertices = new Vertex[6];

	Vector2 start = uvStart;
	Vector2 end = uvEnd;

	vertices[0].Position = Vector3(-0.5f, -0.5f, 0.0f);
	vertices[1].Position = Vector3(-0.5f, +0.5f, 0.0f);
	vertices[2].Position = Vector3(+0.5f, -0.5f, 0.0f);
	vertices[3].Position = Vector3(+0.5f, -0.5f, 0.0f);
	vertices[4].Position = Vector3(-0.5f, +0.5f, 0.0f);
	vertices[5].Position = Vector3(+0.5f, +0.5f, 0.0f);

	vertices[0].Uv = Vector2(start.x, end.y); //Uv쪽 설정 필기참조
	vertices[1].Uv = Vector2(start.x, start.y);
	vertices[2].Uv = Vector2(end.x, end.y);
	vertices[3].Uv = Vector2(end.x, end.y);
	vertices[4].Uv = Vector2(start.x, start.y);
	vertices[5].Uv = Vector2(end.x, start.y);

	vertices[0].Color = color;
	vertices[1].Color = color;
	vertices[2].Color = color;
	vertices[3].Color = color;
	vertices[4].Color = color;
	vertices[5].Color = color;


	vertexBuffer = new VertexBuffer(vertices, 6, sizeof(Vertex));
	SAFE_DELETE_ARRAY(vertices);
}

Texture::~Texture()
{
	SAFE_RELEASE(srv);
}

void Texture::Render()
{
	shader->Render();
	vertexBuffer->Render();
	

	DeviceContext->PSSetShaderResources(0, 1, &srv);
	DeviceContext->Draw(6, 0);
}

 

Animation.h

더보기
#pragma once

struct FAnimation
{
	Texture* texture;
	float time;

	FAnimation()
	{
		texture = NULL;
		time = 0.25f;
	}

	FAnimation(Texture* texture, float time = 0.25f)
	{
		this->texture = texture;
		this->time = time;
	}
};

class Animation
{
public:
	Animation();
	~Animation();

	UINT GetPlayFromIndex() { return playFrameIndex; }
	ID3D11ShaderResourceView* GetCurrentSrv() { return frames[playFrameIndex].texture->GetSrv(); }

	void Initialize(vector<FAnimation> animations);
	
	void Play(UINT frame = 0);
	void Pause();
	void Stop();

	void Update();
	void Render();

private:
	vector<FAnimation> frames;

private:
	bool bPlaying = false;
	UINT playFrameIndex = 0;
	float playTime = 0.0f;
};

Animation.cpp

더보기
#include "stdafx.h"
#include "Animation.h"

Animation::Animation()
{

}

Animation::~Animation()
{
	for (FAnimation& frame : frames)
		SAFE_DELETE(frame.texture);
}

void Animation::Initialize(vector<FAnimation> animations)
{
	frames = animations;
}

void Animation::Play(UINT frame)
{
	bPlaying = true;

	playFrameIndex = frame;
	playTime = Time->Running();
}

void Animation::Pause()
{
	bPlaying = false;
}

void Animation::Stop()
{
	bPlaying = false;
	playFrameIndex = 0;
}

void Animation::Update()
{
	FAnimation& frame = frames[playFrameIndex];

	if (Time->Running() - playTime >= frame.time)
	{
		playFrameIndex++;

		if (playFrameIndex >= frames.size())
			playFrameIndex = 0;

		playTime = Time->Running();
	}
}

void Animation::Render()
{
	frames[playFrameIndex].texture->Render();
}

쉐이더 부분 

Texture.hlsl

더보기
struct VertexInput
{
    float4 Position : POSITION0;
    float2 Uv : UV0;
    float4 Color : Color0;
};

struct PixelInput
{
    float4 Position : SV_POSITION;
    float2 Uv : UV0;
    float4 Color : Color0;
};

cbuffer VS_Vp : register(b0)
{
    matrix View;
    matrix Projection;
}

cbuffer VS_World : register(b1)
{
    matrix World;
}

PixelInput VS(VertexInput input)
{
    PixelInput output;
    
    output.Position = mul(input.Position, World);
    output.Position = mul(output.Position, View);
    output.Position = mul(output.Position, Projection);
    output.Uv = input.Uv;
    output.Color = input.Color;

    return output;
}

SamplerState Sampler : register(s0);
Texture2D Texture : register(t0);

float4 PS(PixelInput input) : SV_TARGET
{
    return Texture.Sample(Sampler, input.Uv) * input.Color;
}

Line.hlsl

더보기
struct VertexInput
{
    float4 Position : POSITION0;
    float4 Color : COLOR0;
};

struct PixelInput
{
    float4 Position : SV_POSITION;
    float4 Color : COLOR0;
};


PixelInput VS(VertexInput input)
{
    PixelInput output;
    output.Position = input.Position;
    output.Color = input.Color;

    return output;
}

float4 PS(PixelInput input) : SV_TARGET
{
    return input.Color;
}

 

Player.h/.cpp

더보기
#pragma once

class Player
{
public:
	Player();
	~Player();

	void Update();
	void Render();

private:

	World* world;
	SamplerState* samplerState;

	Animation* animation;
};

 

#include "stdafx.h"
#include "Player.h"

Player::Player()
{
	

	world = new World();
	world->Position(200, 100);
	world->Scale(50, 50);
	
	animation = new Animation();
    
	//해당 애니메이션을 불러들임  
	vector<FAnimation> frames;
	frames.push_back(FAnimation(Texture::Make(L"MetalSlug/Player.png", Vector2(3, 2), Vector2(30, 38))));
	frames.push_back(FAnimation(Texture::Make(L"MetalSlug/Player.png", Vector2(34, 2), Vector2(30, 38))));
	frames.push_back(FAnimation(Texture::Make(L"MetalSlug/Player.png", Vector2(64, 2), Vector2(30, 38))));
	animation->Initialize(frames);

	samplerState = new SamplerState();
}

Player::~Player()
{

	SAFE_DELETE(world);
	SAFE_DELETE(animation);
	SAFE_DELETE(samplerState);
}

void Player::Update()
{
	animation->Update();
}

void Player::Render()
{

	samplerState->Render();
	world->Render();
	animation->Render();
}

 

 

Device.cpp/Running 부분

더보기
WPARAM Running()
{
	MSG msg;
	ZeroMemory(&msg, sizeof(MSG));

	srand((UINT)time(NULL));


	Key = new Keyboard();
	Time = new Timer();

	InitImGui();
	InitScene();


	struct VpDesc
	{
		Matrix View;
		Matrix Projection;
	} vpDesc;

	D3DXVECTOR3 eye(0, 0, -1);
	D3DXVECTOR3 lookAt(0, 0, 0);
	D3DXVECTOR3 up(0, 1, 0);

	D3DXMatrixLookAtLH(&vpDesc.View, &eye, &lookAt, &up);
	D3DXMatrixTranspose(&vpDesc.View, &vpDesc.View);

	D3DXMatrixOrthoOffCenterLH(&vpDesc.Projection, 0, (float)Width, 0, (float)Height, -1, +1);
	D3DXMatrixTranspose(&vpDesc.Projection, &vpDesc.Projection);

	VpBuffer = new ConstantBuffer(&vpDesc, sizeof(VpDesc), 0);


	while (true)
	{
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			if (msg.message == WM_QUIT)
				break;

			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else
		{
			Time->Update();

			UpdateImGui();
			Update();


			DeviceContext->ClearRenderTargetView(RTV, BgColor);

			
			VpBuffer->Render();

			Render();
			RenderImGui();

			SwapChain->Present(0, 0);
		}
	}

	DestroyScene();
	
	SAFE_DELETE(VpBuffer);
	SAFE_DELETE(Key);
	SAFE_DELETE(Time);

	ImGui_ImplDX11_Shutdown();
	ImGui_ImplWin32_Shutdown();
	ImGui::DestroyContext();

	return msg.wParam;
}

 

Main.cpp 

더보기
#include "stdafx.h"
#include "Game/Player.h"

Line* line = NULL;
Rect* rect = NULL;
Player* player = NULL;

void InitScene()
{
	line = new Line();
	
	rect = new Rect();
	rect->Position(100, 100);
	rect->Scale(50, 50);

	player = new Player();
}

void DestroyScene()
{
	SAFE_DELETE(line);
	SAFE_DELETE(rect);
	SAFE_DELETE(player);
}

void Update()
{
	rect->Update();
	player->Update();
}

void Render()
{	
	line->Add(Vector2(100, 30), Vector2(Width - 100, 30), Color4(1, 0, 0, 1));
	line->Render();

	rect->Render();
	player->Render();
}

 

 

 

 

 

수정사항이 있다면 적극 반영 및 수정하겠음 

 

 

바로 UnrealEngine으로 넘어갈 것이다. 

추후 다렉 파일연습과 수업이 있으면 올리겠음. 

기존 Animation에 대해서 분석한 것이 있다면 댓글로 알려주면 좋겠습니다. 

 

 

 

 

 


 

728x90
728x90
LIST
profile

Adventure of 빠타박스

@PPATABOX

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!