| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
- SGPR
- GPU
- rendering
- Shadow
- shader
- scalar
- vulkan
- wave
- deferred
- atmospheric
- SIMD
- DX12
- optimization
- GPU Driven Rendering
- texture
- RayTracing
- scattering
- UE5
- Study
- Graphics
- DirectX12
- 번역
- forward
- Wavefront
- ShadowMap
- unrealengine
- Nanite
- ue4
- hzb
- VGPR
- Today
- Total
RenderLog
[번역][UE4]Rendering Wounds on Characters in UE4 본문
개인 공부용으로 번역한 거라 잘못 번역된 내용이 있을 수 있습니다.
또한 원작자의 동의 없이 올려서 언제든 글이 내려갈 수 있습니다.
출처 : https://www.tomlooman.com/rendering-wounds-on-characters/
이번주 초에 나는 캐릭터에 동적으로 생성되는 피와 상처를 보여주는 히트마스킹에 관해 트윗을 했었습니다. 오늘 그 효과와 어떻게 그것이 가능한지에 대해서 더 이야기 해보고 싶습니다. 나는 기술적인 디테일과 몇몇 대안에 대해서 이야기 할 것입니다. 효과는 컨셉의 증명과 렌더타겟을 사용하여 저렴한 텍스쳐 스플래팅(texture splatting)을 찾는 것입니다. 그럼 시작해봅시다.


우리게임에서 총알 효과와 피 자국과 같은 몇가지 데칼이 있습니다. 이 데칼은 데미지를 입은 캐릭터 뒤의 벽에도 표시됩니다. 이런 데칼은 명중한 컴포넌트에 붙여집니다, 그러나 만약 애니매이션 된 메시에 붙이려 시도하면, 데칼이 표면을 따라서 슬라이딩 되는 것을 알 수 있고, 보기에 좋지 않습니다. 나는 PlayerUnkonw's Battlegrounds the other day에 캐릭터에 전통적인 데칼을 사용하는 곳에서 이런 종류의 슬라이딩 되는 것을 발견했습니다, 그러나 더 안정적인 해결책은 계속해서 당신이 소유한 캐릭터를 보는 3인칭 게임에서 특별히 더 필요합니다. 문제가 발생한 곳에서 작은 데칼을 사용하여 문제를 눈치채지 못하게 합니다. 여기에 데칼슬라이딩 문제를 더 과정된 예제가 있습니다:

