본문 바로가기

그래픽스

[DX12] Camera

이번에는 좌표계 변환 행렬을 이용해서 Camera를 만들어 볼 것이다.

벡터 계산 등을 위해 microsoft의 simpleMath 라이브러리를 이용한다.

 

VS_OUT VS_Main(VS_IN input)
{
    VS_OUT output = (VS_OUT)0;

    output.pos = mul(float4(input.pos, 1.f), matWVP);
    output.color = input.color;
    output.uv = input.uv;

    return output;
}

 

Shader 코드에서 위치를 그대로 넘기는 것이 아닌  matWVP 행렬을 곱하는데, 이것은 Local 좌표에 World 변환 행렬, View 변환 행렬 , Projection 변환행렬을 곱하는 것과 같다. 

 

class Camera : public Component
{
public:
	Camera();
	virtual ~Camera();

	virtual void FinalUpdate() override;
	void Render();

private:
	PROJECTION_TYPE _type = PROJECTION_TYPE::PERSPECTIVE;

	float _near = 1.f;
	float _far = 1000.f;
	float _fov = XM_PI / 4.f;
	float _scale = 1.f;

	Matrix _matView = {};
	Matrix _matProjection = {};

public:
	// TEMP
	static Matrix S_MatView;
	static Matrix S_MatProjection;
};

 

카메라의 Update는 다른 물체들 Update가 완료되고 마지막으로 실행되기 떄문에 FinalUpdate라는 이름을 붙여준다.

지금은 임시로 View 변환 행렬과 Projection 변환 행렬을 외부에서 사용 가능하게 static으로 들고 있는다.

 

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;
}

 

View 좌표계는 카메라의 Local 좌표계라고도 했다. 그렇기 때문에 _matView는 카메라의 World 행렬의 역행렬이다. (GetLocalToWorldMatrix() = _matWorld) 그리고 Projection 변환은 카메라의 타입에 따라 함수로 실행한다.

 

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();
	}
}

 

Transform::FinalUpdate에서는 Scale, Rotation, Translation에 대하여 행렬을 만들어주고 S*R*T 순서로 곱해 Local 행렬을 구해준다. 부모가 없을 시 World 행렬이 Local 행렬이 되고 부모가 있을 시 Local 행렬에 부모의 world 행렬을 곱한 것이 World 행렬이 된다. 

 

void TestCameraScript::LateUpdate()
{
	Vec3 pos = GetTransform()->GetLocalPosition();

	if (INPUT->GetButton(KEY_TYPE::W))
		pos += GetTransform()->GetLook() * _speed * DELTA_TIME;

	if (INPUT->GetButton(KEY_TYPE::S))
		pos -= GetTransform()->GetLook() * _speed * DELTA_TIME;

	if (INPUT->GetButton(KEY_TYPE::A))
		pos -= GetTransform()->GetRight() * _speed * DELTA_TIME;

	if (INPUT->GetButton(KEY_TYPE::D))
		pos += GetTransform()->GetRight() * _speed * DELTA_TIME;

	if (INPUT->GetButton(KEY_TYPE::Q))
	{
		Vec3 rotation = GetTransform()->GetLocalRotation();
		rotation.x += DELTA_TIME * 0.5f;
		GetTransform()->SetLocalRotation(rotation);
	}

	if (INPUT->GetButton(KEY_TYPE::E))
	{
		Vec3 rotation = GetTransform()->GetLocalRotation();
		rotation.x -= DELTA_TIME * 0.5f;
		GetTransform()->SetLocalRotation(rotation);
	}

	GetTransform()->SetLocalPosition(pos);
}

 

최종적으로 입력에 따라 카메라의 Transform, Rotation을 변경해 조정할 수 있다.

'그래픽스' 카테고리의 다른 글

[DX12] Lighting 코드 #2  (0) 2022.07.25
[DX12] Lighting 코드 #1  (0) 2022.07.25
[DX12] Comoponent  (0) 2022.07.24
[DX12] Material  (0) 2022.07.23
[DX12] Depth Stencil View  (0) 2022.07.23