프로그래밍 공부
작성일
2023. 10. 22. 18:05
작성자
WDmil
728x90

 

먼저 카메라의 움직임을 구현하기 전에 

먼저 카메라의 위치값과 이동을 확인하기 위해 배경지식이 필요하다.

 

각각 코사인 제1법칙, 제2법칙. 그리고 벡터의 내적 외적을 알아야 한다.

 

이러한 벡터의 내적과 외적계산을 통해 더 쉽게 카메라의 움직임을 구현할 수 있다.


camera Header

#pragma once

class Camera : public Transform
{
public:
	Camera();
	~Camera();

	void Update();
	void GUIRender();

	void SetView();
private:
	void FreeMode();

private:
	MatrixBuffer* viewBuffer;
	Matrix view;

	float moveSpeed = 50.0f;
	float rotSpeed = 10.0f;

};

카메라 헤더에서 사용하는데이터는 Transform을 그대로 가져와 사용하며, MatrixBuffer와 Matrix를 통해 View를 관리하고,

 

moveSpeed와 rotSpeed를 통해. 이동속도와 회전속도를 관리하는 변수를 사용한다.


#include "Framework.h"

Camera::Camera()
{

	viewBuffer = new MatrixBuffer();

}

Camera::~Camera()
{
	delete viewBuffer;
}

void Camera::Update()
{
	FreeMode();
	UpdateWorld();
}

void Camera::GUIRender()
{
	if (ImGui::TreeNode("CameraOption"))
	{
		ImGui::DragFloat("MoveSpeed", &moveSpeed);
		ImGui::DragFloat("MoveSpeed", &rotSpeed);

		ImGui::TreePop();
	}
}

void Camera::SetView()
{
	view = XMMatrixInverse(nullptr, world);

	viewBuffer->Set(view);
	viewBuffer->SetVS(1);
}

void Camera::FreeMode()
{
	Vector3 delta = Mouse::Get()->GetMoveValue();

	if (KEY->Press(VK_RBUTTON))
	{
		if (KEY->Press('W'))
			Translate(GetForward() * moveSpeed * DELTA);
		if (KEY->Press('S'))
			Translate(GetBack() * moveSpeed * DELTA);
		if (KEY->Press('A'))
			Translate(GetLeft() * moveSpeed * DELTA);
		if (KEY->Press('D'))
			Translate(GetRight() * moveSpeed * DELTA);
		if (KEY->Press('Q'))
			Translate(GetUp() * moveSpeed * DELTA);
		if (KEY->Press('E'))
			Translate(GetDown() * moveSpeed * DELTA);


		Rotate(Vector3::Up() * delta.x * rotSpeed * DELTA);
		Rotate(Vector3::Left() * -delta.y * rotSpeed * DELTA);
	}

}

cpp파일이다.

 

이전에 만들어놓았던 viewBuffer에 MatrixBuffer을 생성하면서 생성자를 사용한다.

 

Update로는 FreeMode()[ 자유시점 ]과 UpdateWorld를 사용한다.

 

GUIRneder()에서는 사용할 변수를 WIn창에서 사용할 수 있도록 GUI를 생성하고 조절하게 만든다.

 

SetView에서는 XMMatrixInvers를 통해 역행렬을 생성하여. view에 할당하고. 해당 역행렬을 view버퍼에 사용한다.

 

FreeMode에서는 코드가 더욱 간단해진다.

 

delta에 Mouse의 move를 input받아 사용한다.

 

안에 Translate함수가 있는데

 

해당 함수는 Transform의 localPosition변환 함수로 다음과 같은 코드를 가진다.

void Transform::Translate(Vector3 direction)
{
	localPosition += direction;
}

이러한 Translate를 사용하여 객체의 위치변환을 조절해줄 수 있다.

 

이러한 데이터가 적용된 값을 활용하여. SetView로 카메라를 객체로 취급하여 MatrixInvers를 사용해 world를 뒤집어서 view로 반환하면. 현재 월드 객체를 기준으로 역행렬을 만들어 뒷객채를 view와 pos로 취급하여 사용할 수 있다.

 

Rotate는 rotSpeed를 사용해서 Vector3의 위와 아래를 사용하여 현재 객채에 상하좌우 연산을 추가하여 데이터를 변환할 수 있게 한다.

 

그리하여. 카메라의 회전과 이동을 사용할 수 있다.


위 카메라연산을 비슷하게 사용하여. Color값을 변환하여 위치참조하고. 데이터를 변환하여 한 객체의 Vertex간 Color값을 변화시킬 수 있다.

 

즉, 일정 localPos의 위치에 태양을 설정하고. 해당 위치에서 Vertex의 위치의 각도를 계산하여.

 

이 Vertex의 위치가 태양과 어떠한 각도로 빛이 비춰지고있는지 계산하고. 해당 계산내용을 Color값에 곱해서.

 

밝기값을 조절해줄 수 있다.

 

밝기조절근거는 다음과 같다.

위 이미지와 같이. 조정된 Vertex의 위치에 해당하는 법선을 구현하고.

 

그 법선을 기준으로 입사각 반사각을 계산하여. 데이터를 조정하면.

 

빛의 각도와 법선의 각도의 cos만큼 어둡게 또는 밝게 만들면 되는것이다.

 

이러한 빛의 반사차이는 직접광, 간접광 두개의 차이가 존재한다.

 

직접광에서는 또 난반사와 정반사로 나뉘는데,

 

난반사는 말 그대로 해석해서 난잡하게 반사된다고 이해하면된다.

 

들어온 빛이 그 각도를 유지한채로 반사되는것 이 아닌, 다른부분으로 퍼지면서 반사되기 때문에

 

들어온 빛이 그대로 리턴디는것이 아닌 색감만 조금 밝아지는 정도에 그친다.

728x90