(이 포스팅은 2023.11.08에 리뉴얼 하였습니다.)
▎이론편
우리가 노멀맵을 사용하여 프로젝트를 진행하는 경우 대부분 tangent space 또는 mikktspace를 사용합니다. 내가 무엇을 사용하는지 잘 모르겠다고요? 100% 일치하는 것은 아니지만 대부분 유니티는 tangent space를, 언리얼은 mikktspace를 사용하고 있을 확률이 큽니다.
1. mikktspace normal 알아보기
미켈슨 탄젠트 스페이스 노멀(Mikkelsen tangent space normal)은 제작자인 Morten Mikkelsen 이름을 따서 만든것으로 기존 tangent space의 문제점들을 보완한 시스템입니다. 자세한 것은 여기서 확인할 수 있습니다.
2. 왜 mikktspace를 사용해야할까?
여러 이유가 있지만, 그중에서도 가장 큰 이유는 아티스트 입장에서만 바라본다면 노멀맵을 사용하여 더욱 정확하게 하이폴을 흉내 낼 수 있기 때문이라고 생각됩니다. "다른 이유로는 최적화에 적합해서", "이제는 DCC 툴도 mikktspace를 기본적으로 지원해서"가 있습니다.
3. mikktspace를 활용한 버텍스 최적화
mikktspace는 로우폴 메쉬가 스무딩 그룹으로 인하여 굴곡진 쉐이딩이 되어도 원하는 표면으로 보정해줄 수 있다는 장점이 있습니다. 이것을 활용하여 엔진에서 극단적으로 버텍스를 줄일 수 있게 되었습니다. 엔진에서는 DCC와 다르게 UV를 포함하여 버텍스를 카운팅하고 있습니다. UV 전개 방식과 스무딩 그룹에 따라서 버텍스의 갯수가 달라집니다.





▎실전편
1. mikktspace 어떻게 사용하면 좋을까?
리뉴얼 전 포스팅에서는 스무딩 그룹을 1로 만들고 하이폴 라운딩 박스를 베이크 하는 방법을 다루었는데, 시간이 지날수록 저의 의도와는 다르게 해석되기도 하고, 언리얼 엔진 5가 보편화되었고, 저의 실전 경험도 많이 늘어나서 이번에는 다르게 적어보려 합니다.
먼저, 스무딩 그룹을 1로만 만든 다음 베이킹을 한 노멀맵을 사용하면 크게 두 가지 문제가 있습니다. 첫 번째는 노멀맵 편집이 어렵다는 것. 실무에서도 노멀맵 베이크를 한번에 끝내고 바로 텍스처링 작업을 들어가면 좋겠지만, 포토샵 또는 서브스턴스 페인터로 노멀을 수정하는 경우가 꽤 있습니다. 이런 상황에서 이미 굴곡진 노멀맵을 수정하기란 참 어렵습니다. 플랫한 바탕에 나사와 같은 일부 노멀을 수정하는 것은 쉽지만 이미 굴곡진 바탕에 또 다른 무언가를 얹거나 수정하기란 거의 불가능에 가까운 작업이 되어 버립니다. 두 번째는 LOD에서 효과를 보지 못합니다. 이미 LOD0에서 메쉬에 스무딩 그룹으로인해 쉐이딩이 굴곡되어서 그것을 보정하느라 노멀맵에도 보정값이 들어갔는데, 메쉬가 더 단순해지면 메쉬의 쉐이딩은 또 다르게 변하기 마련입니다. 그러면 변형된 왜곡에 보정된 노멀맵이 더해서 쉐이딩은 엉망이 되어버립니다.
그리하여 이러한 문제를 해결하기 위해서 다시 돌고돌아 "노멀맵을 최대한 플랫하게 사용하자"라는 기조로 돌아오게 됩니다. 그렇다고 다시 예전처럼 무작정 스무딩 그룹을 나누어 컷팅하느냐? 그것은 아닙니다. 폴리곤을 조금 더 늘리더라도 최대한 스무딩 그룹을 적게 쓰되, 필요하다면 Weighted Normal 기능을 활용하여 버텍스 노멀의 방향을 수정하는 것입니다. (사실 이것은 개인의 취향이긴 합니다.)
첫 번째로 이전 포스팅에서 예시를 들었던 라운딩 박스의 경우입니다. 스무딩 그룹을 1로 만든 로우폴 박스를 폴리곤을 조금 더 추가하여 쉐이딩 굴곡을 줄이고, Weighted Normal로 버텍스 노멀을 조정하여 큰 면들을 플랫하게 만들어 쉐이딩 굴곡을 한 번 더 줄였습니다. 이 방법은 폴리곤이 조금 더 늘기는 했으나 노멀맵을 플랫하게 베이크할 수 있고, 위 두 가지의 문제점을 해결할 수 있습니다.