나는 이우리 캐릭터에 이 문제의 해결책을 찾으려 시도했으며 또한 찾길 원했습니다. 그리고 Sphere를 쉐이더에서 상처의 마스크 렌더타겟에 그리기 위해서 Material을 렌더타겟에 그리는 기술을 Ryan Bruck's GDC 데모에서 영감을 받았습니다. 여기에 Ryan's 렌더타겟기반 데미지의 구현이 있습니다:
이 효과는 우리가 얻고 싶은 부하정도 보다 너무 비쌉니다. 2개의 렌더타겟(장면에서 각 캐릭터에), 유니크 UVs를 가진 메시(UE4의 마네퀸은 이 예제에서 UV가 유니크하지 않습니다, 그래서 이 작업을 하기위해서 엔진 외부에서 수정해야 합니다. - 역주 : UV가 Mirrored 되지 않은 것을 유니크한 UV라고 하는 것 같네요.) 그리고 캐릭터가 맞았을때, 런타임에서 렌더타겟에 2번 그리는 것 때문에 히칭을 만듭니다. 렌더타겟에 2번 렌더링 하는것은 아주 비싼 연산입니다. (히칭이 발생하는 동안 수 밀리세컨드가 필요함). 만약 왜 2번의 렌더링이 필요한지 궁금하다면, 제가 설명해드리겠습니다.
첫번째는 렌더링은 간단합니다, 당신은 캐릭터 데미지 렌더타겟에 특정 표시를 그리길 원합니다. 그러기 위해서 SphereMask를 사용해서 "Hit" 픽셀을 찾아 렌더타겟에 그려줄 머터리얼, 그러나 이 머터리얼은 캐릭터의 픽셀 위치와 "Hit" 위치를 비교할 방법이 없습니다, 그래서 Ryan 은 애니매이션된 캐릭터의 각 픽셀의 WorldPosition을 두번째 렌더타겟에 기록합니다. 그것은 SphereMask 연산이 실행되는 동안에 샘플링 될 수 있습니다. 여기서의 문제는 픽셀의 월드포지션은 매 프레임 변경된다는 것입니다, 특히 애니매이션된 메시, 각각의 이것이 의미하는 것은 각각의 새로운 히트에서, 우리는 최종 렌더타겟에 표시를 그리기 위해서 먼저 두번째 렌더타겟을 WorldPosition을 업데이트 해야 한다는 것입니다. 우리의 경우 순수 시각적 효과를 위해서 효율적이지 않으며 더 싼 해결책을 찾을 필요가 있었습니다.
렌더타겟 접근의 최적화
이것을 최적화하는 한 방법은 최근에 추가된 pre-skinned local position node를 사용하는 것입니다. 이것은 World Position을 Pre-skinned local 위치를 써넣는 것으로 대체합니다. 이것으로, 우리는 오프라인에서 가능한 한번의 캡쳐만 요구되어집니다(이 위치는 런타임에 변경되지 않기 때문). 레퍼런스 포즈의 위치를 캡쳐하기 위해 Ryan의 unwrap 머터리얼의 변경과 블루프린트를 만들었습니다, 이것은 장면을 캡쳐하고 렌더타겟을 스태틱 텍스쳐로 변경합니다(애니매이션 된 버젼을 아래에서 볼 수 있습니다). 이것은 2번째 렌터타겟이 런타임에서 필요하지 않도록 해줍니다. 각각의 히트를 우리는 그것을 캐릭터에 적용하기 전에 히트 로케이션(월드 스페이스)에서 메시의 Pre-skinned 로컬 공간으로 변환합니다. 다음 섹션에서 나는 월드공간에서 Pre-skinned 공간으로 어떻게 변환시키는지 설명할 것입니다.

이 최적화는 비용을 제거합니다, 그러나 여전히 특별한 렌더타겟을 캐릭터를 위해 만들어야하는 것과 비싼 DrawMaterialToRenderTarget 연산을 매번 히트시에 처리해야하는 것은 즐겁지 않습니다. 나는 GTX850M(노트북)에서 히트당 1.6~4.5 ms 정도로 측정했습니다, 특히 그것이 단일 프레임에서 얼마나 많이 일어날지 컨트롤 되지 않는 상황에서 이 비용은 아주 비쌉니다. 이 효과는 순수하게 보여주기 위한 용도이고 렌더링 예산에 메인 비용이 되어서는 안됩니다.
대안 찾기
그래서 나는 렌더타겟을 완전히 제거하고 SphereMask 만으로 이 효과를 구현하였습니다. 이것은 히트의 수를 제한하도록 합니다, 당신이 Sphere mask를 추가한 후로, 쉐이더에는 고정비용이 추가됩니다. 여기에는 몇가지 최적화가 있습니다, 아직 아무런 히트가 없다면 브랜치와 같은 것으로 Sphere mask 비용을 제거 하거나 히트를 받기 전까지 쉐이더를 교체하는 것입니다. 우리의 예산에서 여전히 잘 동작하기 때문에 이 작업이 쉐이더에서 필요하지 않습니다. 첫번째 히트에서 적이 죽을 수도 있기 때문에 (그렇지 않다면 당신의 보스 캐릭터에 대해서 이야기 하는 것임) 나는 3-5 히트 정도는 추가적인 히트면 괜찮다는 것을 생각했습니다, 이것은 시작점의 발판이 되었습니다.
원본 렌더타겟 효과같이, Sphere mask를 애니매이션 된 메시와 일관성있게 동작하게 하기 위해 우리는 Reference pose를 Sphere mask를 두기 위해서 사용할 필요가 있습니다. 캐릭터를 맞췄을때, 우리는 히트된 월드 위치를 Ref pose 위치로 변환합니다 (Point Damage Event 로 부터 얻은 본의 이름을 사용하여) 당신은 역시 먼저 히트 위치를 현재 본의 현재변환으로 부터 역변환 하여 이것을 할 수 있습니다, 그리고나서 그것과 같은 본의 Reference pose 변환을 사용하여 역변환한 해온 위치를 변환합니다.

