언어:
페이지 정보
수준별:
엔진 버전:
언리얼 엔진

슬레이트 클리핑 시스템

언리얼 엔진

언리얼 엔진 4.17 릴리즈 이후, 슬레이트 클리핑 시스템은 4.16 이전 버전과의 하위 호환성을 깨트립니다. 프로젝트 업데이트를 위해서는 이 페이지의 4.16 이전에서 4.17 이후로 변환 안내 부분을 참고하세요.

언리얼 엔진 4 (UE4) 는 슬레이트의 클리픽 시스템을 사용하여 그래픽이나 텍스트를 화면의 일정 구역에 제한시킵니다. 이는 생성되는 오브젝트와 패널 주변에 클리핑 사각형(clipping rectangle 또는 clipping rect)을 만드는 방식으로 이루어집니다. 이 시스템은 에디터와 UMG UI 디자이너 툴 전반에 걸쳐 사용됩니다. 슬레이트는 사용자로 하여금 에디터에서 필요에 따라 패널 위치와 크기를 조절할 수 있도록 해주며, 클리핑 시스템은 텍스트와 그래픽이 클리핑 사각형 안으로 제한시킵니다. UMG 와 함께 사용하면, UI 가 제대로 클리핑되는 개선된 렌더 트랜스폼을 만들 수 있습니다.

새로운 기능

언리얼 엔진 4.17 에서 클리핑 시스템이 크게 바뀌어 전 버전에 비해 유연성이 대폭 향상되었습니다. 이를 통해 프로젝트의 UI 에도 UMG 같은 툴 시스템용 렌더링 이펙트를 더 많이 추가할 수 있는 가능성이 생겼습니다. 이전 엔진 버전에 사용되던 클리핑 시스템은 한계가 많고 레이아웃 스페이스에서 축 평행인 경우만 지원했기에 아래 예제처럼 렌더 트랜스폼 관련해서 주로 에지 주변에 눈에 띄는 부작용이 많이 생겼었습니다:

OldClippingIssue1.png

OldClippingIssue2.png

이 예제에서는 위젯을 회전시켜도 클리핑 사각형(하양 점)은 회전되지 않아, 그래픽이 캔버스 패널 바운드 안에 들어와도 렌더링되지 않습니다.

아래는 클리핑 시스템 1.0 vs 2.0 차이점 목록입니다:

클리핑 1.0 (4.16 이전)

클리핑 2.0 (4.17 이후)

  • 축 평행 클리핑 - 레이아웃 스페이스에서만 작동합니다.

  • 위젯만 클리핑됩니다.

  • 모든 클리핑은 픽셀 셰이더이서 일어납니다 (버텍스 당 6 플로트가 필요합니다).

  • 클리핑 사각형에 걸친 일괄 처리가 가능한데, 사각형은 일괄 데이터의 일부이기 때문입니다.

  • 렌더 트랜스폼은 부모에 제공된 클리핑 사각형 외부 렌더링이 가능하다는 점에서 "특수"한데, 레이아웃 사각형이 클리핑되면 부작용이 생기기는 합니다.

  • 임의 쿼드 클리핑입니다.

    • Scissor Rects (가위 사각형)을 사용하여 클리핑하는 축 평행 클리핑 존으로, 불필요한 픽셀 셰이더 작업을 피할 수 있습니다.

    • 복합 클리핑 존은 스텐실 버퍼를 사용하여 임의의 클리핑 존 스택을 스텐실 버퍼로 합쳐 넣은 뒤 드로 콜 클리핑에 사용합니다.

  • 이제 (기본적으로) 위젯 클리핑이 매우 적은데, 대부분 스크롤 패널과 편집가능 텍스트 칸으로 이루어집니다.

    • 렌더 트랜스폼은 더이상 "특수"하지 않으며, 어떤 트랜스폼이든 클리핑되지 않는 한 다른 위젯 외부 렌더링이 가능하기 때문입니다.

  • 슬레이트는 더이상 여러 클리핑 존에 걸친 일괄 처리가 불가능합니다. 이로 인해 슬레이트 버텍스 포맷의 플로트 6 개가 해제되어, 더이상 픽셀 셰이더에서 클리핑할 필요가 없습니다.

새 시스템은 축 평행이 아니어도 위젯 렌더 스페이스에서의 클리핑을 지원하므로, 시스템에서는 더이상 (왼쪽의) 클리핑 이슈를 걱정할 필요가 없으며, 그 대신 가장 바깥쪽 위젯을 클리핑합니다. 이제 내부 위젯에 적용되는 트랜스폼은 에지에서 제대로 클리핑이 일어납니다 (오른쪽).

ClippingOld.png

ClippingNew.png

4.16 이전 클리핑 및 트랜스폼

4.17 이후 에지에서 적용된 클리핑

자식에게 트랜스폼도 같이 적용

대부분의 경우, 위젯 스테이트 클리핑을 바꿀 걱정은 하지 않아도 됩니다. 게임 UI 를 고려하는 상황을 예로 든다면, UMG 에서 위젯을 조정할 필요는 정말 별로 없으며, 바꿀 일이 있다면 대부분 스크롤 패널같은 경우, 또는 에디터처럼 텍스트 길이를 제어할 수 없어 패널 일부나 창 크기조절용으로 클리핑을 해야할 경우 정도입니다.

