에픽게임즈 코리아(대표 박성철)는 언리얼 엔진의 최신 기술 및 정보를 개발자들과 공유하는 국내 최대 규모의 언리얼 엔진 컨퍼런스인 서울(Unreal Summit 2018 Seoul, 이하 언리얼 서밋 2018)'을 오늘(18일), 서울 코엑스 그랜드볼룸과 컨퍼런스룸(북)에서 진행했다.

이날, 엔씨소프트의 신인종 테크니컬 아티스트는 식생 머티리얼에서 사용하는 다양한 머티리얼 기능을 청중에게 공유했다. 전달의 편의성을 위해 강연자 시점으로 서술한다.

▲ 엔씨소프트 신인종 테크니컬 아티스트

게임 작업에서 식생은 ‘무서운 것’이다. 자연물을 많이 그려야 하는 상황에서 렌더링을 멋지게 하면서도 버텍스도 줄여야 한다. 또한, 흔들려야 하며 캐릭터 움직임에도 반응해야 한다. 그래서 할 일이 대단히 많다. 언리얼 엔진에는 식생 머티리얼에서 사용하는 다양한 머티리얼 기능이 있다.


1. 양면렌더 활용하기

나무를 그릴 때 가지와 잎이 분리된 활엽수이면서 앞면 뒷면이 명확한 모델링이면 이러한 걱정을 할 필요도 없다. 그런데 이런 경우는 거의 존재하지 않는다. 만약 이렇게 만들면 속된 말로 욕먹는다. 실제 게임에서 쓰기는 힘들기 때문이다. 그래서 보통 십자모델을 사용하거나 잎과 나뭇가지를 한 면에 욱여넣는 경우가 많다.


보통 투사이드사인(TwoSideSign)노드를 사용하곤 한다. 이 노드는 앞면을 그릴 때는 1, 뒷면을 그릴 때는 -1을 넘겨주는 기능을 한다. 언리얼 엔진 문서에는 양면 커스텀 라이팅 머티리얼 뒷면의 노멀을 뒤집어 Phong과 같은 기능을 내도록 하기에 좋은 표현식이라고 적혀있다. 그런데 이렇게 하면 역광일 경우 뒷면에 볼록한 느낌이 나지 않아 이상하게 느껴진다.

역광에 뒷면까지 볼록하게 표현하려면 양면렌더를 활용하면 된다. 버텍스 노멀 방향은 유지하고 탄젠트와 바이노멀만 투사이드사인에 곱해 뒤집어 주면 된다. 이러면 어색함이 사라진다. 보통 게임에서 많이 사용하는 사슬은 일일이 모델링 할 수 없어 십자 모델로 많이 하는데 이를 탄젠트와 바이노말에다가 투사이드사인만 곱해주면 손쉽게 어색함을 없앨 수 있다.

▲ 좌우가 볼록함이 다름을 확인할 수 있다.


2. 하이트 블렌드로 레이어 섞기

나무기둥에 이끼나 흙을 섞는 경우가 있다. 그런데 그냥 버텍스 컬러로 섞으면, 선형보간(Lerp)로 섞으면 흐리멍덩해진다. 만약 중간경계 등을 디테일하게 표현하고 싶으면 하이트(Height) 블렌드로 섞으면 좋다.

우선 하이트 맵을 준비한다. 만약 레이어를 두 개 섞어야 하는데 둘 다 하이트 맵을 가지고 있다면 윗레이어의 높이맵과 아래 레이어의 높이맵을 반전하면 된다. 이를 통해서 디테일하게 풀의 모양을 살려줄 수 있다. 실제로는 아래에서 위로 그라디언트로 섞고 있는 건데 눈에 보이는 건 이처럼 디테일하게 보인다.


만약, 풀리지로 뿌릴 때 랜덤하게 뿌리고 싶으면 PerlnstanceRandom 이라는 노드를 활용하면 된다. PerlnstanceRandom은 머티리얼이 적용된 스태틱 매시 인스턴스마다 다른 랜덤 실수값을 출력하는 표현식으로, InstancedStaticMeshComponent는 인스턴스에 임의의 실수값을 설정하여 원하는 대로 사용할 수 있도록 한다. 인스턴스마다 블렌드 웨이트를 조금씩 다르게 하여 랜덤으로 표현할 수 있다.



3. 라이트매스 트릭

빛이 어떤 물체를 투과할 때, 이를테면 나뭇잎을 투과해서 땅에 그림자가 질 때 현실에서는 그림자가 옅게 나온다. 그런데 언리얼엔진의 실시간 그림자에서는 이를 표현할 방법이 없다. 다만, 라이트매스를 구울 때만 값을 바꿔치기해서 표현할 수는 있다.


라이트매스 리플레이스는 보통 렌더링 용도로, 머티리얼을 컴파일할 때는 리얼타임 입력을 통과시키고 글로벌 일루미네이션 용도로 머티리얼을 라이트매스로 익스포트할 때는 라이트매스 입력을 통과시키는 표현식이다. 실제로는 알파 값이지만, 디더링을 불러서 할 수 있다. 이를 통해 실제와 비슷한 결과물을 얻을 수 있다. 덤으로 셀프 섀도우도 옅어진다.

라이트매스는 다양한 곳에 활용할 수 있다. 창문의 먼지, 그림자 라든지 커튼 그림자처럼 투과할 수 있는 곳은 모두 활용 가능하다. 다만, 바닥이 너무 깨끗하면 디더링이 티가 나므로 주의해야 한다.



4. 캐릭터가 지나가면 눕는 풀

일반적으로 풀이 눕는 것을 표현하기 위해서는 버텍스 옵션을 사용한다. 그런데 캐릭터 위치값을 얻어와서 자기 피벗값과 비교하는 것이기 때문에 온라인 게임처럼 여러 개의 값이 필요한 경우 문제가 생긴다. 그래서 온라인게임 같은 경우 RTT(RenderToTexture)를 이용해서 다수의 캐릭터에 의해 눕는 풀을 구현할 수 있다.

▲ 한 명이면 간단하지만...

RTT는 게임 중 실시간으로 텍스처에 그리는 방법으로 텍스처에는 복수의 데이터를 저장할 수 있다. 이를 구현하기 위해서는 렌더타겟 텍스처, 렌더 타겟에 그릴 머티리얼, 컴포넌트 블루프린트가 필요하다. 또, 풀 머티리얼에 쓸 함수도 필요하다.

렌더타겟 텍스쳐는 그냥 브라우저에 생성하면 된다. 이후 머티리얼을 준비한다. 기본 개념은 캐릭터 기준으로 미는 방향을 기록해 풀을 눕히는 것이다. RTT는 벡터라 마이너스도 기록되므로 음수를 직접 기록할 수 있도록 RTTRG16F를 선택한다.


렌더 타겟 머티리얼을 준비했으면 컴포넌트 블루프린트를 작성한다. 준비한 렌더타겟을 Bigin Draw Canvas to Render Taget에 집어넣는다. 렌더타겟에 그릴 머티리얼도 추가한다. 원하는 클래스에 컴포넌트를 추가하면 된다.


풀 머티리얼 함수는 미리 준비된 렌더 타겟에 샘플링하면 된다. 자기 피벗에 있는 위치를 가지고 렌더 타겟을 샘플링해서 버텍스로 밀어주는 거다. 그리고 풀 머티리얼에 함수를 추가 하기만 하면된다. 뿌리는 움직이지 않게 웨이트를 줘야 한다. 이렇게 하면 여러 캐릭터가 돌아다녀도 각각 자기 컴포넌트를 가지고 렌더 타겟을 그리게 된다.