본문 바로가기

프로그래밍/Unreal

(10)
Landscape Heightmap의 데이터를 World Height로 바꾸어보자 아마 언리얼을 사용하는 대부분의 사용자에게는 전혀 필요없는 정보일 것이다. 사건의 발단은 언리얼 월드 전체를 Z축 방향으로 일정 Offset 만큼 올려야하는 일이 있어서였다. 월드 안에 있는 오브젝트가 한 두개 였다면 에디터에서 진행했겠지만, 수십만개의 오브젝트가 있었기 때문에 그건 불가능했다. Actor의 경우 정한 Offset 만큼 Z축 방향으로 올려준 뒤, SetActorLocation을 불러주고 저장하면 된다. 그러나 이렇게 해버리면 Landscape는 올라가지 않는다. Landscape를 위해서는 Heightmap 데이터를 불러와서, World의 Offset만큼 높여준 뒤 다시 Heightmap의 형태로 저장해주어야 한다. Get landscape heightmap data Heightmap 데..
[UE5] Sparse Distance Field - 2. Distance Field의 스트리밍 이전 글에서 대상 메시의 정보를 이용하여 디스턴스 필드 정보를 생성하고, 이를 FDistanceFieldVolumeData에 저장하는 과정을 살펴보았다. 이 VolumeData는 UStaticMesh의 RenderData 내부의 LODResource[0]번째에 DistanceFieldData라는 이름으로 저장되어있다. 또한 이 데이터를 어떤 형태로 저장해 두었는지 또한 확인하였다. 이번 글에는 이 에셋 데이터가 어떻게 씬에 올라가게 되고, 스트리밍 되는지를 살펴볼 예정이다. FDistanceFieldSceneData 지난 번에 살펴본 FDistanceFieldVolumeData가 각 메시 에셋을 대표한다면, FDistanceFieldSceneData는 이 에셋들을 관리하고 적절히 업데이트 해주는 책임을 ..
[UE5] Sparse Distance Field - 1. Distance Field를 만드는 과정 언리얼 엔진이 5 버전으로 넘어오면서, 디스턴스 필드 또한 눈에 띄진 않지만 많은 부분을 개선했다. 기존 4 버전에서는 메시의 디스턴스 필드를 사용하는데 있어서 가장 큰 문제는 너무 많은 메모리를 소비한다는 점이었다. 그렇기 때문에 디스턴스 필드는 해상도가 굉장히 제한적이었고, 많은 부분에 사용하기도 어려웠다. 5 버전에서는 이것을 개선하기 위해 디스턴스 필드에도 텍스쳐와 같이 Mip Level을 나누고, 이를 스트리밍할 수 있도록 만들었다. 스트리밍이 가능해졌기 때문에 상대적으로 가까운 물체에는 높은 해상도의 디스턴스 필드를, 그렇지 않은 물체에는 낮은 메모리 점유라는 이득을 취할 수 있었다. 물론 스트리밍에 드는 비용을 트레이드 오프로 지불해야만 한다. FMeshUtilities::GenerateSi..
[UE4] Virtual Texturing과 Clipmap Virtual Texturing(VT)이란 오픈 월드 게임등의 대규모 텍스쳐 사용에 따른 메모리 문제를 해결하기 위해, OS의 Virtual memory 알고리즘을 텍스쳐 시스템에 적용한 것이다. 메모리란 언제나 한정된 자원이고 이를 최대한 활용하기 위한 기법은 언제나 수요가 있다. VT는 텍스쳐를 일정한 크기의 Page(Tile)로 구분하여, 해당 페이지가 필요한 수준의 Mip Level을 타일 별로 메모리에 올리도록 만들어준다. 이는 기존에 언리얼에서 사용하던 텍스쳐 스트리밍 기법에 비해 페이지 관리 및 탐색 비용을 더 필요로하지만 메모리 사용량을 줄일 수 있다는 이점이 있다. Clipmap Clipmap은 VT 이전 시대의 텍스쳐 메모리 최적화 솔루션이다. 아래 레퍼런스 링크에서 설명을 굉장히 잘해..
[Unreal] 클래스의 Prefix를 F로 사용하는 이유. Unreal trivia: What does the 'F' prefix on classes and structs stand for? - Programming & Scripting / C++ - Unreal Engine Forums Unreal trivia: What does the 'F' prefix on classes and structs stand for? This gets asked all the time and I thought I would share the official story, as I remember wondering the same thing. ‘U’ stands for UObject, ‘A’ stands for actor, ‘T’ stands for Template. Everyon..
Unreal의 스레드와 단일 스레드로 실행시키기 (-norenderthread) 언리얼은 두 개의 메인 스레드로 돌고 있는데, 하나는 우리가 아는 게임 스레드이고 나머지 하나는 한 틱 뒤에서 이 게임스레드를 뒤쫓고 있는 렌더 스레드이다. 게임 스레드가 월드의 변경점을 렌더 스레드에 반영시키기 위해서는 ENQUEUE_RENDER_THREAD라는 매크로를 통해 람다 함수로 이를 렌더 큐에 쌓아두는 방식으로 접근한다. void BeginInitResource(FRenderResource* Resource) { ENQUEUE_RENDER_COMMAND(InitCommand)( [Resource](FRHICommandListImmediate& RHICmdList) { Resource->InitResource(); }); } RenderResource.cpp에 정의되어있는 BeginInitRe..
UE4 -waitforattach int32 GuardedMain(const TCHAR* CmdLine) { #if !(UE_BULID_SHIPPING) if (FParse::Param(CmdLine, TEXT("waitforattach")) { while (!FPlatformMisc::IsDebuggerPresent()); UE_DEBUG_BREAK(); } #endif ... } 언리얼을 실행시킬 경우, 실행인자로 -waitforattach라는 파라미터를 넣어줄 수 있다. 파라미터 이름에서 쉽게 유추 가능한 기능인데, 해당 파라미터를 넣으면 언리얼은 엔진 실행을 wait하며 디버거가 붙기를 기다려 준다. 디버거가 붙었다면, UE_DEBUG_BREAK를 이용하여 디버거에 신호를 준다. 쿠킹 로직을 따라가보고 싶은 경우에 사용하면 상당히..
GetTypeHash의 구현 size_t GetTypeHash() const { static size_t UniquePointer; return reinterpret_cast(&UniquePointer); } 타입마다 스태틱 변수를 선언하고 이 값의 주소값을 반환하는 방식으로 짜여져 있다. FPrimitiveSceneProxy에 순수가상함수로 선언되어있어 구현 클래스에서 이를 구현해주어야 한다. 예제 코드 #include #define DECLARE_TYPEHASH \ size_t GetTypeHash() const \ { \ static size_t UniquePointer; \ return reinterpret_cast(&UniquePointer); \ } class A { public: DECLARE_TYPEHASH }; cl..