ClippingExamples.png

다양한 클리핑 셋업으로 확인할 수 있는 예제 몇 가지입니다.

  • 왼쪽 - 버튼이나 텍스트에 클리핑이 켜져있지 않습니다.

  • 가운데 - 텍스트에 클리핑이 켜져있습니다.

  • 오른쪽 - 버튼에 클리핑이 켜져있습니다.

다양한 오브젝트에 클리핑이 적용되었을 때의 차이를 눈여겨 보십시오. 시스템에서는 바운드에 클리핑을 하고, 패딩같은 것은 개입되지 않으므로, 버튼에 클리핑하도록 설정된 경우 (오른쪽), 내용이 에지까지 이어지다가 잘리는 반면, 텍스트가 클리핑 처리를 담당하는 경우 (가운데), 버튼 콘텐츠 패딩같은 것을 기반으로 텍스트 클리핑이 일어나 텍스트가 들어갈 공간이 좁아집니다.

간단한 축 평행 클리핑 예제에 더해, 시스템에서는 임의의 클리핑 쿼드를 서로 위에 쌓는 것도 지원합니다.

TransformClipping.png

이 예제는 극단적이긴 하지만, 3D 트랜스폼과 프로젝션을 도입하려면 임의의 클리핑 존을 합칠 수 있어야 하는데, 프로젝션을 포함한 채 클리핑되는 위젯은 프로젝션 스페이스에서 클리핑이 일어나야 하기 때문입니다.

4.16 이전에서 4.17 이후로 변환 안내

4.17 의 슬레이트 클리핑 시스템 변화로 기존 버전과의 하위 호환성이 깨지므로, 아래 섹션을 참고하여 프로젝트를 업데이트해야 변환 문제를 피할 수 있고 프로젝트의 위젯을 디버깅하는 데 쓰이는 새로운 방법을 확인할 수 있습니다.

위젯 클리핑 활성화

모든 UMG 위젯에 대해 선택된 위젯의 디테일 패널에 위치한 Clipping 프로퍼티를 조절할 수 있습니다.

UMGClippingProperty.png

UMG UI 디자이너로 클리핑 문서 에서 자세한 내용을 배우실 수 있습니다.

코드에서 클리핑을 활성화시키려면, EWidgetClipping 에 대한 클리핑 프로퍼티를 다음 스테이트 중 하나로 설정하면 됩니다:

  • Inherit

  • ClipToBounds

  • ClipToBoundsWithoutIntersecting

  • ClipToBoundsAlways

  • OnDemand

코드 예제입니다:

SNew( SBorder )
.Clipping(EWidgetClipping::ClipToBounds)
[
    ...
]

폐기된 API

4.16 버전부로 폐기(deprecate)된 API 는 다음과 같습니다. 프로젝트에서 사용중이셨던 경우, 지금도 사용할 필요가 있는지 고려해 보세요. 모든 위젯이 클리핑되지는 않으므로, 클리핑 존 이동을 가능하게 하기 위해 클리핑 시스템을 속일 수도 있던 코드는 더이상 필요치 않을 것입니다.

  • FSlateDrawElement::Make___(...) - 더이상 모든 드로 콜에 클리핑 사각형을 전달할 필요가 없으므로, 함수 호출만 제거해 주면 자동으로 새 버전을 사용할 것입니다.

  • SScissorRectBox - 이제 모든 축 평행 클리핑 사각형은 가위 사각형이므로 더이상 필요치 않습니다. 얘들은 꼭 지우시고 직계 자손 위젯에 클리핑을 활성화시키는 것으로 그 작업을 대체해 주세요.

커스텀 클리핑

위젯 내부적으로 클리핑이 필요한 경우가 있습니다. 예를 들어, SProgressBar 는 진행상황에 따라 임의의 위치에 진행상황 막대를 클리핑할 필요가 있을 수 있습니다. 자체 클리핑을 추가하려면, OnPaint 에 다음과 같은 작업을 해주면 됩니다:

OutDrawElements.PushClip(FSlateClippingZone(AllottedGeometry));

//TODO 여기에 그리기 작업을 하거나, 자식 위젯 페인트 호출을 합니다.

OutDrawElements.PopClip();

FSlateClippingZone 는 Windows 스페이스의 임의 클리핑 영역으로, 초기화시키면 여러가지 메서드를 통해 기존 코드의 간단한 변환이 가능합니다.

커스텀 클리핑이 Hit Testing 에 영향을 끼치도록 할 필요도 있는 경우, 다음과 같은 구성으로 클리핑 존을 Hit Test Grid 에 푸시해 주어야 할 것입니다:

OutDrawElements.PushClip(FSlateClippingZone(AllottedGeometry));
Args.GetGrid().PushClip(FSlateClippingZone(GetCachedGeometry()));

//TODO 여기에 그리기 작업을 하거나, 자식 위젯 페인트 호출을 합니다.

OutDrawElements.PopClip();
Args.GetGrid().PopClip();

