For me
[DirectX12] 9) Scene 본문
Scene
게임 설계에 따라, 게임은 단일 씬으로 구성되거나, 여러 개의 씬으로 구성될 수 있다.
각각의 스테이지에 대응하는 여러 개의 씬으로 구성할 수 있다
SceneManager.h (싱글톤)
더보기
#pragma once
#include "EnginePch.h"
class Scene;
enum
{
MAX_LAYER = 32,
};
class SceneManager
{
DECLARE_SINGLE(SceneManager);
public:
void Update();
void Render();
void LoadScene(wstring sceneName);
void SetLayerName(uint8 index, const wstring& name);
const wstring& IndexToLayerName(uint8 index) { return _layerNames[index]; }
uint8 LayerNameToIndex(const wstring& name);
shared_ptr<class GameObject> Pick(int32 screenX, int32 screenY);
public:
shared_ptr<Scene> GetActiveScene() { return _activeScene; }
private:
shared_ptr<Scene> LoadTestScene();
private:
shared_ptr<Scene> _activeScene;
array<wstring, MAX_LAYER> _layerNames;
map<wstring, uint8> _layerIndex;
};
SceneManager.cpp
GET_SINGLE(SceneManager)->LoadScene(L"TestScene"); 을 Client에서 입력하게 되면,
LoadTestScene() 이 실행됨
더보기
#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 "Light.h"
#include "TestCameraScript.h"
#include "Resources.h"
#include "ParticleSystem.h"
#include "Terrain.h"
#include "SphereCollider.h"
#include "MeshData.h"
#include "TestDragon.h"
void SceneManager::Update()
{
if (_activeScene == nullptr)
return;
_activeScene->Update();
_activeScene->LateUpdate();
_activeScene->FinalUpdate();
}
void SceneManager::Render()
{
if (_activeScene)
_activeScene->Render();
}
void SceneManager::LoadScene(wstring sceneName)
{
// TODO : 기존 Scene 정리
// TODO : 파일에서 Scene 정보 로드
_activeScene = LoadTestScene();
_activeScene->Awake();
_activeScene->Start();
}
void SceneManager::SetLayerName(uint8 index, const wstring& name)
{
// 기존 데이터 삭제
const wstring& prevName = _layerNames[index];
_layerIndex.erase(prevName);
_layerNames[index] = name;
_layerIndex[name] = index;
}
uint8 SceneManager::LayerNameToIndex(const wstring& name)
{
auto findIt = _layerIndex.find(name);
if (findIt == _layerIndex.end())
return 0;
return findIt->second;
}
shared_ptr<GameObject> SceneManager::Pick(int32 screenX, int32 screenY)
{
shared_ptr<Camera> camera = GetActiveScene()->GetMainCamera();
float width = static_cast<float>(GEngine->GetWindow().width);
float height = static_cast<float>(GEngine->GetWindow().height);
Matrix projectionMatrix = camera->GetProjectionMatrix();
// ViewSpace에서 Picking 진행
float viewX = (+2.0f * screenX / width - 1.0f) / projectionMatrix(0, 0);
float viewY = (-2.0f * screenY / height + 1.0f) / projectionMatrix(1, 1);
Matrix viewMatrix = camera->GetViewMatrix();
Matrix viewMatrixInv = viewMatrix.Invert();
auto& gameObjects = GET_SINGLE(SceneManager)->GetActiveScene()->GetGameObjects();
float minDistance = FLT_MAX;
shared_ptr<GameObject> picked;
for (auto& gameObject : gameObjects)
{
if (gameObject->GetCollider() == nullptr)
continue;
// ViewSpace에서의 Ray 정의
Vec4 rayOrigin = Vec4(0.0f, 0.0f, 0.0f, 1.0f);
Vec4 rayDir = Vec4(viewX, viewY, 1.0f, 0.0f);
// WorldSpace에서의 Ray 정의
rayOrigin = XMVector3TransformCoord(rayOrigin, viewMatrixInv);
rayDir = XMVector3TransformNormal(rayDir, viewMatrixInv);
rayDir.Normalize();
// WorldSpace에서 연산
float distance = 0.f;
if (gameObject->GetCollider()->Intersects(rayOrigin, rayDir, OUT distance) == false)
continue;
if (distance < minDistance)
{
minDistance = distance;
picked = gameObject;
}
}
return picked;
}
shared_ptr<Scene> SceneManager::LoadTestScene()
{
#pragma region LayerMask
SetLayerName(0, L"Default");
SetLayerName(1, L"UI");
#pragma endregion
shared_ptr<Scene> scene = make_shared<Scene>();
{
vector<Vertex> vec(4);
vec[0].pos = Vec3(-0.5f, 0.5f, 0.5f);
vec[0].color = Vec4(1.f, 0.f, 0.f, 1.f);
vec[1].pos = Vec3(0.5f, 0.5f, 0.5f);
vec[1].color = Vec4(0.f, 1.f, 0.f, 1.f);
vec[2].pos = Vec3(0.5f, -0.5f, 0.5f);
vec[2].color = Vec4(0.f, 0.f, 1.f, 1.f);
vec[3].pos = Vec3(-0.5f, -0.5f, 0.5f);
vec[3].color = Vec4(0.f, 1.f, 0.f, 1.f);
vector<uint32> indexVec;
{
indexVec.push_back(0);
indexVec.push_back(1);
indexVec.push_back(2);
}
{
indexVec.push_back(0);
indexVec.push_back(2);
indexVec.push_back(3);
}
mesh->Init(vec, indexVec);
shader->Init(L"..\\Resources\\Shader\\default.fx");
texture->Init(L"..\\Resources\\Texture\\EldenRing.jpg");
}
Scene.h
더보기
#pragma once
class GameObject;
class Scene
{
public:
void Awake();
void Start();
void Update();
void LateUpdate();
void FinalUpdate();
shared_ptr<class Camera> GetMainCamera();
void Render();
void ClearRTV();
void RenderDeferred();
void RenderLights();
void RenderFinal();
void RenderForward();
private:
void PushLightData();
public:
void AddGameObject(shared_ptr<GameObject> gameObject);
void RemoveGameObject(shared_ptr<GameObject> gameObject);
const vector<shared_ptr<GameObject>>& GetGameObjects() { return _gameObjects; }
private:
vector<shared_ptr<GameObject>> _gameObjects;
vector<shared_ptr<class Camera>> _cameras;
vector<shared_ptr<class Light>> _lights;
};
Scene.cpp
더보기
#include "pch.h"
#include "Scene.h"
#include "GameObject.h"
#include "Camera.h"
#include "Engine.h"
#include "ConstantBuffer.h"
#include "Light.h"
#include "Engine.h"
#include "Resources.h"
void Scene::Awake()
{
for (const shared_ptr<GameObject>& gameObject : _gameObjects)
{
gameObject->Awake();
}
}
void Scene::Start()
{
for (const shared_ptr<GameObject>& gameObject : _gameObjects)
{
gameObject->Start();
}
}
void Scene::Update()
{
for (const shared_ptr<GameObject>& gameObject : _gameObjects)
{
gameObject->Update();
}
}
void Scene::LateUpdate()
{
for (const shared_ptr<GameObject>& gameObject : _gameObjects)
{
gameObject->LateUpdate();
}
}
void Scene::FinalUpdate()
{
for (const shared_ptr<GameObject>& gameObject : _gameObjects)
{
gameObject->FinalUpdate();
}
}
shared_ptr<Camera> Scene::GetMainCamera()
{
if (_cameras.empty())
return nullptr;
return _cameras[0];
}
void Scene::Render()
{
PushLightData();
ClearRTV();
RenderDeferred();
RenderLights();
RenderFinal();
RenderForward();
}
void Scene::ClearRTV()
{
// SwapChain Group 초기화
int8 backIndex = GEngine->GetSwapChain()->GetBackBufferIndex();
GEngine->GetRTGroup(RENDER_TARGET_GROUP_TYPE::SWAP_CHAIN)->ClearRenderTargetView(backIndex);
// Deferred Group 초기화
GEngine->GetRTGroup(RENDER_TARGET_GROUP_TYPE::G_BUFFER)->ClearRenderTargetView();
// Lighting Group 초기화
GEngine->GetRTGroup(RENDER_TARGET_GROUP_TYPE::LIGHTING)->ClearRenderTargetView();
}
void Scene::RenderDeferred()
{
// Deferred OMSet
GEngine->GetRTGroup(RENDER_TARGET_GROUP_TYPE::G_BUFFER)->OMSetRenderTargets();
shared_ptr<Camera> mainCamera = _cameras[0];
mainCamera->SortGameObject();
mainCamera->Render_Deferred();
GEngine->GetRTGroup(RENDER_TARGET_GROUP_TYPE::G_BUFFER)->WaitTargetToResource();
}
void Scene::RenderLights()
{
shared_ptr<Camera> mainCamera = _cameras[0];
Camera::S_MatView = mainCamera->GetViewMatrix();
Camera::S_MatProjection = mainCamera->GetProjectionMatrix();
GEngine->GetRTGroup(RENDER_TARGET_GROUP_TYPE::LIGHTING)->OMSetRenderTargets();
// 광원을 그린다.
for (auto& light : _lights)
{
light->Render();
}
GEngine->GetRTGroup(RENDER_TARGET_GROUP_TYPE::LIGHTING)->WaitTargetToResource();
}
void Scene::RenderFinal()
{
// Swapchain OMSet
int8 backIndex = GEngine->GetSwapChain()->GetBackBufferIndex();
GEngine->GetRTGroup(RENDER_TARGET_GROUP_TYPE::SWAP_CHAIN)->OMSetRenderTargets(1, backIndex);
GET_SINGLE(Resources)->Get<Material>(L"Final")->PushGraphicsData();
GET_SINGLE(Resources)->Get<Mesh>(L"Rectangle")->Render();
}
void Scene::RenderForward()
{
shared_ptr<Camera> mainCamera = _cameras[0];
mainCamera->Render_Forward();
for (auto& camera : _cameras)
{
if (camera == mainCamera)
continue;
camera->SortGameObject();
camera->Render_Forward();
}
}
void Scene::PushLightData()
{
LightParams lightParams = {};
for (auto& light : _lights)
{
const LightInfo& lightInfo = light->GetLightInfo();
light->SetLightIndex(lightParams.lightCount);
lightParams.lights[lightParams.lightCount] = lightInfo;
lightParams.lightCount++;
}
CONST_BUFFER(CONSTANT_BUFFER_TYPE::GLOBAL)->SetGraphicsGlobalData(&lightParams, sizeof(lightParams));
}
void Scene::AddGameObject(shared_ptr<GameObject> gameObject)
{
if (gameObject->GetCamera() != nullptr)
{
_cameras.push_back(gameObject->GetCamera());
}
else if (gameObject->GetLight() != nullptr)
{
_lights.push_back(gameObject->GetLight());
}
_gameObjects.push_back(gameObject);
}
void Scene::RemoveGameObject(shared_ptr<GameObject> gameObject)
{
if (gameObject->GetCamera())
{
auto findIt = std::find(_cameras.begin(), _cameras.end(), gameObject->GetCamera());
if (findIt != _cameras.end())
_cameras.erase(findIt);
}
else if (gameObject->GetLight())
{
auto findIt = std::find(_lights.begin(), _lights.end(), gameObject->GetLight());
if (findIt != _lights.end())
_lights.erase(findIt);
}
auto findIt = std::find(_gameObjects.begin(), _gameObjects.end(), gameObject);
if (findIt != _gameObjects.end())
_gameObjects.erase(findIt);
}
▶DECLARE_SINGLE(SceneManager);
더보기
#define DECLARE_SINGLE(type) \
private: \
type() {} \
~type() {} \
public: \
static type* GetInstance() \
{ \
static type instance; \
return &instance; \
} \
#define GET_SINGLE(type) type::GetInstance()
'DirectX12' 카테고리의 다른 글
[DirectX12] 11) Light - 1 (이론) (1) | 2023.01.17 |
---|---|
[DirectX12] 10) Camera (0) | 2023.01.17 |
[DirectX12] 8) Material (0) | 2023.01.16 |
[DirectX12] 7) Component (0) | 2023.01.16 |
[DirectX12] 6) Timer (0) | 2023.01.15 |