티스토리 뷰
이 포스팅은 '대마왕의 유니티 URP 셰이더 그래프 스타트업'을 학습하고 개인 학습용으로 정리한 내용입니다.
NPR 렌더링이란?
Non- Phot Realistic 렌더링이란, 사실적이지 않은 렌더링 방식입니다. 지금까지 공부했던 PR과는 정반대의 의미에요.
오늘은 대표적인 NPR 셰이딩인 툰 셰이딩을 해보려고 합니다.
툰 셰이딩하면 보통
1. 외곽선이 있다
2. 음영이 끊어져 있다
의 성질을 띄고 있어요. 오늘은 이 두 가지 중에서 외곽선을 구현해보도록 하겠습니다.
1. 외곽선 만드는 방법들
대표적으로 3가지 방법이 있습니다.
- 2Pass
- Fresnel
- 포스트 프로세싱
| 종류 | 설명 | 장점 | 단점 | 성능 |
| 2Pass | 같은 메쉬를 한 번 더 크게 그려서 단색으로 칠함. | 실루엣 라인이 선명, 안정적. 재질/라이팅과 독립. 두께를 오브젝트별로 제어 쉬움 |
드로우콜 1회 증가 얇은/열려있는 지오메트리에서 깨짐. 거리 따라 두께 변동 |
중~보통 (오브젝트 수에 비례) |
| Fresnel | 가장자리만 밝히거나 어둡게 칠해 윤곽 느낌을 만듦 | 구현 간단/저비용 투명 재질에도 적용 쉬움. |
진짜 선이 아님(실루엣 밖으로 안 나옴). 오브젝트 간 경계선 못 잡음. 노멀/시점에 따라 두께 들쭉날쭉 |
낮음 |
| 포스트 프로세싱 (스크린 스페이스 엣지) |
화면 전체의 Depth/Normal 기울기로 에지 검출 후 선을 그림 | 화면 픽셀 기준 두께라 거리 무관하게 일정. 오브젝트 간 경계·내부 주름까지 잡음. 씬 전역 적용 쉬움 |
무거움. 투명물은 추가 처리 필요. 오브젝트별 제외/색 분기에는 스텐실·레이어 세팅 필요 |
보통~높음 (해상도 의존) |
이 중에서 2Pass로 외곽선을 만들어 보겠습니다.
2. 외곽선 만들기
1) 면 확장하기
2Pass를 사용하려면 오브젝트를 한 치수 더 크게 만들어줘야 합니다.
버텍스 셰이더로 각 버텍스의 노말 방향으로 크기를 조금씩 더해주면 됩니다.

Scale 이라는 Float 변수를 지정해서 수치에 변화를 주면

이렇게 오브젝트가 부풀어오릅니다 ㅎㅎ
2) 면 뒤집기
2Pass로 외곽선을 만드려면 면을 뒤집은 뒤에 확장시켜야 합니다.
면을 뒤집는다는 것은 앞면만 보이는 렌더링을 끄고 뒷면만 보이게 하는 거라네용
렌더페이스 설정을 Front에서 Back으로 바꿔줍니다!


베이스 컬러도 검정색을 지정해줍니다.

그림자는 이렇게 준비가 됐어요

이제 원본 오브젝트를 위에 겹쳐주면

짠~
3. Render Feature 를 이용해서 외곽선 추가하기
2Pass는 두 번 그려서 외곽선을 표현해주는 방법이라 2배 무거워진다는 단점이 있습니다.
이번엔 SRP의 기능인 Render Feature를 사용해서 만들어보겠습니다.
Render Featur란 일종의 렌더링 레이러 같은 개념으로, 엔진에서 추가 렌더링 오브젝트와 메터리얼, 렌더링 타이밍까지 결정할 수 있는 강력한 기능입니다.
1) Render Feature 추가하기
현재 프로젝트에서 사용중인 렌더 파이프라인 에셋에 적용된 렌더러를 찾아서 Add Renderer Feature 를 눌러 Render Feature를 추가해줘야 합니다

렌더 오브젝트 클릭

기존의 렌더링 순서에 추가적인 렌더링 단계를 넣을 수 있는 기능이라네여
아래와 같이 설정해줍니다. (레이어 마스크도 하나 추가해서 여기에 설정하고, 외곽선을 나타내고 싶은 오브젝트의 레이어도 똑같이 맞춰줘야함)

Event 항목을 보면 아래와 같이 쭉 늘어진 것들을 볼 수 있는데

저 맨 위에서 맨 아래까지가 일반적 렌더링 순서라네요.
Event는 어느 시점에서 이 이벤트를 발생시킬지 지정하는 거에요.
여기서 디폴트 값이었던 AfterRenderingOpaques 를 유지해줍니다.
지금 우리의 공룡뼈는 Opaque에 그려지는 단계에 속해 있으며, Z버퍼를 이용해 앞뒤를 판정하기 때문에 특별히 Before/After를 신경쓰지 않아도 됩니다.
Material 항목에 위에서 만들었던 외곽선 머티리얼을 넣어주면