Hit Test Grid 에 대한 클리핑 사각형은 AllotedGeometry 대신 캐시된 지오메트리를 사용하고 있습니다. OnPaint 에서, AllotedGeometry 는 Windows 스페이스인 반면, Hit Test Grid 는 데스크톱 스페이스입니다. 그래서 Tick 시키려는 지오메트리를 사용해야 합니다.

래핑된 클리핑 스테이트

어떤 경우 클리핑 스테이트를 갖는 위젯이 클리핑을 담당하지 않습니다. 예를 들어 SScrollBox 는 다른 위젯처럼 클리핑 스테이트를 퍼블릭하게 변경하도록 해주지만, SScrollBox 가 생성되면 bClippingProxytrue 로 설정합니다. 즉 Slate 가 위젯을 렌더링하게 될 때, 클리핑 스테이트를 무시한다는 뜻입니다.

내부적으로 SScrollBox 는 다른 중첩 위젯에 클리핑을 해야한다 알리거나, 하라고 시킨 클리핑 스테이트를 처리합니다. 추가적으로 사용자가 클리핑 스테이트를 바꿀 때, SScrollBox SWidget 함수 OnClippingChanged 를 덮어써서 중첩 프라이빗 위젯에 새로운 클리핑 스테이트를 미러링하는 시기를 알려줍니다.

컬링 변화

클리핑이 렌더링 스페이스에서 이루어지기는 하지만, 엔진은 여전히 단순한 바운딩 박스를 사용하여 컬링을 합니다. 하지만 그 박스는 렌더 트랜스폼이 적용된 클리핑 존의 바운딩 박스를 기반으로 합니다. 추가적으로 클리핑과 컬링이란 것은 시간에 따라 미묘한 차이가 더욱 심해질 수 있으므로, 커스텀 패널이 있고 MyClippingRect.IntersectionWith 를 통해 그려지지 않을 확률이 있는 위젯을 알아내고 컬링하려는 경우, 이제 SWidget 함수 IsChildWidgetCulled 를 사용해야 합니다. 다음은 그 예제입니다:

for (int32 ChildIndex = 0; ChildIndex < ArrangedChildren.Num(); ++ChildIndex)
{
    FArrangedWidget& CurWidget = ArrangedChildren[ChildIndex];

    if (!IsChildWidgetCulled(MyCullingRect, CurWidget))
    {
        // 이 위젯을 페인트합니다.
    }
}

OnPaint 에서 MyClippingRect 를 받는 곳이면 어디든 MyCullingRect 로 이름을 변경해야 합니다.

클리핑 시스템이 변화되었어도, 슬레이트의 컬링 접근법은 변하지 않았습니다. 아래 예제에서는 부모 위젯(파랑)이 클리핑 존(초록) 밖에 있을 때 컬링된다면, 자식 위젯(노랑) 역시 부모 바운드 완전히 밖에 렌더링할 수 있도록 해주는 트랜스폼이 있다 할지라도 컬링된다는 점을 유의해야 합니다. 이것은 Clip to Bounds - Without Intersecting 클리핑 프로퍼티가 활성화되었을때도 마찬가지인데, 이 옵션은 직계 부모 위젯에서만 검사하기 때문입니다.

클리핑 존 외부에서 | 본 위젯.

클리핑 존 외부에서 | 컬링된 위젯.

클리핑 디버깅

Widget Reflector (위젯 리플렉터)는 에디터 안에서 선택된 위젯의 클리핑 스테이트를 표시합니다.

WidgetReflector.png

위젯 리플렉터를 사용하여 텍스트 블록을 선택, 클리핑 스테이트가 On Demand 로 설정된 것이 표시됩니다.

위젯 리플렉터 를 열려면 파일 메뉴 > > 개발자 툴 > 위젯 리플렉터 를 선택하면 됩니다.

에디터에서 위젯의 컬링 스테이트나 클리핑을 디버깅하는 데 사용할 수 있는 콘솔 변수는 다음과 같습니다:

콘솔 변수

설명

Slate.ShowClipping

활성화 시, 모든 축 평행 클리핑 사각형(Scissor Rect, 가위 사각형)에 노랑 윤곽선이, 모든 스텐실 클리핑 쿼드에 빨강 윤곽선이 표시됩니다.

이미지를 클릭하면 원본을 확인합니다.

Slate.DebugCulling

활성화 시, 패널의 컬링 작동 방식, 또는 왜 정상 작동하지 않고있는 이유를 파악하는 데 도움이 됩니다. GPU 에서의 클리핑은 비활성화시키고 모든 것을 보통처럼 진행시켜, 클립 존 바운드 밖에 렌더링되는 모든 것들과 예상대로 컬링되고 있는지를 확인할 수 있도록 해줍니다.

Slate.EnableDrawEvents

활성화 시, 드로 이벤트가 활성화되어 RenderDoc 등의 툴로 디버깅할 때 일괄 작업이나 클리핑 스테이트 트랜지션을 이해하기가 쉬워집니다. Debug 빌드를 사용하면 기본적으로 활성화되는 옵션입니다.

관련 토픽