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 타입으로 변환할 수 있습니다.
LWCHackToFloat
는 LWCToFloat
함수를 둘러싼 래퍼처럼 작동합니다. 둘의 차이점은 LWC 스케일에서의 변환이 안전하다는 사실을 알 경우 LWCToFloat
함수가 사용된다는 것입니다. LWCHackToFloat
는 검색 가능 마커입니다. 코드베이스를 리팩터링하여 WorldPosition
을 float3
에서 FLWCVector3
으로 전환할 시간이 없다면 대신 다음 코드를 사용할 수도 있습니다.
float3 WorldPosition = mul(Input.LocalPosition, LWCHackToFloat(PrimaryView.LocalToWorld));
TranslatedWorldSpace는 UE5 셰이더에서 사용되는 기존의 엔진 개념입니다. 이전에는 카메라 원점에 대해 상대적으로 작동하여 정밀도를 높이기 위한 목적이었습니다. 그러나 TranslatedWorldSpace에서 작업 시 플로트를 사용하는 것이 안전하므로 이러한 작동은 LWC에도 유용합니다. WorldPosition을 LWC 값으로 변환하는 대신 다음과 같은 공식을 사용할 수 있습니다.
float3 TranslatedWorldPosition = mul(Input.LocalPosition, PrimaryView.LocalToTranslatedWorld);
빠른 포팅 가이드
기존 HLSL 코드베이스를 언리얼 엔진 5로 포팅할 수 있습니다. 아래의 몇 가지 제안을 활용하면 성공적인 변환이 가능합니다.
월드 스페이스에서 값/매트릭스 액세스 시
View
를PrimaryView
로 변경(LocalToWorld, PreViewTranslation)월드 스페이스에서 작동하는 코드가 함수 오버로드 또는 타입 변환이 누락되고, 코드베이스를 리팩터링할 리소스가 없으면, 다음과 같이
LWCHackToFloat
함수를 사용해 컴파일할 수 있습니다.(LWCHackToFloat(PrimaryView.PreViewTranslation))
그래도 코드가 컴파일되지 않으면 다음 방법을 사용해 보세요.
WorldSpace 대신 TranslatedWorldSpace에서 작동하도록 셰이더 코드 변경을 고려해 보세요.
월드 스페이스 값은 LWC 타입을 필요로 합니다(float3 대신 FLWCVector3 필요).
LWCAdd
및LWCMin
함수를 사용해야 할 수 있습니다.
새로운 코드 개발 시 가급적 위에 나열된 가이드라인에 따라 TranslatedWorldSpace를 사용해야 합니다. 그렇지 않을 경우 LWC 타입을 사용하는 것을 권장합니다.
머티리얼 트랜슬레이터
머티리얼 트랜슬레이터(Material Translator) 가 LWC 값과 함께 작동하도록 업데이트되었습니다. 머티리얼 노드는 AbsoluteWorldPosition을 쿼리하고 WorldSpace로 트랜스폼할 때 플로트 대신 LWC 값을 출력합니다.
그러나 머티리얼이 LWC 스케일로 작동할 때는 퍼포먼스 비용이 소요될 수 있습니다. 포팅하는 머티리얼의 비용은 프로세스 콜을 추가하는 LWC 연산으로 인해 한층 더 높을 수 있습니다.