Resources
- Resources를 통해서 그리고자 하는 물체의 정보를 저장하여 사용
- 물체의 정보를 넘겨주어 같은 물체를 대량으로 그릴 때 유용하다.
- 구와 큐브에 대한 Vertex, Index Buffer를 설정하고 Resources에 Add하여 Mesh를 입력한다.
Object.h
더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
#pragma once
enum class OBJECT_TYPE : uint8
{
NONE,
GAMEOBJECT, // PREFAB
COMPONENT,
MATERIAL,
MESH,
SHADER,
TEXTURE,
END
};
enum
{
OBJECT_TYPE_COUNT = static_cast<uint8>(OBJECT_TYPE::END)
};
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; }
// TODO : Instantiate
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;
};
|
cs |
- Object들을 관리하기 위한 class. ( GAMEOBJECT, COMPONENT, MATERIAL, MESH, SHADER, TEXTURE) 등
- Obj Type과 Name을 저장하거나 Get할 수 있으며 FriendClass인 Resources도 접근이 가능하다.
Resources.h
더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
#pragma once
#include "GameObject.h"
#include "Material.h"
#include "Mesh.h"
#include "Shader.h"
#include "Texture.h"
class Resources
{
DECLARE_SINGLE(Resources);
public:
template<typename T>
shared_ptr<T> Load(const wstring& key, const wstring& path);
template<typename T>
bool Add(const wstring& key, shared_ptr<T> object);
template<typename T>
shared_ptr<T> Get(const wstring& Key);
template<typename T>
OBJECT_TYPE GetObjectType();
shared_ptr<Mesh> LoadCubeMesh();
shared_ptr<Mesh> LoadSphereMesh();
private:
using KeyObjMap = std::map<wstring/*key*/, shared_ptr<Object>>;
array<KeyObjMap, OBJECT_TYPE_COUNT> _resources;
};
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;
}
template<typename T>
bool Resources::Add(const wstring& key, shared_ptr<T> object)
{
OBJECT_TYPE objectType = GetObjectType<T>();
KeyObjMap& keyObjMap = _resources[static_cast<uint8>(objectType)];
auto findIt = keyObjMap.find(key);
if (findIt != keyObjMap.end())
return false;
keyObjMap[key] = object;
return true;
}
template<typename T>
shared_ptr<T> Resources::Get(const wstring& key)
{
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);
return nullptr;
}
template<typename T>
inline OBJECT_TYPE Resources::GetObjectType()
{
if (std::is_same_v<T, GameObject>)
return OBJECT_TYPE::GAMEOBJECT;
else if (std::is_same_v<T, Material>)
return OBJECT_TYPE::MATERIAL;
else if (std::is_same_v<T, Mesh>)
return OBJECT_TYPE::MESH;
else if (std::is_same_v<T, Shader>)
return OBJECT_TYPE::SHADER;
else if (std::is_same_v<T, Texture>)
return OBJECT_TYPE::TEXTURE;
else if (std::is_convertible_v<T, Component>)
return OBJECT_TYPE::COMPONENT;
else
return OBJECT_TYPE::NONE;
}
|
cs |
- Singleton 으로 선언되었다.
- KeyObjMap = Key에 따른 Object를 저장하기 위한 Map
- _resources = Obj Type에 따라서 KeyObjMap을 관리하기 위한 Array
- Load() = Template를 통해 Type, 매개변수를 통해Key, 경로를 받아 오브젝트 파일을 Load해준 뒤 return 해주는 함수.
- Add() = Template를 통해 Type, 매개변수를 통해Key, object를 받아 object를
- Get() = Type Map 내에 존재하는 Obj를 찾아 반환해주는 함수.
- GetObjectType() = typename에 맞는 type을 반환해주는 함수.
Resources.Cpp
더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
|
#include "pch.h"
#include "Resources.h"
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;
}
shared_ptr<Mesh> Resources::LoadSphereMesh()
{
shared_ptr<Mesh> findMesh = Get<Mesh>(L"Sphere");
if (findMesh)
return findMesh;
float radius = 0.5f; // 구의 반지름
uint32 stackCount = 20; // 가로 분할
uint32 sliceCount = 20; // 세로 분할
vector<Vertex> vec;
Vertex v;
// 북극
v.pos = Vec3(0.0f, radius, 0.0f);
v.uv = Vec2(0.5f, 0.0f);
v.normal = v.pos;
v.normal.Normalize();
v.tangent = Vec3(1.0f, 0.0f, 1.0f);
vec.push_back(v);
float stackAngle = XM_PI / stackCount;
float sliceAngle = XM_2PI / sliceCount;
float deltaU = 1.f / static_cast<float>(sliceCount);
float deltaV = 1.f / static_cast<float>(stackCount);
// 고리마다 돌면서 정점을 계산한다 (북극/남극 단일점은 고리가 X)
for (uint32 y = 1; y <= stackCount - 1; ++y)
{
float phi = y * stackAngle;
// 고리에 위치한 정점
for (uint32 x = 0; x <= sliceCount; ++x)
{
float theta = x * sliceAngle;
v.pos.x = radius * sinf(phi) * cosf(theta);
v.pos.y = radius * cosf(phi);
v.pos.z = radius * sinf(phi) * sinf(theta);
v.uv = Vec2(deltaU * x, deltaV * y);
v.normal = v.pos;
v.normal.Normalize();
v.tangent.x = -radius * sinf(phi) * sinf(theta);
v.tangent.y = 0.0f;
v.tangent.z = radius * sinf(phi) * cosf(theta);
v.tangent.Normalize();
vec.push_back(v);
}
}
// 남극
v.pos = Vec3(0.0f, -radius, 0.0f);
v.uv = Vec2(0.5f, 1.0f);
v.normal = v.pos;
v.normal.Normalize();
v.tangent = Vec3(1.0f, 0.0f, 0.0f);
vec.push_back(v);
vector<uint32> idx(36);
// 북극 인덱스
for (uint32 i = 0; i <= sliceCount; ++i)
{
// [0]
// | \
// [i+1]-[i+2]
idx.push_back(0);
idx.push_back(i + 2);
idx.push_back(i + 1);
}
// 몸통 인덱스
uint32 ringVertexCount = sliceCount + 1;
for (uint32 y = 0; y < stackCount - 2; ++y)
{
for (uint32 x = 0; x < sliceCount; ++x)
{
// [y, x]-[y, x+1]
// | /
// [y+1, x]
idx.push_back(1 + (y) * ringVertexCount + (x));
idx.push_back(1 + (y) * ringVertexCount + (x + 1));
idx.push_back(1 + (y + 1) * ringVertexCount + (x));
// [y, x+1]
// / |
// [y+1, x]-[y+1, x+1]
idx.push_back(1 + (y + 1) * ringVertexCount + (x));
idx.push_back(1 + (y) * ringVertexCount + (x + 1));
idx.push_back(1 + (y + 1) * ringVertexCount + (x + 1));
}
}
// 남극 인덱스
uint32 bottomIndex = static_cast<uint32>(vec.size()) - 1;
uint32 lastRingStartIndex = bottomIndex - ringVertexCount;
for (uint32 i = 0; i < sliceCount; ++i)
{
// [last+i]-[last+i+1]
// | /
// [bottom]
idx.push_back(bottomIndex);
idx.push_back(lastRingStartIndex + i);
idx.push_back(lastRingStartIndex + i + 1);
}
shared_ptr<Mesh> mesh = make_shared<Mesh>();
mesh->Init(vec, idx);
Add(L"Sphere", mesh);
return mesh;
}
|
cs |
- LoadCubeMesh() = Mesh Type의 Cube가 있는지 확인한 뒤 있으면 반환하고, 없으면 Cube Vertex와 Index를 설정한 뒤 하고 Add() 해주며 mesh를 반환한다.
- LoadSphereMesh() = LoadCubeMesh()와 똑같이 동작하지만, 구체를 생성하는 알고리즘에 따라서 mesh 생성한다.
- 각 vertex를 설정할 때 pos, uv, normal, tangent를 인자로 보내주고 있는데, normal과 tangent에 관한 부분은 다음 내용인 lighting을 할 떄 사용된다.
SceneManager.Cpp
더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
#include "pch.h"
#include "SceneManager.h"
#include "Scene.h"
#include "Engine.h"
#include "Material.h"
#include "GameObject.h"
#include "MeshRenderer.h"
#include "Transform.h"
#include "Camera.h"
#include "TestCameraScript.h"
#include "Resources.h"
void SceneManager::Update()
{
if (_activeScene == nullptr)
return;
_activeScene->Update();
_activeScene->LateUpdate();
_activeScene->FinalUpdate();
}
// TEMP
void SceneManager::Render()
{
if (_activeScene == nullptr)
return;
const vector<shared_ptr<GameObject>>& gameObjects = _activeScene->GetGameObjects();
for (auto& gameObject : gameObjects)
{
if (gameObject->GetCamera() == nullptr)
continue;
gameObject->GetCamera()->Render();
}
}
void SceneManager::LoadScene(wstring sceneName)
{
// TODO : 기존 Scene 정리
// TODO : 파일에서 Scene 정보 로드
_activeScene = LoadTestScene();
_activeScene->Awake();
_activeScene->Start();
}
shared_ptr<Scene> SceneManager::LoadTestScene()
{
shared_ptr<Scene> scene = make_shared<Scene>();
#pragma region Camera
shared_ptr<GameObject> camera = make_shared<GameObject>();
camera->AddComponent(make_shared<Transform>());
camera->AddComponent(make_shared<Camera>()); // Near=1, Far=1000, FOV=45도
camera->AddComponent(make_shared<TestCameraScript>());
camera->GetTransform()->SetLocalPosition(Vec3(0.f, 100.f, 0.f));
scene->AddGameObject(camera);
#pragma endregion
#pragma region Sphere
{
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(0.f, 100.f, 200.f));
shared_ptr<MeshRenderer> meshRenderer = make_shared<MeshRenderer>();
{
shared_ptr<Mesh> sphereMesh = GET_SINGLE(Resources)->LoadSphereMesh();
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\\Manduk.png");
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
#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\\Manduk.png");
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
return scene;
}
|
cs |
- 우선 Sphere 부분을 보면 GameObject로써 생성한 뒤 mesh를 Resources를 통해 세팅한 뒤 오브젝트를 Scene에 추가해주는 모습을 확인할 수 있으며, Cube도 같은 방식으로 추가되는 것을 확인할 수 있다.
결과
SceneManager에서 Resources를 통해 생성한 구체와 육면체가 잘 생성되었음을 볼 수 있으며,
생성한 mesh에 texture 또한 잘 입혀서 출력되는 모습을 확인할 수 있아.
'Grahpics' 카테고리의 다른 글
[Graphics] DirectX12 - Lighting (0) | 2022.02.07 |
---|---|
[Graphics] DirectX12 - Lighting 개요 (0) | 2022.02.06 |
[Graphics] DirectX12 - Camera, 원근투영 (perspective) (0) | 2022.02.04 |
[Graphics] DirectX12 - Scene (0) | 2022.01.31 |
[Graphics] DirectX12 - Component (0) | 2022.01.31 |