For me
[DirectX12] 10) Camera 본문
Transform
Camera를 구현하기전, 먼저 Transform을 구현해야함
▶ 월드좌표, 로컬좌표를 구해야 하기 때문에
PushData를 통해 ConstantBuffer을 통해 transformParams를 GPU로 보내준다
Transfom.h
더보기
#pragma once
#include "Component.h"
class Transform : public Component
{
public:
Transform();
virtual ~Transform();
virtual void FinalUpdate() override;
void PushData();
public:
// Parent 기준
const Vec3& GetLocalPosition() { return _localPosition; }
const Vec3& GetLocalRotation() { return _localRotation; }
const Vec3& GetLocalScale() { return _localScale; }
//TEMP
float GetBoundingSphereRadius() { return max(max(_localScale.x, _localScale.y), _localScale.z); }
const Matrix& GetLocalToWorldMatrix() { return _matWorld; }
Vec3 GetWorldPosition() { return _matWorld.Translation(); }
Vec3 GetRight() { return _matWorld.Right(); }
Vec3 GetUp() { return _matWorld.Up(); }
Vec3 GetLook() { return _matWorld.Backward(); }
void SetLocalPosition(const Vec3& position) { _localPosition = position; }
void SetLocalRotation(const Vec3& rotation) { _localRotation = rotation; }
void SetLocalScale(const Vec3& scale) { _localScale = scale; }
public:
void SetParent(shared_ptr<Transform> parent) { _parent = parent; }
weak_ptr<Transform> GetParent() { return _parent; }
private:
// Parent 기준
Vec3 _localPosition = {};
Vec3 _localRotation = {};
Vec3 _localScale = { 1.f, 1.f, 1.f };
Matrix _matLocal = {};
Matrix _matWorld = {};
weak_ptr<Transform> _parent;
};
Transfom.cpp
더보기
#include "pch.h"
#include "Transform.h"
#include "Engine.h"
#include "Camera.h"
Transform::Transform() : Component(COMPONENT_TYPE::TRANSFORM)
{
}
Transform::~Transform()
{
}
void Transform::FinalUpdate()
{
Matrix matScale = Matrix::CreateScale(_localScale);
Matrix matRotation = Matrix::CreateRotationX(_localRotation.x);
matRotation *= Matrix::CreateRotationY(_localRotation.y);
matRotation *= Matrix::CreateRotationZ(_localRotation.z);
Matrix matTranslation = Matrix::CreateTranslation(_localPosition);
_matLocal = matScale * matRotation * matTranslation;
_matWorld = _matLocal;
shared_ptr<Transform> parent = GetParent().lock();
if (parent != nullptr)
{
_matWorld *= parent->GetLocalToWorldMatrix();
}
}
void Transform::PushData()
{
TransformParams transformParams = {};
transformParams.matWorld = _matWorld;
transformParams.matView = Camera::S_MatView;
transformParams.matProjection = Camera::S_MatProjection;
transformParams.matWV = _matWorld * Camera::S_MatView;
transformParams.matWVP = _matWorld * Camera::S_MatView * Camera::S_MatProjection;
transformParams.matViewInv = Camera::S_MatView.Invert();
CONST_BUFFER(CONSTANT_BUFFER_TYPE::TRANSFORM)->PushGraphicsData(&transformParams, sizeof(transformParams));
}
Camera
meshRenderer가 있는 모든 물체를 그려줌
Cemra.cpp
더보기
#include "pch.h"
#include "Camera.h"
#include "Transform.h"
#include "Scene.h"
#include "SceneManager.h"
#include "GameObject.h"
#include "MeshRenderer.h"
#include "Engine.h"
Matrix Camera::S_MatView;
Matrix Camera::S_MatProjection;
Camera::Camera() : Component(COMPONENT_TYPE::CAMERA)
{
}
Camera::~Camera()
{
}
void Camera::FinalUpdate()
{
_matView = GetTransform()->GetLocalToWorldMatrix().Invert();
float width = static_cast<float>(GEngine->GetWindow().width);
float height = static_cast<float>(GEngine->GetWindow().height);
if (_type == PROJECTION_TYPE::PERSPECTIVE)
_matProjection = ::XMMatrixPerspectiveFovLH(_fov, width / height, _near, _far);
else
_matProjection = ::XMMatrixOrthographicLH(width * _scale, height * _scale, _near, _far);
S_MatView = _matView;
S_MatProjection = _matProjection;
}
void Camera::Render()
{
shared_ptr<Scene> scene = GET_SINGLE(SceneManager)->GetActiveScene();
const vector<shared_ptr<GameObject>>& gameObjects = scene->GetGameObjects();
for (auto& gameObject : gameObjects)
{
if (gameObject->GetMeshRenderer() == nullptr)
continue;
gameObject->GetMeshRenderer()->Render();
}
}
Frustum Culling
카메라 영역 안에 있는 물체만 그려주는 방법
CPU 단계에서 필터를 거쳐 GPU에서 계산안해도 되도록 하는 기술
평면 A (ax+by+cz+d = 0) , A의 법선벡터 n(a,b,c) , 임의의 점B(X,Y,Z) 과 O로 이루어진 벡터 OB
n과 OB벡터의 내적은 aX+bY+cZ
▶ 만약 최종값이 0이라면 평면위에 위치한다고 알 수 있음
위와 같은 방식으로 6개의 평면과 비교하여 계산함.
Frustum.h
더보기
#pragma once
enum PLANE_TYPE : uint8
{
PLANE_FRONT,
PLANE_BACK,
PLANE_UP,
PLANE_DOWN,
PLANE_LEFT,
PLANE_RIGHT,
PLANE_END,
};
class Frustum
{
public:
void FinalUpdate();
bool ContainsSphere(const Vec3& pos, float radius);
private:
array<Vec4, PLANE_END> _planes;
};
Frustum.ccp
더보기
#include "pch.h"
#include "Frustum.h"
#include "Camera.h"
void Frustum::FinalUpdate()
{
Matrix matViewInv = Camera::S_MatView.Invert();
Matrix matProjectionInv = Camera::S_MatProjection.Invert();
Matrix matInv = matProjectionInv * matViewInv;
vector<Vec3> worldPos =
{
::XMVector3TransformCoord(Vec3(-1.f, 1.f, 0.f), matInv),
::XMVector3TransformCoord(Vec3(1.f, 1.f, 0.f), matInv),
::XMVector3TransformCoord(Vec3(1.f, -1.f, 0.f), matInv),
::XMVector3TransformCoord(Vec3(-1.f, -1.f, 0.f), matInv),
::XMVector3TransformCoord(Vec3(-1.f, 1.f, 1.f), matInv),
::XMVector3TransformCoord(Vec3(1.f, 1.f, 1.f), matInv),
::XMVector3TransformCoord(Vec3(1.f, -1.f, 1.f), matInv),
::XMVector3TransformCoord(Vec3(-1.f, -1.f, 1.f), matInv)
};
_planes[PLANE_FRONT] = ::XMPlaneFromPoints(worldPos[0], worldPos[1], worldPos[2]); // CW
_planes[PLANE_BACK] = ::XMPlaneFromPoints(worldPos[4], worldPos[7], worldPos[5]); // CCW
_planes[PLANE_UP] = ::XMPlaneFromPoints(worldPos[4], worldPos[5], worldPos[1]); // CW
_planes[PLANE_DOWN] = ::XMPlaneFromPoints(worldPos[7], worldPos[3], worldPos[6]); // CCW
_planes[PLANE_LEFT] = ::XMPlaneFromPoints(worldPos[4], worldPos[0], worldPos[7]); // CW
_planes[PLANE_RIGHT] = ::XMPlaneFromPoints(worldPos[5], worldPos[6], worldPos[1]); // CCW
}
bool Frustum::ContainsSphere(const Vec3& pos, float radius)
{
for (const Vec4& plane : _planes)
{
// n = (a, b, c)
Vec3 normal = Vec3(plane.x, plane.y, plane.z);
// ax + by + cz + d > radius
if (normal.Dot(pos) + plane.w > radius)
return false;
}
return true;
}
'DirectX12' 카테고리의 다른 글
[DirectX12] 12) Light - 2 (0) | 2023.01.17 |
---|---|
[DirectX12] 11) Light - 1 (이론) (1) | 2023.01.17 |
[DirectX12] 9) Scene (0) | 2023.01.16 |
[DirectX12] 8) Material (0) | 2023.01.16 |
[DirectX12] 7) Component (0) | 2023.01.16 |