대규모 월드 좌표 렌더링 개요

대규모 월드 좌표 렌더링의 개요입니다.

LWC 렌더링 개요

대규모 월드 좌표와 함께 도입된 새로운 HLSL 타입은 LargeWorldCoordinates.ush 파일에서 찾을 수 있습니다.

HLSL 타입

노트

FLWCScalar FLWCVector2/3/4

이 타입은 float1/2/3/4와 비슷하지만, 추가적인 타일 좌표가 포함되어 있습니다. 따라서 FLWCVector2는 float2 Tile과 float2 Offset으로 이루어집니다. 표시된 값은 다음과 같은 공식으로 계산됩니다. Tile * TileSize + Offset, TileSize는 256k로 정의된 상수 값입니다.

FLWCMatrix FLWCInverseMatrix

이 타입은 float4x4와 비슷하지만, 둘 다 추가적인 float3 타일 좌표가 포함되어 있습니다.

FLWCMatrix

매트릭스를 곱한 후 결과에 타일 좌표를 추가합니다.

FLWCInverseMatrix

매트릭스를 곱하기 전 타일 좌표를 추가합니다.

FLWCMatrix

월드 스페이스로 트랜스폼 시 사용됩니다(LocalToWorld).

FLWCInverseMatrix

월드 스페이스에서 트랜스폼 시 사용됩니다(WorldToLocal).

LWCAdd 또는 LWCRsqrt 와 같은 연산을 이러한 타입에서 수행할 수 있습니다. LWC 입력 값을 받는 연산은 LWC 출력을 반환하고(LWCAdd ), 그 외의 경우 일반 플로트 출력을 반환합니다(LWCRsqrt ). 이 구분은 어떤 구현 방식을 선택하는지에 따라 달라지지만, 좌표를 작게 만드는 연산의 경우 일반 플로트 값을 반환합니다.

셰이더 코드 내에서 여러 타입이 LWC 베리언트로 전환되었습니다. 아래 목록은 몇 가지 주목할 만한 예시입니다.

  • 높은 수준에서, LWC 타입은 유니폼 버퍼 내에 직접 포함되지 않습니다. 엔티티는 모두 동일한 타일 좌표를 사용할 수 있는 몇 가지 데이터 조각을 포함하고 있습니다(WorldToLocal, LocalToWorld, AbsoluteWorldPosition). 따라서 전형적인 패턴은 일반 비 LWC 값(RelativeWorldToLocal, LocalToRelativeWorld, RelativeWorldPosition)을 싱글 float3 TilePosition 값과 함께 유니폼 버퍼에 저장하는 것입니다.

셰이더 내에서 이 유니폼 데이터는 실제 LWC 값을 포함하는 새로운 구조체 타입으로 '언패킹'됩니다. 실제 LWC 값의 경우 여러 값이 싱글 TilePosition과 함께 초기화됩니다.

  • SceneData.ush, FPrimitiveSceneData, FInstanceSceneData는 다양한 최신 매트릭스 및 위치 벡터를 가지고 있습니다.

  • 글로벌 카메라 유니폼에는 다양한 매트릭스와 오프셋이 있습니다(PreViewTranslation 등). 기존에 글로벌 카메라 유니폼은 인스턴스드 스테레오 렌더링을 처리하는 메시 렌더링 시 ResolvedView를 통해 액세스되거나 포스트 프로세싱 및 기타 글로벌 패스 렌더링 시 View를 통해 접근할 수 있었습니다.

이전 엔진 버전에서 View가 글로벌 유니폼 버퍼를 직접 참조함에 따라 언패킹된 글로벌 뷰 구조체를 참조하는 새로운 에일리어스 PrimaryView 를 추가했습니다. 따라서 View.PreViewTranslation 과 같은 이름은 PrimaryView.PreViewTranslation 으로 변경되었습니다. ResolvedView.PreViewTranslation 은 적용 가능한 경우 계속 작동하며, 일반 View 에일리어스에서 비 LWC 양에 액세스할 수 있습니다.

  • 이제 FNaniteView가 카메라 유니폼에 대한 업데이트와 일치합니다.

  • 라이트 위치 및 리플렉션 캡처 위치가 새로운 LWC HLSL 타입으로 전환되었습니다.

