게임 개발 자료/DirectX 스터디

DirectX 11 스터디 - Camera 컴포넌트

원소랑 2023. 9. 26. 16:07
728x90

Camera 컴포넌트를 생성해서 View, Projection Matrix 를 갱신하고, 갱신한 값을 셰이더에서 참조, 연산하도록 수정.

 

먼저 기존에 GameObject 에서 TransformData 를 갱신하던 코드. Transform클래스의 UpdateTransform 함수에서 World좌표계 변환 Matrix를 만들었다.

void GameObject::Update()
{
	_transformData.matWorld = _transform->GetWorldMatrix();
	_constantBuffer->CopyDate(_transformData);
}

void Transform::UpdateTransform()
{
	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; // SRT

	if (!HasParent())
	{
		_matWorld = _matLocal;
	}
	else
	{
		_matWorld = _matLocal * _parent->GetWorldMatrix();
	}
}

Camera 컴포넌트에서는 Transform 컴포넌트를 가져와서 View(카메라)Matrix를 구성한다.

- 카메라의 위치

- 바라보는 대상

- Up벡터

이렇게 3개 벡터로 ViewMatrix를 구성할 수 있음. 이 때 사용되는 함수가 ::XMMatrixLookAtLH() 함수. 카메라의 Look벡터와 Up벡터를 외적해서 Right 를 새로 구하고, Up벡터도 외적으로 새로 계산해 ViewMatrix를 생성한다.

 

혹은, Camera의WorldMatrix의 역행렬(Invert)을 구하면 간단하게 구할 수 있기도. ProjectionType 에 따라서 DirectXMathMatrix 함수 사용이 달라짐.

Perspective Type : ::XMMatrixPerspectiveFovLH()

Orthographic Type : ::XMMatrixOrthographicLH()

Matrix Camera::S_MatView = Matrix::Identity;
Matrix Camera::S_MatProjection = Matrix::Identity;


void Camera::Update()
{
	UpdateMatrix();
}

void Camera::UpdateMatrix()
{
	Vec3 eyePosition = GetTransform()->GetPosition();
	Vec3 targetPosition = eyePosition + GetTransform()->GetLook();
	Vec3 upDirection = GetTransform()->GetUp();
	S_MatView = ::XMMatrixLookAtLH(eyePosition, targetPosition, upDirection);

	//S_MatView = GetTransform()->GetWorldMatrix().Invert();

	if (_type == ProjectionType::Perspective)
		S_MatProjection = ::XMMatrixPerspectiveFovLH(XM_PI / 4.f, 800.f / 600.f, 1.f, 100.f);
	else
		S_MatProjection = ::XMMatrixOrthographicLH(800.f, 600.f, 0.f, 1.f);
}

이제 상수버퍼를 분리해준다. 기존에 TransformData 에 World, View, Proejction Matrix가 모두 모여있던 걸 분리.  GameObject의 ConstantBuffer도 2개로 나눠서 생성해준다.

struct CameraData
{
	Matrix matView = Matrix::Identity;
	Matrix matProjection = Matrix::Identity;
};

struct TransformData
{
	Matrix matWorld = Matrix::Identity;
};

class GameObject : public enable_shared_from_this<GameObject>
{
	//...
private:
	CameraData _cameraData;
	shared_ptr<ConstantBuffer<CameraData>> _cameraBuffer;
	
	TransformData _transformData;
	shared_ptr<ConstantBuffer<TransformData>> _transformBuffer;
}

void GameObject::Update()
{
	for (shared_ptr<Component>& component : _components)
	{
		if (component)
			component->Update();
	}

	for (shared_ptr<MonoBehaviour>& script : _scripts)
	{
		script->Update();
	}
	
	if (GetCamera()) // Camera 컴포넌트를 가진 GameObject라면 패스.
		return;

	// cameraData 복사 추가.
	_cameraData.matView = Camera::S_MatView;
	_cameraData.matProjection = Camera::S_MatProjection;
	_cameraBuffer->CopyData(_cameraData);

	// transformData 복사 추가.
	_transformData.matWorld = _transform->GetWorldMatrix();
	_transformBuffer->CopyData(_transformData);
}

생성하고 갱신한 ConstantBuffer 는 GameObject::Render() 함수에서 Pipeline의 SetConstantBuffer() 함수로 0, 1 번 슬롯에 각각 연결. 셰이더도 아래와 같이 수정.

void GameObject::Render(shared_ptr<Pipeline> pipeline)
{
	//..
	pipeline->SetConstantBuffer(0, SS_VertexShader, _cameraBuffer);
	pipeline->SetConstantBuffer(1, SS_VertexShader, _transformBuffer);
    //..
}

cbuffer CameraData : register(b0)
{
	row_major matrix matView;
	row_major matrix matProjection;
}
cbuffer TransformData : register(b1)
{
	row_major matrix matWorld;
}

여기까지 처리하면, Camera 컴포넌트와 Camera 컴포넌트에서 처리한 View, Projection Matrix 를 Shader로 전달해서 처리까지 완료. 아래는 결과 화면.

다음은, Rendering Pipeline 의 주인공(?)이라고 할 수 있는 MeshRenderer 를 생성해서, Rendering 과 관련된 코드를 MeshRenderer 로 옮겨서 모듈화 해본다.


<리얼-타임 렌더링(REAL-TIME RENDERING) 4/e> 구입 링크
https://link.coupang.com/a/8VWas

 

리얼-타임 렌더링 4/e

COUPANG

www.coupang.com

<DirectX 12를 이용한 3D 게임 프로그래밍 입문> 구입 링크
https://link.coupang.com/a/8V4Wq

 

DirectX 12를 이용한 3D 게임 프로그래밍 입문:게임 개발 중심으로 익히는 대화식 컴퓨터 그래픽 프

COUPANG

www.coupang.com

<이득우의 게임 수학:39가지 예제로 배운다! 메타버스를 구성하는 게임 수학의 모든 것> 구입 링크

https://link.coupang.com/a/9BqLd

 

이득우의 게임 수학:39가지 예제로 배운다! 메타버스를 구성하는 게임 수학의 모든 것

COUPANG

www.coupang.com

유니티 에셋 스토어 링크

https://assetstore.unity.com?aid=1011lvz7h 

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

(링크를 통해 도서/에셋 구입시 일정액의 수수료를 지급받습니다.)


728x90
반응형