두 번째로 의상과 같이 얇은 두께가 있는 부분을 표현할 때의 경우입니다. 스무딩 그룹을 1로 만들면 두께를 준 면의 영향으로 끝에 해당하는 면들이 쉐이딩이 왜곡되어 검게 나타날 때가 있습니다. 두께에 해당하는 면을 더 세분화하는 방법도 있지만 이번에는 그대로 폴리곤 수를 유지하면서 문제를 해결해 보겠습니다.

이 경우엔 앞면의 엣지를 미세하게 살짝 올립니다. 이러면 베이킹도 두께감 표현이 잘 묻어나올 뿐더러 로우폴의 왜곡을 완화시켜줍니다.


그다음 뒷면은 엣지를 선택하여 스무딩 그룹을 나눕니다. 어짜피 뒷면의 UV는 따로 펼치기 때문에 나눠야 하고, 스무딩 그룹을 나눠도 뒷면까지 보이진 않기 때문에 룩에는 크게 영향을 끼치지 않기 때문입니다.


마지막으로 Weighted Normal까지 주면 버텍스 노멀의 정리는 깔끔하게 이루어집니다. 아래는 솔루션 전후의 차이입니다.


세 번째는 자원이 한정적일 때 스무딩 그룹 나누기입니다. 또 다시 등장하는 라운딩 박스. 번외로 라운딩 박스가 밑면을 보여주지 않는다면, 밑면을 과감히 제거하는 방법도 좋은 선택지 중에 하나입니다. 다시 돌아와서 라운딩 박스의 로우폴을 최대한 스무딩 그룹을 적게쓰고 쉐이딩 왜곡이 없이 만들려면 저라면 이렇게 반반씩 나눌 것 같습니다. 왜곡을 한쪽 방향으로만 주는 것이지요. 물론 UV도 이렇게 펼쳐지겠지요.


비슷한 경우로 사다리꼴 형태의 작은 하드섭 부품을 만든다면 이런 식으로 스무딩 그룹을 나누어 왜곡을 최소화합니다.



사실, 주저리 주저리 써놓았지만 이러한 문제는 폴리곤을 넉넉히 쓰면 모두 해결되는 일입니다. 언리얼 엔진5에는 나나이트 기능이 생기면서 상호작용이 없는 스태틱 메쉬는 폴리곤을 충분히 사용할 수 있게 되었습니다. 스태틱 메쉬 한정이긴 하지만 나나이트를 사용할 수 있으면 최대한 활용하는 것이 좋습니다.
2. DCC에서 FBX 내보내기
우선 스무딩그룹이 의도한 대로 구성되어 있는지 확인합니다. 그리고 UV는 최대한 쪼개지 않도록 주의하여 언랩을 합니다. 덩어리들이 붙어 있을수록 엔진에서 연산되는 버텍스의 수는 줄어듭니다.
그다음 삼각면을 만들어 주고 FBX로 저장해야 하는데, 삼각면으로 만드는 이유는 엔진에 따라 사각면 속에 삼각면이 다르게 표시되는데, 베이킹 했을 때와 엔진에 넣었을 때 삼각면의 방향이 달라지면 노멀맵은 베이킹 했을 때의 삼각면에 맞춰서 베이크 되었기 때문에 엔진에서는 표면이 울게 됩니다.
삼각면을 만들 때 export 옵션에서 Triangulate를 체크하고 파일로 저장해도 되지만, 되도록 모디파이어를 활용하여 직접 삼각형으로 변환하는 것을 추천합니다. (블렌더에서는 Keep Normals 옵션에 체크 필수)


이렇게 작업을 진행하는 이유는 이 데이터를 가지고, 서브스턴스 페인터에서 텍스처링 작업에도 사용하고 엔진에 올리는 최종 메쉬로도 사용하기 때문입니다.(간혹가다 베이킹 메쉬와 최종 메쉬의 형태가 다른 경우가 있습니다.)
블렌더는 디폴트 세팅이 mikktspace로 되어있습니다. 추가 설정 없이 Geometry 패널에서 Smoothing을 Face로 변경하고 익스포트합니다.

3ds max 또는 maya의 경우 FBX export 옵션에서 Tangents and Binormals를 체크 해제하고 익스포트합니다.

3. Substance Painter에서 베이킹 방법
Substance 공식 문서에는 프로젝트에 따라 Tangent Space를 설정하라고 나와있습니다. 서브스턴스 프로젝트를 생성할 때 Compute tangent space per fragment 옵션을 체크/체크 해제합니다. 즉, Unity 기본 쉐이딩을 사용하는 프로젝트에는 체크를 해제하고, UE4나 Unity HDRP, 블렌더를 사용하는 프로젝트에는 체크하고 프로젝트를 생성합니다. 잘 모르겠다 싶으면 Template을 이용해주세요.

4. 언리얼 엔진에서 FBX 가져오기
이미 언리얼 엔진은 기본값으로 mikktspace가 설정되어있습니다. 하지만 옵션이 제대로 설정되었는지 보려면 메시 패널을 확장하고 Normal Generation Method가 MikK TSpace로 되어있는지 확인합니다.

참고한 사이트 : bgolus.medium.com/generating-perfect-normal-maps-for-unity-f929e673fc57