원근감(거리감) 없이, 물체의 실제 크기를 그대로 화면에 투영하는 방식
즉, 카메라에서 얼마나 멀리 있든 화면 크기가 절대 줄어들지 않는다.
이를 통해서 UI를 만들어 보자
Define.h에 Layer관련 enum 추가하기#pragma once
#include "Component.h"
enum class ProjectionType
{
Perspective, // 원근 투형 (3d, 원근법에 따라 크기 차이)
Orthographic, // 직교 투영 (2d, 화면에 들어온 모든 오브젝트는 같은 크기)
};
class Camera : public Component
{
using Super = Component;
public:
Camera();
virtual ~Camera();
virtual void Update() override;
void SetProjectionType(ProjectionType type) { _type = type; }
ProjectionType GetRrojectionType() { return _type; }
void UpdateMatrix();
void SetNear(float nearPlane) { _near = nearPlane; }
void SetFar(float farPlane) { _far = farPlane; }
void SetFov(float fov) { _fov = fov; }
void SetWidth(float width) { _width = width; }
void SetHeight(float height) { _height = height; }
Matrix& GetViewMatrix() { return _matView; }
Matrix& GetProjectionMatrix() { return _matProjection; }
float GetWidth() { return _width; }
float GetHeight() { return _height; }
private:
ProjectionType _type = ProjectionType::Perspective;
Matrix _matView = Matrix::Identity;
Matrix _matProjection = Matrix::Identity;
float _near = 1.f;
float _far = 1000.f;
float _fov = XM_PI / 4.f;
float _width = 0.f;
float _height = 0.f;
public:
static Matrix S_MatView;
static Matrix S_MatProjection;
public:
// 관련된 문체들을 가져오기
void SortGameObject();
void Render_Forward();
void SetCullingMaskLayerOnOff(uint8 layer, bool on)
{
if (on)
_cullingMask |= (1 << layer);
else
_cullingMask &= ~(1 << layer);
}
// 아무것도 그리지 않겠다.
void SetCullingMaskAll() { SetCullingMask(UINT32_MAX); }
void SetCullingMask(uint32 mask) { _cullingMask = mask; }
// 비트연산을 통해서 그려줄지 안그려줄지 판단
bool IsCulled(uint8 layer) { return (_cullingMask & (1 << layer)) != 0; }
private:
// 비트마스크 - 그릴지 안그릴지에 대한 규칙
uint32 _cullingMask = 0;
vector<shared_ptr<GameObject>> _vecForward;
};
void Camera::UpdateMatrix()
{
Vec3 eyePosition = GetTransform()->GetPosition();
Vec3 focusPosition = eyePosition + GetTransform()->GetLook();
Vec3 upDirection = GetTransform()->GetUp();
//S_MatView = GetTransform()->GetWorldMatrix().Invert();
_matView = ::XMMatrixLookAtLH(eyePosition, focusPosition, upDirection);
if (_type == ProjectionType::Perspective)
{
_matProjection = ::XMMatrixPerspectiveFovLH(_fov, _width / _height, _near, _far);
}
else
{
_matProjection = ::XMMatrixOrthographicLH(_width, _height, _near, _far);
}
}
void Camera::SortGameObject()
{
shared_ptr<Scene> scene = CUR_SCENE;
unordered_set<shared_ptr<GameObject>>& gameObjects = scene->GetObjects();
_vecForward.clear();
for (auto& gameObject : gameObjects)
{
if (IsCulled(gameObject->GetLayerIndex()))
continue;
if (gameObject->GetMeshRenderer() == nullptr &&
gameObject->GetModelRenderer() == nullptr &&
gameObject->GetModelAnimator() == nullptr)
continue;
_vecForward.push_back(gameObject);
}
}
void Camera::Render_Forward()
{
S_MatView = _matView;
S_MatProjection = _matProjection;
// 카메라에서 물체 그려주기
GET_SINGLE(InstancingManager)->Render(_vecForward);
}
enum LayerMask
{
Layer_Default = 0,
Layer_UI = 1,
};
#pragma once
class Scene
{
public:
virtual void Start();
virtual void Update();
virtual void LateUpdate();
virtual void Render();
virtual void Add(shared_ptr<GameObject> object);
virtual void Remove(shared_ptr<GameObject> object);
unordered_set<shared_ptr<GameObject>>& GetObjects() { return _objects; }
shared_ptr<GameObject> GetMainCamera();
shared_ptr<GameObject> GetUICamera();
shared_ptr<GameObject> GetLight() { return _lights.empty() ? nullptr : *_lights.begin(); }
shared_ptr<class GameObject> Pick(int32 screenX, int32 screenY);
void CheckCollision();
private:
unordered_set<shared_ptr<GameObject>> _objects;
// Cache Camera
unordered_set<shared_ptr<GameObject>> _cameras;
// Cache Light
unordered_set<shared_ptr<GameObject>> _lights;
};
void Scene::Render()
{
for (auto& camera : _cameras)
{
camera->GetCamera()->SortGameObject();
camera->GetCamera()->Render_Forward();
}
}
shared_ptr<GameObject> Scene::GetMainCamera()
{
for (auto& camera : _cameras)
{
if (camera->GetCamera()->GetRrojectionType() == ProjectionType::Perspective)
return camera;
}
return nullptr;
}
shared_ptr<GameObject> Scene::GetUICamera()
{
for (auto& camera : _cameras)
{
if (camera->GetCamera()->GetRrojectionType() == ProjectionType::Orthographic)
return camera;
}
return nullptr;
}
void SceneManager::Update()
{
if (_currentScene == nullptr)
return;
_currentScene->Update();
_currentScene->LateUpdate(); // 카메라가 들어감
_currentScene->Render();
}
void OrthographicDemo::Init()
{
//RESOURCES->Init();
_shader = make_shared<Shader>(L"23.RenderDemo.fx");
// Camera
{
auto camera = make_shared<GameObject>();
camera->GetOrAddTransform()->SetPosition(Vec3{ 0.f, 0.f, -5.f });
camera->AddComponent(make_shared<Camera>());
camera->AddComponent(make_shared<CameraScript>());
camera->GetCamera()->SetCullingMaskLayerOnOff(Layer_UI, true); // ui 끄기
CUR_SCENE->Add(camera);
}
// UI_Camera
{
auto camera = make_shared<GameObject>();
camera->GetOrAddTransform()->SetPosition(Vec3{ 0.f, 0.f, -5.f });
camera->AddComponent(make_shared<Camera>());
camera->GetCamera()->SetProjectionType(ProjectionType::Orthographic);
camera->GetCamera()->SetNear(1.f);
camera->GetCamera()->SetFar(100.f);
camera->GetCamera()->SetCullingMaskAll();
camera->GetCamera()->SetCullingMaskLayerOnOff(Layer_UI, false); // ui 켜기
CUR_SCENE->Add(camera);
}
// Light
{
auto light = make_shared<GameObject>();
light->AddComponent(make_shared<Light>());
LightDesc lightDesc;
lightDesc.ambient = Vec4(0.4f);
lightDesc.diffuse = Vec4(1.f);
lightDesc.specular = Vec4(0.1f);
lightDesc.direction = Vec3(1.f, 0.f, 1.f);
light->GetLight()->SetLightDesc(lightDesc);
CUR_SCENE->Add(light);
}
// Material
{
shared_ptr<Material> material = make_shared<Material>();
material->SetShader(_shader);
auto texture = RESOURCES->Load<Texture>(L"Veigar", L"..\\Resources\\Textures\\veigar.jpg");
material->SetDiffuseMap(texture);
MaterialDesc& desc = material->GetMaterialDesc();
desc.ambient = Vec4(1.f);
desc.diffuse = Vec4(1.f);
desc.specular = Vec4(1.f);
RESOURCES->Add(L"Veigar", material);
}
// Mesh 버튼 형식
{
auto obj = make_shared<GameObject>();
obj->GetOrAddTransform()->SetLocalPosition(Vec3(0.f, 200.f, 0.f));
obj->GetOrAddTransform()->SetScale(Vec3(200.f));
obj->AddComponent(make_shared<MeshRenderer>());
obj->SetLayerIndex(Layer_UI);
{
obj->GetMeshRenderer()->SetMaterial(RESOURCES->Get<Material>(L"Veigar"));
}
{
auto mesh = RESOURCES->Get<Mesh>(L"Quad");
obj->GetMeshRenderer()->SetMesh(mesh);
obj->GetMeshRenderer()->SetPass(0);
}
CUR_SCENE->Add(obj);
}
// Mesh
{
auto obj = make_shared<GameObject>();
obj->GetOrAddTransform()->SetLocalPosition(Vec3(0.f));
obj->GetOrAddTransform()->SetScale(Vec3(2.f));
obj->AddComponent(make_shared<MeshRenderer>());
{
obj->GetMeshRenderer()->SetMaterial(RESOURCES->Get<Material>(L"Veigar"));
}
{
auto mesh = RESOURCES->Get<Mesh>(L"Sphere");
obj->GetMeshRenderer()->SetMesh(mesh);
obj->GetMeshRenderer()->SetPass(0);
}
CUR_SCENE->Add(obj);
}
}
