
입체감을 표현하는 효과 넣기
Tutorial
intermediate
+10XP
25 mins
Unity Technologies
평면적인 느낌을 넘어 스프라이트 객체에 입체감을 더해주는 Normal을 다루는 차시입니다.
1. 노멀맵 소개
3D 객체의 표면을 더욱 세밀하게 표현하기 위해 고안된 것으로 매쉬에 NormalMap 노멀맵 텍스쳐를 추가하여 빛에 반응하는 입체감 있는 표면을 만들 수 있습니다. 오로지 물리적인 폴리곤으로 세밀함을 표현하면 CPU, GPU 연산은 물론 메모리에도 부담이 가기 때문에 이러한 노멀맵을 사용한 3D 객체 표현은 오래전부터 꾸준히 사용되어 오고 있습니다. 노멀 맵에 대한 자세한 정보는 아래 가이드 및 유니티 코리아 유튜브 채널에서 확인할 수 있습니다.
유니티 엔진이 계속 진화해가면서 이제 2D 스프라이트에도 노멀맵을 활용할 수 있게 되었습니다. 그 방법 또한 이번 시간에 함께 알아보도록 하겠습니다.
2. 픽셀아트 노멀맵 제작하기
일반적으로 텍스쳐는 해상도가 크기 때문에 노멀맵 또한 이에 맞추어 큰 해상도에서 제작됩니다. 하지만 픽셀아트는 매우 작기 때문에 기존 방식을 그대로 사용하면 상당히 어긋난 결과물을 얻게 됩니다.
다행히 Aseprite 프로그램 기준으로 자동으로 노멀맵을 생성하는 플러그인 ( #mooosik's normal-toolkit , #securas's Edge Normals ) 이 몇몇 존재합니다. 픽셀아트 특성상 3D 와 다르게 직접 제작할 수 있습니다. 다만 이 작업을 위해서는 각 방향에 맞게 색상을 칠할 수 있도록 가이드 이미지가 필요합니다. 이것 또한 이 프로젝트에 포함되어 있으며, Sprites > Props 폴더에 Sample_Normal 스프라이트로 확인할 수 있습니다.
입체적인 구체 표면을 노멀 맵으로 나타내면 이렇게 표현할 수 있습니다. 그 중 평면과도 같은 부분은 한가운데의 연보라색입니다. 이 색상표를 참고하면 해상도가 낮은 픽셀 아트에서 직접 노멀맵을 그릴 수 있는데 예시로 Scene에 배치되어 있는 Block을 들 수 있겠습니다.
3. 노멀맵 적용하기
유니티에서 노멀맵을 적용하는 방법은 Emission과 마찬가지로 원본 스프라이트의 Secondary Texture로 등록하는 것입니다. 노멀맵은 Secondary Textures의 드롭다운 기본 항목에 _NormalMap으로 존재하므로 더욱 손쉽게 추가할 수 있습니다.
Witch 객체를 좀 더 조명에 가까이 옮겨봅니다. 하지만 그럴싸한 입체감은 표현되지 않는데요. 이것은 Light 2D이 Normal Map을 반영하도록 추가 설정이 필요하기 때문입니다. 모든 Spot, Sprite Light 2D에서 Normal Maps > Quality를 Accurate로 설정합니다. 낮은 해상도의 픽셀아트 특성상 정확한 노멀맵 반영이 필요하기 때문입니다.
Witch 객체의 마법사 모자 부분을 보면 노멀맵을 따라 경계에 명암이 바뀐 것을 확인할 수 있습니다. 하지만 이것만으로는 효과가 부족한 느낌이고 더군다나 기존에 잘 비추던 조명이 더 어두워진 것을 볼 수 있습니다.
우리는 노멀맵의 효과의 증폭과 함께 무너진 조명을 다시 복구할 작업이 필요합니다.
4. Rim Light로 전환하기
일부 고해상도 2D 프로젝트는 이러한 볼륨감을 위해 노멀맵을 사용하지만 픽셀 아트는 오히려 이질감을 느낄 수 있습니다. 반대로 화려한 2D 라이팅을 픽셀 아트 객체에 잘 반영할 수 있도록 외각을 따라 테두리 광원이 나타나는 Rim Light를 사용하는 사례가 많습니다. 그렇기 때문에 노멀맵을 림 라이트로 전환해보겠습니다.
- 기존 Sprite Light 2D 객체의 Normal Maps > Quality를 None으로 원상복구
- 해당 객체를 Ctrl+D로 복사 및 Rim Light로 이름 변경 (기존 객체는 비활성화)
- Light Type을 Spot으로 변경하고 Radius > Outer를 기존 조명 영역보다 더 크게 확장
- Intensity를 10 이상 높게 설정
- Normal Maps > Quality를 Accurate로 변경
- Normal Maps > Distance를 1 이하로 설정
이렇게 하여 새로운 Rim Light 객체가 추가되고 Witch 객체에는 더욱 뚜렷한 테두리 조명을 얻게 됩니다. 하지만 아직 무너진 조명은 해결하지 못했는데 지난 차시에서 다루었던 Target Sorting Layer를 활용하면 쉽게 복구할 수 있습니다.
- Rim Light의 Target Sorting Layer 는 Default만 설정
- 기존 Sprite Light 2D를 다시 활성화
- Rim Light를 Sprite Light 2D의 자식 객체로 등록하기
림 라이트는 보통 강조하려는 동적인 대상에 부여하기 때문에 이러한 객체들이 사용하는 정렬 레이어만 대상으로 삼는 것이 포인트입니다. 기존 Sprite Light 2D는 그대로 배경과 전경 모두 적용하거나 분위기, 상황에 따라서 배경만 대상으로 삼아도 좋습니다. 이런 방식으로 다른 Spot Light 2D도 Rim Light를 추가 생성합니다.
이로서 화려한 조명은 받는 2D 픽셀아트 장면이 만들어졌습니다. 하지만 이렇게 많은 Light 2D를 마음껏 사용해도 괜찮을까요?
5. 불필요한 배치를 줄여 최적화 하기
혹시 모르니 성능을 확인하기 위해 Frame Debugger를 펼쳐봅시다.
자세히 들여다보면 한 프레임에 Batch 수는 무려 134나 되는 것을 볼 수 있고 (처음 시작하기 전에는 16 밖에 되지 않았습니다.), 그림자를 그리는 단계인 Shadow2D UnsafePass에서 상당한 비중을 차지하고 있는 것을 확인할 수 있었습니다.
Batch란 CPU가 GPU에게 그래픽을 그리도록 명령하는 절차를 말합니다. 이 수가 많을 수록 CPU와 GPU 간의 데이터 통신이 잦아지면서 부담이 가중되기 때문에 Batch 수는 최적화의 척도라고 할 수 있겠습니다. Batch에 대한 기본기는 유니티 코리아의 유튜브 채널 영상을 참고하세요.
지금은 모든 Light 2D가 그림자를 생성하므로 조명이 겹치는 영역에 Shadow Caster 2D를 가진 객체가 진입하면 필요한 연산이 곱셈으로 증폭되는 상황입니다. 그러므로 불필요한 그림자 연산을 줄이기 위해 최적화 작업이 필요해보이네요.
- Witch의 Shadow Caster 2D에서 Target Sorting Layers를 Background만 지정
- Mineral의 Shadow Caster 2D에서 Target Sorting Layers를 Background만 지정
- 모든 Rim Light의 Light 2D에서 Shadows 속성을 체크 해제하여 비활성화
- 중요도가 낮은 Block 객체의 Shadow Caster 2D 비활성화
이 작업을 통해 거의 절반 이하 수준의 Batch를 아낄 수 있게 되었습니다. 이처럼 그래픽스 요소를 추가할수록 최적화에 신경써야 한다는 점 잊지 마시길 바랍니다.