# Part 10 | Lit Shader Graph를 이용해 봅시다

## 01 Lit Shader

Lit 셰이더 : 물리 기반 셰이더 물리 기반 셰이더 : 구형 라이팅 시스템과 달리 주변 환경에 따라 물리 법칙대로 계산해서 표현해줌 simpleLit : 구형 라이팅이지만 단순하고 직관적이어서 아직도 씀

Lit Shader 만드는 법

* Create > Shader Graph > URP > Lit Shader Graph
* Unlit Shader Graph 생성 > Graph Settings > Material > Lit

만들면 빛에 반응해서 그림자가 지긴 하지만 내장된 Lit 셰이더와는 달리 기능이 아무것도 없다. 기능들은 직접 만들어야 한다.

## 02 Lit Shader Graph 사용하기

애셋 받아왔을 때 파이프라인이 안 맞아서 마젠타로 나오면 셰이더만 바꿔도 해결되는 경우가 있지만 많은 경우 설정을 바꿔줘야 하는데, 어떤 데이터가 어떤 설정으로 어디에 들어가야 하는지 알고 있으면 된다.

![](https://velog.velcdn.com/images/biomatrix117/post/7d86dcdf-553b-419d-ba02-03b0badd67c1/image.png)

**Base Color** : 물체가 가진 순수한 색. 텍스쳐를 넣는 곳.

내장 Lit 셰이더에선 컬러를 곱해서 Base Map의 색상을 조절할 수 있다. (그래서 현재 만드는 Shader에도 Color를 곱해줌)

> **Diffuse?** \
> Diffuse는 물리 기반 셰이더가 나오기 이전 셰이더에서 물체의 컬러를 나타내는 용어로 쓰였다. \
> Diffuse는 빛에 의해 난반사된 결과물이라는 의미가 있다. 물리 기반 셰이더는 '순수하게 물체가 갖고 있는 색상'을 가진 텍스쳐가 필요하므로 Albedo라고 부르는게 자연스럽다. 유니티에서는 Albedo를 Base Map이라고 부르기도 한다.

![](https://velog.velcdn.com/images/biomatrix117/post/d94d08bf-74d9-45fc-9e08-37beb225b70a/image.png)

**Metalic** : 재질의 금속성을 결정. 0이면 비금속, 1이면 금속. (텍스쳐 or 수치로 입력 가능)

* 비금속은 정반사(Specular, Highlight) 컬러는 조명의 색이다. 하얀 빛을 비추면 흰색이 반사된다.
* 금속은 하얀 빛을 비춰도 자신의 고유 스페큘러 색이 반사되어 나온다.
* 비금속은 기울어질수록 반사가 강해진다.
* 금속은 정면과 기울어진 면의 반사차는 크지 않다.
  * 예로, 거울은 유리 뒤에 은색 금속이 발라져 있어서 정면에서 바라봐도 반사가 잘 된다.
* Metalic 텍스쳐는 이론적으로 중간색 없이 흰색 혹은 검은색만 사용하는 것이 옳다. '금속과 비금속의 중간 물체'는 존재하지 않기 때문이다.
* Metalic에서 0이나 1이 아닌 중간색을 쓰는 경우는, 미세하게 기름이나 비금속의 투명한 무엇이 묻어서 애매한 케이스를 표현하거나, 텍스쳐 사이즈 문제로 금속과 비금속 경계면의 안티앨리어싱을 표현하기 위해 쓰는 경우가 있다.

**Smoothness** : 재질의 매끄러움/거침 여부를 결정

* Smoothness 맵은 보통 Metalic 맵의 Alpha 채널에 있다.
  * 이는 내장 Lit 셰이더에서도 동일하게 되어 있다. Material Inpsector > Surface Inputs > Metalic Map > Source를 보면 Metalic Alpha로 되어있다.
* 0이면 완벽히 거칠어서 난반사만 일어나고, 1이면 완벽히 매끄러워서 정반사만 일어남. (텍스쳐 or 수치로 입력 가능)
* 사물들은 정반사와 난반사를 적절히 섞어서 갖고 있다.
* 언리얼은 이를 Roughness라 부르며, 유니티와 반대로 사용한다. 0이면 매끄럽고 1이면 둔탁하다. 언리얼의 Roughness 텍스쳐를 구하게 됐다면 그대로 넣고 One Minus 노드를 붙이면 Smoothness가 된다는 뜻. (sRGB는 끄고)
* 물리 기반 렌더링(유니티의 Lit Shader)의 기본 원리는 에너지 보존 법칙이다. 나가는 빛의 양은 들어온 빛의 양을 넘을 수 없다. 정반사가 높아지면 난반사는 줄어든다는 뜻.

<https://docs.unity3d.com/cn/2018.3/Manual/StandardShaderMaterialCharts.html>

유니티에서 제공하는 'Metalic Value Chart'를 보면 Metalic과 Smoothness에 따른 재질의 변화를 한 눈에 알 수 있다. (Unity Specular Chart라는 것도 찾을 수 있을텐데, 이 차트는 물리 기반 셰이더이면서도 스페큘러 컬러를 자유롭게 사용할 수 있도록 만든 셰이더를 위한 차트이다)

<br>

![](https://velog.velcdn.com/images/biomatrix117/post/61f41216-b6a6-4e3b-a4be-b8df6dfb470d/image.png)

**Normal Map** : 텍스쳐를 이용해서 빛의 음영을 속여 디테일이 늘어난 것처럼 보이게 하는 눈속임 맵

* 텍스쳐의 Type이 Normal map으로 되어 있는지 반드시 확인해주어야 한다. (텍스쳐 Inpsector 뿐 아니라 Shader Graph Node에서도)

**만드는 방법**

* sculpting 툴 : Z-Brush, Mudbox 등
* Render To Texture : 3D 프로그램에서 하이 폴리곤 모델링 후 RTT(Render To Texture)로 추출
* 이미지 음영 기반 Normal map 추출 : Crazy bump, B2M, 포토샵
* 유니티에도 음영 기반 노말맵 추출 기능 내장됨 (퀄리티가 크게 안 중요할 때 간단히 사용)
  * 텍스쳐 Inspector > Texture type → Normal map > Create from Grayscale 선택 > Bumpiness, Filtering 조절 > Apply
  * 이미 파랗게 된 Normal Map은 Texture type을 Normal map으로 바꿔주기만 하면 된다. Normal map을 또 Normal map으로 바꾸면 결과물 엉망됨.

내장 Lit Shader에는 Normal Map의 강도를 조절할 수 있는 기능이 있다. Normal Strength Node으로 같은 기능을 구현할 수 있다.

![](https://velog.velcdn.com/images/biomatrix117/post/59fdebe7-4522-4062-8ee1-e0cd2bf80003/image.png)

**Ambient Occlusion** : 구석진 부분의 추가적인 음영 표현

* 일반적으로 환경광(Ambient Color)로 가득 차 있는 세상에서 그림자가 드리워진 부분도 사방에서 오는 환경광을 받기 마련이다. 하지만 매우 구석져 있거나 복잡한 물체로 가려져 환경광도 닿지 못하는 부분은 더욱 더 어두워지는데, 이를 Ambient Occlusion(환경 차폐)라 부른다.
* 기본적으로 AO 값은 1이 들어가 있다. 이를 0으로 바꾸면 환경광의 영향이 사라지고, 주광의 영향만 남는다. 즉, 주광을 받지 못한 부분은 그냥 검은색이 된다.

(스샷의 Ambient Occlusion Intensity에서 Saturate를 넣은 이유는 AO 값이 0\~1 사이만 사용하기 때문.)

***

> **책 실습 과제 o1 답변** \
> 잘 생각해 보면, Metalic 텍스쳐의 G와 B는 아무것도 사용하지 않고 있고, Ambient Occlusion 맵도 R만 사용하고 있어서 나머지 채널이 낭비가 된다는 것을 알 수 있습니다.\
> \
> 아시다시피, 게임에서 텍스쳐 용량을 아끼는 것은 무척 중요합니다.\
> \
> 그렇다면, 포토샵을 이용해서 Metalic 텍스쳐와 Ambient Occlusion 텍스쳐를 다른 채널에 합쳐서 사용할 수 있지 않을까요?\
> \
> 아니면, 현재 필요 없는 Base Map의 A 채널을 Ambient Occlusion 맵으로 이용하는 것은 어떨까요? 어떻게 응용하는 것이 가장 좋을까요? 단점은 무엇인가요?

**채널 합치기의 장점과 단점**

**장점**

1. **메모리 최적화**:
   * 여러 장의 텍스쳐를 한 장으로 합침으로써 텍스쳐의 개수가 줄어들고, 특정 압축 포맷(예: DXT, BC, ASTC 등)에서 메모리 사용량이 줄어듭니다.
2. **드로우콜 및 관리 용이**:
   * 텍스쳐를 로딩하거나 관리할 때 자원을 좀 더 효율적으로 관리 가능.
   * 셰이더에서 필요한 텍스쳐 샘플이 줄어 성능에도 긍정적인 영향이 있을 수 있음.

**단점**

1. **압축 품질 이슈**:
   * 하나의 텍스쳐 안에 서로 다른 용도의 정보를 담을 경우, 특정 채널이 높은 디테일을 요구하는데 다른 채널 때문에 압축 손실이 발생할 수 있습니다.
   * 예: AO는 미세 그라디언트가 중요하지만, Metallic은 크게 차이가 없는 단색 기반이라면 채널별로 다른 압축 방식을 쓰고 싶어도 불가능해짐.
2. **유연성 감소**:
   * AO 맵만 교체하거나, Metallic 맵만 해상도를 낮출 수 있는 유연함이 없어집니다(모두 묶여 있으므로 전체 텍스쳐 교체/수정 필요).
   * 파이프라인상의 채널 연결(셰이더 설정)도 복잡해질 수 있음.
3. **셰이더/머티리얼 설정 복잡도**:
   * 각 채널에 어떤 데이터가 들어있는지 셰이더 측에서 인지해야 하고, 알파 채널을 이용하는 경우에는 더더욱 커스텀 셰이더 설정이 필요할 때가 많습니다.

추가로, 책 p.293에서 언급하기로는

"너무 많은 텍스쳐가 들어가는 것은 곤란하므로 나중에 포토샵에서 채널별로 합쳐주는 것도 좋은 선택입니다. 예를 들어, 4장의 smoothness는 각 GRBA 채널에 넣어서 한 장의 텍스쳐로 합쳐줄 수도 있습니다. 물론 **게임용 텍스쳐 포맷은 압축되면서 채널 침범의 문제가 있어서** 신중히 사용해야 합니다."

라고 함.

***

![](https://velog.velcdn.com/images/biomatrix117/post/25eca112-2333-466d-b153-52aa9fb28741/image.png)

**Emission** : 빛이나 그림자의 영향을 받지 않는 Unlit 텍스쳐. 스스로 빛나는 부분에 사용됨.

* Emission의 색 조절은 Base Map의 색 조절과는 다르게 HDR 옵션을 주는게 좋다. 1보다 큰 색을 곱해주면 더 강하게 빛나는 Emission을 만들 수 있기 때문이다.
* 스샷에서 Colorspace Conversion을 해준 이유는 Emission의 Texture type이 sRGB(감마 스페이스)이고, Color 노드에서 나오는 값은 기본적으로 Linear기 때문이다.

씬 배경을 간단하게 삽입하는 방법 : exr 파일을 유니티에 삽입 > Texture Inspector > Texture Shape > Cube > Apply > Cubemap으로 바뀐 텍스쳐를 빈 하늘에 드래그 & 드롭

## 03 9장의 배경을 Lit Shader로 만들어 응용해 봅시다

Graph Inspector > Graph Settings > Material > Lit

![](https://velog.velcdn.com/images/biomatrix117/post/bba922e2-f549-42e5-8ec3-2a457559d4aa/image.png)

Base Color에 Vertex Color대로 멀티 텍스쳐를 할당했던 shader graph가 (Lit 셰이더가 된 탓에) 6번 반복되기 때문에, sub graph를 만든다.

* sub graph를 수정하려면 더블 클릭하면 된다. 변수의 순서 또한 바꿀 수 있다.
* 아무것도 없는 상태에서 Sub Graph를 만드는 것도 가능하다.
* sub graph를 만들면 검색으로도 추가 가능하다.

스샷은 Texture 4개를 Lerp 3번하는 그래프들을 왼쪽처럼 sub graph로 묶은 모습이다.

> **TroubleShooting 과정**
>
> * `ullReferenceException: Object reference not set to an instance of an object UnityEditor.ShaderGraph.Drawing.MaterialGraphEditWindow.ToSubGraph ()` 오류 발생
> * 작은 노드들부터 sub graph로 만들어본 결과 sub graph를 만드는 과정 자체에 문제가 있지는 않았던 것으로 파악됨. sub graph의 조건을 뭔가 위배해서 발생한 오류. 책에서와는 다르게 sample Texture 2D 4개까지 포함하여 sub graph를 생성하니 무사히 생성됐다.
> * 하지만 책에선 "Texture Sampler 2D까지 Sub Graph로 묶지 않은 이유는, 나중에 텍스쳐가 아닌 값 (예를 들어 Metalic에 그냥 숫자 0을 넣을 경우, 혹은 Color를 넣어야 하는 경우)에 대응하기 위해서입니다." 라고 돼있었기에, 다시 sub graph를 unpack해보려고 함. 그런 기능은 없었음. 일단 copy paste로 원상 복귀. (undo 기록 사라졌었음)
> * 책 실습 파일 패키지에서 9장의 셰이더 그래프 원본을 import하고 책과 동일한 영역을 sub graph로 만들어보았으나, 똑같은 Nullref가 발생. 하지만 import한 sub graph 파일은 멀쩡히 잘 있음. 즉, 뭔가 버전 문제 때문에 sub graph가 원활히 만들어지지 못하는 것. 검색해보니 여러 사례가 있었고, 뾰족한 해결책이 없어 보임.
> * Sample Texture 2D에 Vector4를 연결하여 sub graph를 만들어보았으나, 역시 nullref
> * 결국 Project 창 > Create > Shader Graph > Sub Graph로 직접 서브 그래프를 만든 후, Property들을 생성하고, 묶고자 하는 그래프들을 복붙해서 해결하긴 했다.

![](https://velog.velcdn.com/images/biomatrix117/post/74b5a191-3f9c-4d55-a29f-dc5f76b3794a/image.png)

**물리 기반 셰이더에 입각한 데이터 값 추가하기**

* 금속이 아니니 Metalic에는 값 0
* Smoothness는 값 전부 넣어줘야 함. Smoothness 텍스쳐들은 모두 Linear 텍스쳐 (예뻐서 만든게 아니라 값이 정확해서 만든 데이터 텍스쳐) 이기 때문에, 모두 sRGB 옵션을 꺼줘야 한다.
* Texture Type > Normal map 확인 Sample Texture 2D 노드에서 Texture sample > Normal 설정 노드 출력 RGBA로 출력하면 마젠타로 오류가 뜰 것이고, 이는 16개 이상의 샘플러를 사용해서 픽셀셰이더 5.0의 한계를 넘어섰기 때문. (텍스쳐는 128개까지 가능) Sampler State를 만들고 Property로 Convert해서 여러 곳에 한 개의 Sampler State를 이용해주면 오류가 해결된다.
* Ambient Occlusion을 동일하게 추가해주고
* Emission을 넣으면 되는데, Emission이 따로 들어가지 않는 텍스쳐 자리에는 Property > Node Settings > Mode > Black으로 해놓기
* 실제로 이렇게 텍스쳐를 많이 넣으면 샘플 비용이 비싸지고, 안 쓰는 텍스쳐 채널이 낭비되게 된다. 포토샵에서 텍스쳐를 어떻게 잘 합쳐서 넣으면 텍스쳐 장수가 적어지는데 그건 알아서 고민해보라고 함. (노말맵의 A가 비었다고 이곳을 사용하는 건 피해야 한다고 함. 노말맵의 A는 Packing에서 사용하기 때문.)

> **텍스쳐 샘플링?** \
> GPU가 텍스쳐 데이터를 읽어서 UV 좌표를 기반으로 픽셀에 적용하는 과정


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://lazyartisan.gitbook.io/note/main-page/books/urp/part-10-or-lit-shader-graph.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
