DX12코드 갈아엎고 DX11로 다시 만들었다 구조도 전부 바뀜. 이 게시글->lighting ->normal mapping 순으로 수정
Transform
유니티처럼 Position, Rotation, Scale을 가지고 있는 transform component를 만들어 볼 생각이다.
// Component.h
enum class COMPONENT_TYPE : uint8
{
TRANSFORM,
END
}
컴포넌트를 상속받고 타입을 정해준다. 컴포넌트는 타입과 루프에 돌릴 함수들을 가지고 있고 컴포넌트가 속한 게임 오브젝트를 friend 시켜놓는다. 컴포넌트는 타입을 가지고 있어 gameObject는 해당 타입의 컴포넌트에 접근 가능하게 해준다.
class Component
{
public:
Component(COMPONENT_TYPE type) : _type(type) {}
virtual ~Component() = default;
public:
virtual void Start() {}
virtual void Update() {}
virtual void LateUpdate() {}
virtual void FinalUpdate() {}
virtual void UpdateImGui() {}
public:
COMPONENT_TYPE GetType() { return _type; }
private:
friend class GameObject;
void SetGameObject(std::shared_ptr<GameObject> gameObject) { _gameObject = gameObject; }
public:
std::shared_ptr<GameObject> GetGameObject();
std::shared_ptr<Transform> GetTransform();
protected:
COMPONENT_TYPE _type;
std::weak_ptr<GameObject> _gameObject;
};
GetTransform()은 카메라에서 현 오브젝트의 transform이 필요하므로 만들어놨다.
좌표는 크게 두가지로 나뉜다.
- Local
- World
위의 두 원을 보면 각 World좌표는 (2, 2)고, (5, 2)이다. 여기서 기준 좌표를 왼쪽 원으로 잡게되면 오른쪽 원의 좌표는 (3, 0)이 된다. 이것이 왼쪽 원을 기준으로 한 오른쪽 원의 Local 좌표가 되는 것이다. 이렇게 상대적인 좌표를 위해 transform은 기준이 되는 좌표, 즉 parent transform을 가지고 있도록 한다.
// Transform.h
#pragma once
#include "Component.h"
class Transform : public Component
{
public:
Transform() : Component(COMPONENT_TYPE::TRANSFORM) {};
virtual ~Transform() = default;
public:
virtual void FinalUpdate() override;
virtual void UpdateImGui() override;
void PushData();
public:
const FLOAT3& GetLocalPosition() { return _localPosition; }
const FLOAT3& GetLocalRotation() { return _localRotation; }
const FLOAT3& GetLocalScale() { return _localScale; }
const MATRIX& GetWorldMatrix() { return _matWorld; }
FLOAT3 GetWorldPosition() { return _matWorld.Translation(); }
void SetLocalPosition(const FLOAT3& position) { _localPosition = position; }
void SetLocalRotation(const FLOAT3& rotation) { _localRotation = rotation; }
void SetLocalScale(const FLOAT3& scale) { _localScale = scale; }
public:
void SetParent(std::shared_ptr<Transform> parent) { _parent = parent; }
std::weak_ptr<Transform> GetParent() { return _parent; }
private:
// Parent 기준
FLOAT3 _localPosition = {};
FLOAT3 _localRotation = {};
FLOAT3 _localScale = { 1.f, 1.f, 1.f };
MATRIX _matLocal = {};
MATRIX _matWorld = {};
std::weak_ptr<Transform> _parent;
};
편의를 위해 SimpleMath 함수들을 사용했다.
https://github.com/microsoft/DirectXTK
GitHub - microsoft/DirectXTK: The DirectX Tool Kit (aka DirectXTK) is a collection of helper classes for writing DirectX 11.x co
The DirectX Tool Kit (aka DirectXTK) is a collection of helper classes for writing DirectX 11.x code in C++ - GitHub - microsoft/DirectXTK: The DirectX Tool Kit (aka DirectXTK) is a collection of h...
github.com
// transform.cpp
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;
std::shared_ptr<Transform> parent = GetParent().lock();
if (parent != nullptr)
{
_matWorld *= parent->GetWorldMatrix();
}
}
_matLocal는 크기행렬, 회전행렬, 이동행렬(곱하는 순서중요 크기->회전(자전)->이동->공전->부모행렬)을 곱한 값이다. 그리고 _matWorld는 로컬 행렬에 부모 행렬까지 곱한 행렬이다.
편의상 rotation은 오일러 회전을 사용했다. 오일러 회전의 단점은 아래와 같은 짐벌락(gimbal lock) 현상이 일어난다는 것이다. 이러한 현상을 보완한 회전 방식이 쿼터니언 회전(quaternion rotation)이다. 간단하게 설명하면 대충 오일러는 회전 순서에 기반하고, 쿼터니언은 세 축을 동시에 회전시키기 때문에 짐벌락 현상이 일어나지 않는ek.
아무튼 이렇게 만든 transform을 hlsl에 넘겨주어 정점 셰이더의 pos에 곱해준다.
// VertexShader.hlsl
VSOut main(VSIn vin)
{
VSOut vso;
vso.pos = mul(float4(vin.pos, 1.f), transform);
vso.uv = vin.uv;
return vso;
}
'DirectX' 카테고리의 다른 글
법선 매핑(Normal Mapping) (0) | 2022.07.15 |
---|---|
조명(Lighting) (0) | 2022.06.09 |
7.6 루트 서명 추가 설명 (0) | 2022.01.08 |
7.5 도형 예제 (0) | 2022.01.06 |
7.4 도형 기하구조 (0) | 2022.01.06 |