반응형

서브모듈 정리

 

d3dx12.h는 2023년경부터 한 파일 구조에서 여러 파일로 분할됐습니다(d3dx12_core.h, d3dx12_barriers.h, d3dx12_root_signature.h 등). 파일을 손으로 복사해 쓰면 버전이 섞이거나 일부가 빠지기 쉽습니다. 게다가 신버전은 최신 d3d12.h를 전제로 작성돼 있어서, Windows SDK 버전과도 어긋날 수 있습니다.

해당 문제를 해결할 방법은 총 두가지입니다.

방식 내용 한계
DirectX-Headers 서브모듈 d3d12.h와 d3dx12를 같은 버전으로 통일 헤더만 최신, 런타임은 OS것(옛날 버전과 호환이 안될 수 있음)
Agility SDK 헤더와 D3D12Core.dll을 앱에 포함 DLL 배포와 export 심볼 선언이 필요

 

현재 상황에서는 기본 런타임으로 충분하기 때문에 서브모듈로 적용하여 다음과 같이 적용하여 수정했다.

 

bash.

git submodule add https://github.com/microsoft/DirectX-Headers.git ThirdParty/DirectX-Headers

 

CMakeLists.

# ThirdParty/CMakeLists.txt
add_subdirectory(DirectX-Headers)

# Engine/CMakeLists.txt
target_link_libraries(Engine PUBLIC DirectX-Headers DirectX-Guids d3d12 dxgi dxguid d3dcompiler imgui)

 

DxUtils.h 로 통일 후 기존 다른 파일의  <d3d12.h>, "d3dx12.h" 삭제.

// DxUtil.h
#include <directx/d3d12.h>     // 서브모듈 것, 반드시 맨 먼저
#include <directx/d3dx12.h>
#include <dxgi1_6.h>           // DXGI는 Windows SDK 것

 

이후 다른 환경에서 .git을 가져올때 재귀적으로 pull.

git pull
git submodule update --init --recursive

카메라

조작방식

입력 동작
우클릭 + 마우스 이동 시점 회전
우클릭 + WASD 플라이 이동 (Shift를 누르면 3배 가속)
Alt + 좌클릭 드래그 피벗 중심 오비트
휠 줌 (전진 / 후퇴)

 


Camera 클래스 (Engine/Scene/Camera)

카메라 상태는 위치와 yaw/pitch 두 각도로만 저장합니다. 행렬은 필요할 때마다 계산합니다.

멤버 의미
mPos 월드 위치.
mYaw 좌우 각도. 0이면 +Z를 봄
mPicth 상하 각도. 음수면 아래를 봄. ±89로 제한
mOrbitDist 오비트 피벗까지의 거리
mFovY, mAspect, mNear, mFar 투영 파라미터

 

전방 벡터는 구면좌표로 구합니다(왼손 좌표계 기준).

forward = (cos(pitch) * sin(yaw), sin(pitch), cos(pitch) * cos(yaw))
  • View: XMMatrixLookToLH(pos, forward, up). 목표 지점이 아니라 방향을 넘김
  • Right: normalize(cross(worldUp, forward)). 왼손 좌표계에서는 upxforward가 right입니다.
  • Pitch 제한: ±90을 넘으면 forward가 up과 평행해져서 화면이 뒤짚히므로 89로 제한합니다.

오비트는 피벗을 고정한 채 카메라를 돌린다는 뜻입니다. 총 세 단계로 구현됐습니다.

pivot = pos + forward * dist;   // 1. 현재 보고 있는 지점을 피벗으로
Rotate(dYaw, dPitch);           // 2. 각도 변경
pos = pivot - forward * dist;   // 3. 새 방향 기준으로 위치 재계산

줌을 전방으로 이동하면 mOrbitDist도 같이 줄어듭니다. 피벗을 뚫고 지나가지 않도록 최소 거리(0.2)를 둡니다.

 


입력 처리: Viewport 위에서만

에디터 카메라에서 가장 중요한 규칙은 다른 패널을 조작할때 카메라가 움직이면 안 된다는 것입니다.

// 시작은 Viewport 위에서만, 유지는 버튼을 누르고 있는 동안
if (hovered && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) flying = true;
if (!ImGui::IsMouseDown(ImGuiMouseButton_Right))              flying = false;
  • Camera 인스턴스는 main에 생성합니다. 그 후 ImGui 바인딩을 호출하며 Camera를 업데이트 합니다.
  • 시작 조건은 ImGui::IsWindowHovered() 로 Viewport 패널 위에서 클릭했는지 봅니다.
  • 유지 조건은 버튼을 누르고 있느지만 봅니다. 드래그하다 커서가 패널 밖으로 나가면 조작이 끊기지 않습니다.
  • 이동 속도에는 io.DeltaTime을 곱해서 프레임률과 무관하게 만듭니다.
  • 회전은 io.MouseDelta(프레임 간 이동량)에 감도(0.004rad/pixel)를 곱합니다.
  • io.ConfigWindowsMoveFromTitleBarOnly = true을 통해 Viewport를 플로팅 창으로 쓸때 Alt+좌클릭 드래그가 창 이동 되는것을 막습니다.

SceneRenderer 변경

Render(cmd, aspect, time)을 Render(cmd, viewProj)로 바꿨습니다.

카메라 행렬을 밖에서 받습니다. 렌더러가 카메라를 소유하지 않고 입력으로 받기 때문에, 나중에 뷰포트가 여러 개가 되어도 같은 렌더러를 재사용할 수 있습니다.

반응형

+ Recent posts