이것이 히트 위치(녹색)과 현재 포즈의 변환 그리고 히트된 본에 변환이 적용된 것을 시각화한 것입니다. 그리고 파랑색 선이 레퍼런스 포즈 변환과 일치하는 것입니다. 보락색 선은 차이를 보여주는데 도움을 줍니다.

레퍼런스 포즈 예제에서 (두 이미지 중 아래), 히트 위치는 이미 올바른 공간에 있습니다, 그래서 파란색과 녹색 선이 겹쳐져 z-fighting 을 볼 수 있습니다. 심지어 그들은 정확히 일치하는 offset 때문에 보라색 선이 없기 때문에 차이를 시각화할 것이 없습니다.
위의 이미지에서 원래의 히트 위치에서 우리의 레퍼런스 포즈 로케이션으로 이동시키는지 봤습니다. 이제 우리는 움직이지 않는 일정한 위치를 가지고 있습니다, 우리는 Pre-skinned 위치와 Sphere mask를 사용하는 쉐이더에 이 위치를 넣습니다. 여러개의 히트를 지원하기 위해서, 우리는 새로운 히트가 발생되면 파라메터 이름을 각각 마다 증가시켜줍니다. 즉, HitLocation_1, HitLocation_2 (이것은 사전에 머터리얼에 있어야 함)
피를 애니매이션 시키기
Sphere mask 가 렌더타겟에 비해 좋은 점은 우리는 계속해서 렌더타겟에 그림을 그리는 것과 같은 엄청난 비용을 추가하지 않고도 여전히 시간의 흐름에 따라서 데이터를 수정할 수 있다는 것입니다. 예를들어, Sphere mask의 scale로 피가 캐릭터의 옷을 통해 퍼져나가는 효과 같은것은 아주 간단합니다.
또 다른 추가해야할 멋진 기능은 입은 데이미지에 따라서 크기를 조절 하는 것, 충분한 시간이 흐른뒤 시간에 따라 피가 말라가거나 충분한 시간이 지나서 상처가 치유되는 것을 상처가 사라지는 것을 추가하는 것입니다.
결론
시각적으로 개선할 여지는 많이 있습니다, 그러나 기본 기술은 확실합니다. 나는 위의 예에서 HeightLerp를 SphereMask로 부터 얻은 간단한 Spherical 모양과 비교해 더 나은 fall-off을 보여주기위해서 추가했습니다.
이 기술은 히트의 수에 제한이 있으며, 원래의 기능에 비해서 더 일정한 비용을 가집니다. 우리는 적(Enemy) 당 렌더타겟이 필요하지 않고 히칭이 유발되는 비용을 이 기능을 컨트롤하는 몇개의 머터리얼 파라메터를 설정하므로써 가지지 않습니다. 렌더타겟을 사용하는 것은 여전히 가능한 접근법입니다, 그리고 런타임 코스트에 문제가 되지 않는다면 캐릭터 상태를 게임플레이 동안 극단적으로 변경할 수 있는 좋은 방법입니다. 나는 더 이야기 할 것이 많다고 느낍니다, 상처를 제거와 같은, 메시 변형 등등! 그러나 이것은 아마 다음 시간에 도달 할 부분입니다...
나는 이 포스트가 당신에게 영감을 주길 바랍니다! 질문은 아래의 코맨트로 남겨주시거나 follow me on Twitter 에 남겨주세요.
References
- ShaderBits’ GDC Demos (GitHub unofficial download)
- Left 4 Dead Wound PDF
'Graphics > 참고자료' 카테고리의 다른 글
| [번역]Tile-Based Rendering (0) | 2020.06.25 |
|---|---|
| [번역]Life of a triangle - NVIDIA's logical pipeline (0) | 2020.06.21 |
| [번역]Gaussian Smoothing (0) | 2020.06.06 |
| [번역][Nvidia White Paper] Volume Light (0) | 2020.05.28 |
| [번역] Forward+ : A Step Toward Film-Style Shading in Real Time (0) | 2020.05.17 |