짠 이렇게 오브젝트 하나에 외곽선 표현까지 가능해집니다.
Skull 레이어에 해당하는 오브젝트만 렌더 피쳐로 한번 더 그려서, 그것들을 Outline 메터리얼로 덮어써 버리는 일을 한 겁니다.
4. 끊어지는 음영 나타내기
이제 음영을 만화처럼 나타내볼건데요.

하프램버트로 0~1 까지의 음영을 나타낸 뒤
Comparison, Branch 노드를 통해
0.5 보다 크다면 -> 1
0.5 보다 적다면 -> 0 으로 분리해줍니다.

이거 완전 코믹스잖아,,!!
5. Ceiling을 이용해 끊어지는 음영을 만들어 봅시다
앞선 방법의 문제점 : 경우의 수를 2가지로 밖에 나누지 못한다
소수점이 있는 숫자를 정수로 올려주는 Ceiling노드를 사용해서 만들어봅시다.

0~1의 범위에 5를 곱하여 0~5 범위로 늘려준 뒤 Ceiling을 통해 모든 값들을 1,2,3,4,5 로 분리합니다.
그리고 다시 5로 나눠주면 0.2, 0.4, 0.6, 0.8, 1 의 다섯 단계의 값이 나오게 되죠

좀 더 부드러워졌어요

이제 공룡뼈 노멀맵과 기존 색상까지 곱해주면




이렇게 됩니당
6. Fresnel을 이용해서 외곽선을 만들어 봅시다
프레넬 효과를 사용해서 외곽선을 만들어 볼 수도 있어용

Step은 들어오는 값이 Edge보다 크면 1, 작다면 0을 반환하는 노드에요.
외곽선이 더 딱 떨어지는 극적인 표현을 위해 추가했습니다.

그래프에 연결해주면
결과는

이건... 잘 모르겠다..
7. Diffuse Warping 기법
팀 포트리스 2의 Warped diffuse기법은 가볍고도 응용이 편리해서 지금도 많이 사용되는 기법이기도 합니다. 이 기법의 핵심 구현 기법은 빛 계산으로 쓰는 공식인 노멀과 라이트 벡터의 내적을 UV로 이용한다는 것입니다.


다시 밋밋한 모습으로 돌려놓고 시작해볼게요

이렇게 생긴 텍스쳐를 사용할 겁니다.
이 텍스쳐의 UV좌표는

이런 모습일텐데
UV좌표를 통해 색을 불러오면 됩니다.
하프램버트 값을 UV좌표로 넣어주면


결과는

이쁘다...!!
카툰 풍 너무 이쁘다
8. Diffuse Warping 응용
UV 좌표 중에 Y좌표가 아깝게 남아 돌고 있습니다.
그 자리에 스페큘러를 넣어봅시다
텍스쳐의 윗부분이 흰색이라는 점을 이용해서 Y좌표를 1로 설정해서 스페큘러로 나타내는 거에요.

계산된 결과를 UV의 Y좌표로 넣어주면

이렇게 흰 부분들이 생깁니다.

여기서 텍스쳐를 이런 모양으로 교체해줍니다.
위의 흰색 줄이 스패큘러가 될 것이고, 아래에 그리게 되면 림라이트 영역이니 어둡게 표현되어서 외곽선 효과가 생길 거에요.
검은 표현은 왼쪽으로 갈 수록 얇아지는데, 이를 통해 밝은 부분은 검은 외곽선이 얇아지고 어두운 부분에는 검은 외곽선이 두꺼워지는 표현이 가능해집니다.

결과는

짠~
'개발 > Unity' 카테고리의 다른 글
| [대마왕] 알파와 뎁스 버퍼 (Alpha & Depth Buffer) (0) | 2025.09.06 |
|---|---|
| [대마왕] 큐브맵 리플랙션 (0) | 2025.09.06 |
| [대마왕] 그림자 감쇠 (6) | 2025.08.16 |
| [대마왕] 퐁 반사 / 블린 퐁 반사 (4) | 2025.07.27 |
| [ 대마왕의 유니티 URP 셰이더 그래프 스타트업 1 ] Part14 (6) | 2025.07.13 |
- Total
- Today
- Yesterday
- 안드로이드스튜디오
- SpinLock
- unorderedset
- Unity
- C++
- 지크슈
- 동기화
- registerForActivityResult
- 유니티
- NotFoundException: String resource ID #0x0
- semaphore
- Java
- photon
- 바이너리세마포
- Vector
- dependencyResilutionManagement
- 게임개발
- 포톤
- mutex
- ARface
- 세마포
- 스핀락
- ㅗㅂ
- unorderedmap
- unityAR
- 유니티슈팅게임
- 광유다
- map
- StartActivityForResult
- 뮤텍스
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 | 29 | 30 |