언리얼을 공부하게 되니 유니티를 다룰 때는 관심이 없었던 머티리얼에 대해서 조금 더 깊이 있게 학습하는 느낌입니다.
오늘은 카툰셰이더 튜토리얼 영상이 있어서 한번 진행해 볼 생각입니다.
https://youtu.be/qSUCiWrjSBU?si=kKO0TnDRhQuMvrR5
해당 영상을 참고해서 진행했습니다.
다음처럼 완성하게 되었는데 강의를 보면서 따라 진행하다 보니 생각보다 이해하지 못한 노드가 많이 있어서 하나씩 분석해 볼 생각입니다.
해당 영상만으로는 위 사진의 모습까지만 진행이 가능해서 이왕 시작한 김에 조금 더 학습해 보기로 했습니다.
우선 위 영상에 나오는 머티리얼 그래프를 분석해 보겠습니다.
1. 기본 조명 계산
Main Lighting 노드와 관련된 흐름이 조명 방향과 표면 방향을 비교해서 밝기를 계산하는 부분
- Main Lighting (빨간색 노드)
- 광원의 방향벡터를 설정하는 노드
- 예시 → 태양이 어디서 비추는지 설정
- Normalize (정규화)
- 이 벡터를 정규화해서 길이를 1로 맞춤 → 방향만 필요하기 때문
- VertexNormalWS (버텍스 법선)
- 표면의 방향(법선)을 월드 스페이스에서 가져오는 노드
- 표면이 어디를 향하고 있는지 알려준다.
- Dot (내적)
- 빛의 방향과 표면의 방향 사이의 각도를 계산
- 결과값이 1에 가까우면 빛이 표면을 정면으로 비추고, 0이면 수직, -1 이면 반대 방향이다.
- Saturate
- 결과값을 0~1 사이로 클램핑 한다.
- 이걸로 표면이 빛을 받는 밝기를 나타낼 수 있다
- Multiply
- 이 값을 특정 숫자(1.5 같은 값)와 곱해서 라이트의 강도를 조절
2. 계단형 밝기 (카툰 셰이딩)
만화처럼 보이려면 표면 밝기가 부드럽게 변화하는 게 아니라 단계적으로 나눠져야 한다.
저는 이 부분을 구현하는 방법들 중에 3가지 방법이 있는 것을 확인하여서 모든 방법으로 구현해 보았습니다.
위 강의 영상에서는 IF문을 이용한 구현 방법을 사용하셨습니다.
2-1. if 문을 이용한 구현
if 노드를 사용하면 특정 값의 범위를 기준으로 조건에 따라 색상 분류 가능
- 장점: 조건을 자유롭게 설정할 수 있어서 다양한 상황에 맞게 유연하게 사용할 수 있다.
- 단점: 단계가 많아질수록 IF 노드가 반복적으로 늘어나서 그래프가 복잡해진다.
흐름
- Dot노드: 빛과 표면 법선의 방향을 비교해 0~1 범위의 값(밝기)을 가져온다.
- if 노드: 특정 Threshold 값을 기준으로 색상을 나눈다.
- if (Dot 값 ≤ 0.33) → 그림자 색상
- if (Dot 값 ≤ 0.66 → 중간 색상
- 그 외 값 → 밝은 색상
- 각 if 노드의 조건 결과를 색상에 연결한다.
결과
특정 조건에 따라 색상이 뚜렷하게 나누어져서 카툰 느낌을 살릴 수 있다.
2-2. Floor을 이용한 구현
Floor 노드를 사용하면 밝기 값을 계단형으로 나누는 효과를 간단하게 구현할 수 있다
- 장점: 노드 수가 적고, 단계를 추가하거나 수정하기 쉽다.
- 단점: 중간 단계의 색상을 따로 설정하기 위해서는 추가적인 Multiply나 Lerp가 필요하다.
흐름
- Floor 노드: 소수점 이하 값을 버려서 계단형으로 만든다. → 결과: 0, 1, 2
- Divide: Floor 결과를 단계 수로 나눠서 다시 0~1 범위로 맞춘다.
- Lerp(보간): 각 단계에 다른 색상을 연결한다.
결과
- 단계적으로 밝기만 나누어지면서도 깔끔하게 변경이 가능하다.
- Multyply 값만 바꾸면 단계를 쉽게 조정할 수 있다.
2-3. Step을 이용한 구현
Step 노드를 사용하면 특정 임계값(Threshold)을 기준으로 밝기 단계를 나눌 수 있다.
- 장점: 경계를 명확하게 나눌 수 있어서 카툰 셰이딩에 적합하다.
- 단점: 각 단계마다 색상을 적용하려면 추가적으로 Multiply나 Add가 필요하다.
흐름
- Stop 노드를 사용해 각 임계값(Threshold)을 설정한다.
- Step 1: Threshold = 0.33 → 0 또는 1
- Step 2: Threshold = 0.66 → 0 또는 1
- Multiply: Step 결과에 각 단계별 색상을 곱한다.
- Add: Multiply 결과를 모두 합산해 최종 색상을 만든다.
결과
- Step 노드를 통해 뚜렷하게 색상이 나뉘어 카툰 스타일의 명확한 명암 단계를 구현할 수 있다.
- Threshold 값을 조절하면 단계 수를 쉽게 늘리거나 줄일 수 있다.
3. 텍스쳐 샘플과 연결해 보기
이제 위에서 테스트로 구현한 툰셰이딩 머티리얼을 실제 사용할 캐릭터에 적용해 볼 생각입니다.
기존처럼 위에 방식으로 구현한 머티리얼들은 임시 조명으로 렌더링 된 상태여서 텍스쳐도 없고 밑밑하게 보입니다.
그리고 임시 조명으로 구현되다 보니 레벨에 있는 디렉셔널 라이트와는 관계없는 라이팅 모양이 형성되어 있습니다.
이 부분을 이제 제가 사용할 캐릭터의 텍스쳐를 가져와서 구현해 보도록 하겠습니다.
텍스쳐 샘플을 가져와서 적용하는 툰 셰이딩
1. 기존 조명 계산하던 부분을 약간 수정해서 캐릭터의 텍스쳐를 기본 베이스 컬러로 지정합니다.
2. 이번엔 If문을 활용해서 그림자 한계 값과 하이라이트 한계 값을 기준으로 그림자 텍스쳐, 메인 텍스쳐, 하이라이트 텍스쳐를 연결합니다.
이 부분에서 어떤 식으로 레벨의 색상 값에 맞는 그림자, 메인, 하이라이트 텍스쳐를 구해오나 했는데 생각보다 간단하게 정리되었습니다.
그림자 텍스쳐 → 메인 텍스쳐 * 0.7
메인 텍스쳐
하이라이트 텍스쳐 → 메인 텍스쳐 * 1.3
이렇게 정리 후 나온 값에 기존과 동일하게 아웃라인 셰이더를 연결해 주면 끝입니다.
최종 결과물
사실 뭔가 드라마틱하게 툰셰이딩이 들어갔다는 느낌은 안 들지만 그래도 원했던 결과는 나와서 다행이었습니다.
이 이상의 영역은 어떤 느낌의 툰셰이딩이 필요한지 기준이 있어야 구현이 가능할 것 같습니다.
그래도 기본 캐릭터와 움직이는 캐릭터(툰셰이딩)가 적용된 캐릭터는 약간 느낌이 달라서 만족합니다.
감사합니다.