게임 리소스를 관리하는 Resources 클래스를 구현
- 그리고 모든 오브젝트를 묶어주는 최상위 클래스 Object 구현
enum class OBJECT_TYPE : uint8
{
NONE,
GAMEOBJECT,
COMPONENT,
MATERIAL,
MESH,
SHADER,
TEXTURE,
END
};
enum
{
OBJECT_TYPE_COUNT = static_cast<uint8>(OBJECT_TYPE::END),
};
- 모든 오브젝트를 OBJECT_TYPE으로 분류해서 Object 클래스로 묶어서 관리
class Object
{
public:
Object(OBJECT_TYPE type);
virtual ~Object();
OBJECT_TYPE GetType() { return _objectType; }
void SetName(const wstring& name) { _name = name; }
const wstring& GetName() { return _name; }
protected:
friend class Resources;
virtual void Load(const wstring& path) { }
virtual void Save(const wstring& path) { }
protected:
OBJECT_TYPE _objectType = OBJECT_TYPE::NONE;
wstring _name;
};
- Object 클래스는 모든 오브젝트의 기반 클래스로, 여기에 있는 기능들을 Resources에게 오픈함으로써
- Protected한 데이터에 접근할 수 있게 한다 (Save, Load등의 기능을 사용하기 위해서)
template<typename T>
inline shared_ptr<T> Resources::Load(const wstring& key, const wstring& path)
{
OBJECT_TYPE objectType = GetObjectType<T>();
KeyObjMap& keyObjMap = _resources[static_cast<uint8>(objectType)];
auto findIt = keyObjMap.find(key);
if (findIt != keyObjMap.end())
return static_pointer_cast<T>(findIt->second);
shared_ptr<T> object = make_shared<T>();
object->Load(path);
keyObjMap[key] = object;
return object;
}
- Resources의 Load에서 객체가 가진 Load를 불러온다
- 이전에 모작 때 했던 방식과 비슷한데 다른 점은 스마트포인터를 이용한다는 점
- 리소스를 이름으로 검색해서 있으면 그 리소스를 리턴하고, 없으면 만들어서 파일로부터 로드
- 리소스 맵에 등록하고 리턴
3D Cube 만들기
- 기존 Vertex에서 color가 빠지고 normal, tangent가 추가되었다.
struct Vertex
{
Vertex() {}
Vertex(Vec3 p, Vec2 u, Vec3 n, Vec3 t)
: pos(p), uv(u), normal(n), tangent(t)
{}
Vec3 pos;
Vec2 uv;
Vec3 normal;
Vec3 tangent;
};
- color가 빠진 이유는 color는 이제 uv 좌표로 불러올 텍스쳐에 있기 때문에 필요가 없어짐
- normal, tangent는 이후 Lighting 예제에서 사용될 변수
- Vertex 구성요소가 바뀌면서 InputLayout 양식도 바뀜
D3D12_INPUT_ELEMENT_DESC desc[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA},
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 20, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 32, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
};
- 쉐이더 코드도 바뀜
struct VS_IN
{
float3 pos : POSITION;
float2 uv : TEXCOORD;
};
struct VS_OUT
{
float4 pos : SV_Position;
float2 uv : TEXCOORD;
};
- normal과 tangent는 당장 넣지 않아도 오류가 나지 않으므로 없는걸 찾는 문제만 발생하지 않도록 조치
shared_ptr<Mesh> Resources::LoadCubeMesh()
{
shared_ptr<Mesh> findMesh = Get<Mesh>(L"Cube");
if (findMesh)
return findMesh;
float w2 = 0.5f;
float h2 = 0.5f;
float d2 = 0.5f;
vector<Vertex> vec(24);
// 앞면
vec[0] = Vertex(Vec3(-w2, -h2, -d2), Vec2(0.0f, 1.0f), Vec3(0.0f, 0.0f, -1.0f), Vec3(1.0f, 0.0f, 0.0f));
vec[1] = Vertex(Vec3(-w2, +h2, -d2), Vec2(0.0f, 0.0f), Vec3(0.0f, 0.0f, -1.0f), Vec3(1.0f, 0.0f, 0.0f));
vec[2] = Vertex(Vec3(+w2, +h2, -d2), Vec2(1.0f, 0.0f), Vec3(0.0f, 0.0f, -1.0f), Vec3(1.0f, 0.0f, 0.0f));
vec[3] = Vertex(Vec3(+w2, -h2, -d2), Vec2(1.0f, 1.0f), Vec3(0.0f, 0.0f, -1.0f), Vec3(1.0f, 0.0f, 0.0f));
// 뒷면
vec[4] = Vertex(Vec3(-w2, -h2, +d2), Vec2(1.0f, 1.0f), Vec3(0.0f, 0.0f, 1.0f), Vec3(-1.0f, 0.0f, 0.0f));
vec[5] = Vertex(Vec3(+w2, -h2, +d2), Vec2(0.0f, 1.0f), Vec3(0.0f, 0.0f, 1.0f), Vec3(-1.0f, 0.0f, 0.0f));
vec[6] = Vertex(Vec3(+w2, +h2, +d2), Vec2(0.0f, 0.0f), Vec3(0.0f, 0.0f, 1.0f), Vec3(-1.0f, 0.0f, 0.0f));
vec[7] = Vertex(Vec3(-w2, +h2, +d2), Vec2(1.0f, 0.0f), Vec3(0.0f, 0.0f, 1.0f), Vec3(-1.0f, 0.0f, 0.0f));
// 윗면
vec[8] = Vertex(Vec3(-w2, +h2, -d2), Vec2(0.0f, 1.0f), Vec3(0.0f, 1.0f, 0.0f), Vec3(1.0f, 0.0f, 0.0f));
vec[9] = Vertex(Vec3(-w2, +h2, +d2), Vec2(0.0f, 0.0f), Vec3(0.0f, 1.0f, 0.0f), Vec3(1.0f, 0.0f, 0.0f));
vec[10] = Vertex(Vec3(+w2, +h2, +d2), Vec2(1.0f, 0.0f), Vec3(0.0f, 1.0f, 0.0f), Vec3(1.0f, 0.0f, 0.0f));
vec[11] = Vertex(Vec3(+w2, +h2, -d2), Vec2(1.0f, 1.0f), Vec3(0.0f, 1.0f, 0.0f), Vec3(1.0f, 0.0f, 0.0f));
// 아랫면
vec[12] = Vertex(Vec3(-w2, -h2, -d2), Vec2(1.0f, 1.0f), Vec3(0.0f, -1.0f, 0.0f), Vec3(-1.0f, 0.0f, 0.0f));
vec[13] = Vertex(Vec3(+w2, -h2, -d2), Vec2(0.0f, 1.0f), Vec3(0.0f, -1.0f, 0.0f), Vec3(-1.0f, 0.0f, 0.0f));
vec[14] = Vertex(Vec3(+w2, -h2, +d2), Vec2(0.0f, 0.0f), Vec3(0.0f, -1.0f, 0.0f), Vec3(-1.0f, 0.0f, 0.0f));
vec[15] = Vertex(Vec3(-w2, -h2, +d2), Vec2(1.0f, 0.0f), Vec3(0.0f, -1.0f, 0.0f), Vec3(-1.0f, 0.0f, 0.0f));
// 왼쪽면
vec[16] = Vertex(Vec3(-w2, -h2, +d2), Vec2(0.0f, 1.0f), Vec3(-1.0f, 0.0f, 0.0f), Vec3(0.0f, 0.0f, -1.0f));
vec[17] = Vertex(Vec3(-w2, +h2, +d2), Vec2(0.0f, 0.0f), Vec3(-1.0f, 0.0f, 0.0f), Vec3(0.0f, 0.0f, -1.0f));
vec[18] = Vertex(Vec3(-w2, +h2, -d2), Vec2(1.0f, 0.0f), Vec3(-1.0f, 0.0f, 0.0f), Vec3(0.0f, 0.0f, -1.0f));
vec[19] = Vertex(Vec3(-w2, -h2, -d2), Vec2(1.0f, 1.0f), Vec3(-1.0f, 0.0f, 0.0f), Vec3(0.0f, 0.0f, -1.0f));
// 오른쪽면
vec[20] = Vertex(Vec3(+w2, -h2, -d2), Vec2(0.0f, 1.0f), Vec3(1.0f, 0.0f, 0.0f), Vec3(0.0f, 0.0f, 1.0f));
vec[21] = Vertex(Vec3(+w2, +h2, -d2), Vec2(0.0f, 0.0f), Vec3(1.0f, 0.0f, 0.0f), Vec3(0.0f, 0.0f, 1.0f));
vec[22] = Vertex(Vec3(+w2, +h2, +d2), Vec2(1.0f, 0.0f), Vec3(1.0f, 0.0f, 0.0f), Vec3(0.0f, 0.0f, 1.0f));
vec[23] = Vertex(Vec3(+w2, -h2, +d2), Vec2(1.0f, 1.0f), Vec3(1.0f, 0.0f, 0.0f), Vec3(0.0f, 0.0f, 1.0f));
vector<uint32> idx(36);
// 앞면
idx[0] = 0; idx[1] = 1; idx[2] = 2;
idx[3] = 0; idx[4] = 2; idx[5] = 3;
// 뒷면
idx[6] = 4; idx[7] = 5; idx[8] = 6;
idx[9] = 4; idx[10] = 6; idx[11] = 7;
// 윗면
idx[12] = 8; idx[13] = 9; idx[14] = 10;
idx[15] = 8; idx[16] = 10; idx[17] = 11;
// 아랫면
idx[18] = 12; idx[19] = 13; idx[20] = 14;
idx[21] = 12; idx[22] = 14; idx[23] = 15;
// 왼쪽면
idx[24] = 16; idx[25] = 17; idx[26] = 18;
idx[27] = 16; idx[28] = 18; idx[29] = 19;
// 오른쪽면
idx[30] = 20; idx[31] = 21; idx[32] = 22;
idx[33] = 20; idx[34] = 22; idx[35] = 23;
shared_ptr<Mesh> mesh = make_shared<Mesh>();
mesh->Init(vec, idx);
Add(L"Cube", mesh);
return mesh;
}
- 이렇게 리소스에서 큐브를 만들 수 있고,
#pragma region Cube
{
shared_ptr<GameObject> sphere = make_shared<GameObject>();
sphere->AddComponent(make_shared<Transform>());
sphere->GetTransform()->SetLocalScale(Vec3(100.f, 100.f, 100.f));
sphere->GetTransform()->SetLocalPosition(Vec3(150.f, 100.f, 200.f));
shared_ptr<MeshRenderer> meshRenderer = make_shared<MeshRenderer>();
{
shared_ptr<Mesh> sphereMesh = GET_SINGLE(Resources)->LoadCubeMesh();
meshRenderer->SetMesh(sphereMesh);
}
{
shared_ptr<Shader> shader = make_shared<Shader>();
shared_ptr<Texture> texture = make_shared<Texture>();
shader->Init(L"..\\Resources\\Shader\\default.hlsli");
texture->Init(L"..\\Resources\\Texture\\veigar.jpg");
shared_ptr<Material> material = make_shared<Material>();
material->SetShader(shader);
material->SetTexture(0, texture);
meshRenderer->SetMaterial(material);
}
sphere->AddComponent(meshRenderer);
scene->AddGameObject(sphere);
}
#pragma endregion
- 이렇게 불러와서 사용한다.
'DirectX > [Inflearn_rookiss] Part2: DirectX12' 카테고리의 다른 글
16. Lighting 구현 (0) | 2023.01.26 |
---|---|
15. Lighting 기본 개념 (0) | 2023.01.25 |
13. Translation 정리 & Camera 클래스 추가 (0) | 2023.01.24 |
12. Projection, Screen 변환 행렬 (2) | 2023.01.23 |
11. World, View 변환 행렬 (0) | 2023.01.22 |
댓글