이러한 글로벌 타입 전환은 LWC를 지원하기 위해 셰이더 코드를 리팩터링해야 하는 곳이 어디인지 통상적으로 알려줍니다. 예시:

    float3 WorldPosition = mul(Input.LocalPosition, View.LocalToWorld);

    //이는 더 이상 컴파일되지 않으며, 다음으로 리팩터링되어야 합니다.

    FLWCVector3 WorldPosition = LWCMultiply(Input.LocalPosition, PrimaryView.LocalToWorld);

초기 LWC 패스는 모든 셰이더가 LWC와 함께 제대로 작동하는지 확인하지 않습니다.

이 문제를 해결하려면 글로벌 함수 LWCHackToFloat 를 사용하여 LWC 타입을 비 LWC 타입으로 변환할 수 있습니다.

LWCHackToFloatLWCToFloat 함수를 둘러싼 래퍼처럼 작동합니다. 둘의 차이점은 LWC 스케일에서의 변환이 안전하다는 사실을 알 경우 LWCToFloat 함수가 사용된다는 것입니다. LWCHackToFloat 는 검색 가능 마커입니다. 코드베이스를 리팩터링하여 WorldPositionfloat3 에서 FLWCVector3 으로 전환할 시간이 없다면 대신 다음 코드를 사용할 수도 있습니다.

    float3 WorldPosition = mul(Input.LocalPosition, LWCHackToFloat(PrimaryView.LocalToWorld));

TranslatedWorldSpace는 UE5 셰이더에서 사용되는 기존의 엔진 개념입니다. 이전에는 카메라 원점에 대해 상대적으로 작동하여 정밀도를 높이기 위한 목적이었습니다. 그러나 TranslatedWorldSpace에서 작업 시 플로트를 사용하는 것이 안전하므로 이러한 작동은 LWC에도 유용합니다. WorldPosition을 LWC 값으로 변환하는 대신 다음과 같은 공식을 사용할 수 있습니다.

    float3 TranslatedWorldPosition = mul(Input.LocalPosition, PrimaryView.LocalToTranslatedWorld);

빠른 포팅 가이드

기존 HLSL 코드베이스를 언리얼 엔진 5로 포팅할 수 있습니다. 아래의 몇 가지 제안을 활용하면 성공적인 변환이 가능합니다.

  • 월드 스페이스에서 값/매트릭스 액세스 시 ViewPrimaryView 로 변경(LocalToWorld, PreViewTranslation)

  • 월드 스페이스에서 작동하는 코드가 함수 오버로드 또는 타입 변환이 누락되고, 코드베이스를 리팩터링할 리소스가 없으면, 다음과 같이 LWCHackToFloat 함수를 사용해 컴파일할 수 있습니다.

    (LWCHackToFloat(PrimaryView.PreViewTranslation))

그래도 코드가 컴파일되지 않으면 다음 방법을 사용해 보세요.

  • WorldSpace 대신 TranslatedWorldSpace에서 작동하도록 셰이더 코드 변경을 고려해 보세요.

  • 월드 스페이스 값은 LWC 타입을 필요로 합니다(float3 대신 FLWCVector3 필요). LWCAddLWCMin 함수를 사용해야 할 수 있습니다.

새로운 코드 개발 시 가급적 위에 나열된 가이드라인에 따라 TranslatedWorldSpace를 사용해야 합니다. 그렇지 않을 경우 LWC 타입을 사용하는 것을 권장합니다.

머티리얼 트랜슬레이터

머티리얼 트랜슬레이터(Material Translator) 가 LWC 값과 함께 작동하도록 업데이트되었습니다. 머티리얼 노드는 AbsoluteWorldPosition을 쿼리하고 WorldSpace로 트랜스폼할 때 플로트 대신 LWC 값을 출력합니다.

그러나 머티리얼이 LWC 스케일로 작동할 때는 퍼포먼스 비용이 소요될 수 있습니다. 포팅하는 머티리얼의 비용은 프로세스 콜을 추가하는 LWC 연산으로 인해 한층 더 높을 수 있습니다.

태그