✅ 오늘 한 일
- 대마왕의 유니티 URP 셰이더 그래프 읽기
- Random Study
📝 배운 것들
🏷️ 텍스쳐 샘플링
텍스처 샘플링(Texture Sampling)은 GPU가 텍스처 데이터를 읽어서 픽셀에 적용하는 과정을 말합니다. 텍스처는 2D 이미지 데이터를 말하며, 이 데이터를 객체의 표면에 적용할 때, GPU는 UV 좌표를 기반으로 텍스처 데이터를 가져와 렌더링에 사용합니다. 이 과정을 텍스처 샘플링이라고 합니다.
텍스처 샘플링의 개념
-
텍스처와 UV 좌표
- 텍스처는 2D 이미지 데이터로, (0,0)에서 (1,1)까지의 UV 좌표를 통해 참조됩니다.
- UV 좌표는 객체의 정점(Vertex)에 할당되며, 렌더링 시 정점 간 보간(Interpolation)을 통해 픽셀마다의 UV 좌표가 결정됩니다.
-
픽셀과 텍셀
- 텍스처는 텍셀(Texel)이라는 작은 픽셀 단위로 구성되어 있습니다.
- 텍스처 샘플링 과정에서 UV 좌표에 따라 해당 텍셀의 데이터를 읽어와 픽셀에 적용합니다.
-
UV 좌표 범위
- UV 좌표는 일반적으로 (0,0)에서 (1,1) 범위를 가집니다.
- UV 좌표가 이 범위를 벗어나면, 샘플링 동작은 Address Mode 설정에 따라 Wrap, Clamp, Mirror 등으로 처리됩니다.
텍스처 샘플링의 과정
-
UV 좌표 기반 데이터 읽기
- GPU는 객체의 픽셀마다 보간된 UV 좌표를 계산하고, 이를 기반으로 텍스처 이미지에서 데이터를 샘플링합니다.
-
필터링 적용
- 샘플링된 UV 좌표가 텍스처의 텍셀과 정확히 일치하지 않는 경우, 필터링 방식을 사용하여 값을 계산합니다. 대표적인 필터링 방식은 다음과 같습니다:
- Point 필터링: UV 좌표에 가장 가까운 텍셀을 선택합니다.
- Linear 필터링: UV 좌표 주변의 텍셀 값을 선형 보간하여 부드러운 결과를 만듭니다.
- Anisotropic 필터링: 비등방성 필터링으로, 특정 각도에서 텍스처를 더 선명하게 보이게 합니다.
-
Address Mode 설정 처리
- UV 좌표가 (0,0)~(1,1) 범위를 벗어나면 Address Mode 설정에 따라 처리됩니다:
- Wrap: 텍스처를 반복합니다.
- Clamp: 텍스처의 가장자리 픽셀 값을 연장하여 적용합니다.
- Mirror: 텍스처를 반복하면서 뒤집어서 표시합니다.
-
텍스처 데이터 반환
- 텍스처 샘플링이 완료되면, 픽셀 셰이더는 샘플링된 텍셀 데이터를 반환받아 객체의 표면에 적용합니다.
필터링과 해상도
텍스처 샘플링 과정에서 텍스처 해상도와 화면 해상도가 다를 경우, GPU는 텍셀과 픽셀의 차이를 처리해야 합니다:
1. 다운샘플링: 화면 해상도가 텍스처 해상도보다 높을 때, 하나의 텍셀이 여러 픽셀에 매핑됩니다. Point, Linear 필터링을 사용하여 처리.
2. 업샘플링: 화면 해상도가 텍스처 해상도보다 낮을 때, 하나의 픽셀이 여러 텍셀에 매핑됩니다. 필터링을 통해 부드럽게 처리.
텍스처 샘플링의 실제 사용 사례
-
Diffuse Mapping:
- 객체 표면의 기본 색상을 나타내기 위해 텍스처 샘플링을 사용합니다.
- UV 좌표를 기반으로 텍스처에서 샘플링된 색상을 객체 표면에 적용.
-
Normal Mapping:
- 텍스처 샘플링을 사용해 객체 표면의 세부적인 법선 데이터를 읽고, 이를 조명 계산에 사용.
-
Reflection Mapping:
- 환경 맵(Environment Map) 텍스처를 샘플링하여 객체에 반사 효과를 적용.
-
Animation:
- UV 좌표를 시간에 따라 변경하여 텍스처가 움직이는 애니메이션 효과를 만듭니다.
Shader Graph에서의 텍스처 샘플링
Unity Shader Graph에서 텍스처 샘플링은 주로 Sample Texture 2D 노드를 사용하여 수행됩니다. 이 노드는 UV 좌표를 기반으로 텍스처 데이터를 읽고, 필터링과 Address Mode 설정에 따라 결과를 반환합니다.
- Sample Texture 2D 구성:
- Texture: 샘플링할 텍스처.
- UV: 텍스처 샘플링에 사용할 UV 좌표.
- Sampler State: 필터링 및 Address Mode 설정.
- RGBA 출력: 샘플링된 텍스처 데이터.
결론
텍스처 샘플링은 3D 그래픽스 프로그래밍의 핵심 개념으로, UV 좌표를 기반으로 텍스처 데이터를 읽고 객체 표면에 적용하는 과정입니다. 이 과정은 렌더링의 품질과 성능에 직접적인 영향을 미치며, Unity에서는 Shader Graph의 Sample Texture 2D 노드를 통해 이를 쉽게 처리할 수 있습니다. 텍스처 샘플링을 잘 이해하면 고품질의 텍스처 기반 그래픽 효과를 구현할 수 있습니다.
🏷️ 샘플러
샘플러(Sampler)는 GPU가 텍스처 데이터를 읽고 처리하는 방식(필터링, 경계 처리 등)을 정의하는 객체입니다. 샘플러는 텍스처 샘플링 과정에서 사용되며, 텍스처 데이터를 어떻게 해석할지 결정하는 역할을 합니다.
샘플러는 텍스처 데이터 자체와 별개로, 텍스처의 샘플링 방식을 정의하는 독립적인 설정입니다.
샘플러(Sampler)의 역할
샘플러는 주로 다음과 같은 동작 방식을 정의합니다:
-
필터링(Filtering):
- 텍스처 좌표(UV)가 텍셀(Texel, 텍스처의 픽셀)과 정확히 일치하지 않을 때, GPU가 텍셀 데이터를 어떻게 보간(interpolate)하여 결과를 생성할지 결정합니다.
- 필터링 옵션:
- Point (Nearest): 가장 가까운 텍셀 값을 그대로 사용. (거친 이미지, 픽셀아트에 적합)
- Linear: 주변 텍셀 값을 선형 보간하여 부드러운 결과 생성.
- Anisotropic: 텍스처가 기울어진 각도에서도 선명도를 유지하도록 고급 필터링 적용.
-
주소 처리(Addressing):
- UV 좌표가 텍스처의 범위(0~1)를 벗어날 경우, 이를 어떻게 처리할지를 결정합니다.
- 주소 처리 모드:
- Wrap: 텍스처를 반복(타일링)합니다.
- Clamp: 텍스처의 가장자리 값을 연장하여 사용.
- Mirror: 텍스처를 반복하면서 뒤집어 나타냅니다.
- MirrorOnce: 텍스처를 한 번 뒤집고 그 이후에는 클램프 처리.
-
비등방성 필터링(Anisotropic Filtering):
- 텍스처가 화면에 기울어진 각도로 렌더링될 때, 텍셀의 왜곡을 줄이고 선명도를 유지하는 고급 필터링 옵션.
-
Mip Mapping:
- 텍스처가 여러 해상도로 저장되었을 때, 특정 해상도의 텍스처를 선택하여 샘플링하는 방식을 결정.
샘플러의 실제 구성
샘플러는 다음과 같은 파라미터를 정의합니다:
| 속성 | 설명 |
|---|
| Filter Mode | 텍스처 필터링 방식. (Point, Linear, Anisotropic) |
| Address Mode | UV 좌표가 텍스처 범위를 벗어날 때의 처리 방식. (Wrap, Clamp, Mirror 등) |
| Max Anisotropy | 비등방성 필터링의 강도. (값이 높을수록 선명도 증가, 일반적으로 2~16 사용) |
| MipMap Level | Mip Mapping 시 특정 레벨의 텍스처를 샘플링할지 결정. |
Unity에서 샘플러(Sampler)
Unity에서는 Sampler State라는 개념으로 Shader Graph나 HLSL 코드에서 샘플러를 정의하고 사용할 수 있습니다.
1. Shader Graph의 Sampler State 노드
- Shader Graph에서 Sampler State 노드는 텍스처 샘플링 방식(필터링, Address Mode 등)을 정의합니다.
Sample Texture 2D 노드와 함께 사용되며, 텍스처 샘플링 설정을 사용자 정의할 수 있습니다.
Sampler State 설정:
- Filter Mode: Point, Linear, Anisotropic.
- Address Mode: Wrap, Clamp, Mirror 등.
2. HLSL에서 샘플러
HLSL(High-Level Shading Language)에서는 sampler 또는 SamplerState를 사용해 샘플러를 정의합니다.
예: HLSL에서 샘플러 정의
SamplerState samplerState : register(s0); // 샘플러 상태 등록
Texture2D myTexture : register(t0); // 텍스처 등록
float4 main(float2 uv : TEXCOORD) : SV_Target {
return myTexture.Sample(samplerState, uv); // 샘플러를 사용한 텍스처 샘플링
}
3. Unity에서 기본 샘플러
- Unity는
Sample Texture 2D 노드를 사용할 때 기본 샘플러를 자동으로 제공하며, 기본 필터링 및 Address Mode 설정은 다음과 같습니다:
- Filter: Linear.
- Address Mode: Wrap.
샘플러와 텍스처 샘플링의 차이
- 텍스처: 픽셀 데이터를 저장한 이미지.
- 샘플러: 텍스처를 샘플링할 때 사용하는 필터링 방식과 처리 방식을 정의.
예: 샘플러 없이 텍스처를 읽을 수 없다!
- 텍스처 데이터는 샘플러의 필터링 및 주소 처리 방식을 통해 픽셀에 적용됩니다.
- 샘플러는 텍스처를 "어떻게 읽어올지"를 결정하는 설정 도구입니다.
샘플러의 실제 사용 예
-
텍스처 타일링:
- Wrap Address Mode를 사용하여 텍스처를 반복.
Sample Texture 2D 노드에서 타일링된 텍스처 좌표를 사용해 타일링 효과 구현.
-
픽셀 아트 스타일:
- Point 필터링을 사용하여 텍스처를 확대/축소해도 픽셀 아트의 선명도를 유지.
-
고품질 그래픽:
- Anisotropic 필터링과 Linear 필터링을 결합하여 고품질 텍스처 표현.
-
클램핑 효과:
- Clamp Address Mode를 사용하여 UV 좌표가 텍스처 범위를 벗어날 때 가장자리 색을 연장.
결론
- 샘플러(Sampler)는 텍스처 데이터를 GPU에서 샘플링하는 방식을 정의하는 객체입니다.
- 필터링 방식(Point, Linear, Anisotropic)과 Address Mode(Wrap, Clamp, Mirror 등)를 포함하여, 텍스처의 표현 품질과 동작을 제어합니다.
- Unity Shader Graph에서는
Sampler State 노드, HLSL에서는 SamplerState 객체를 사용해 샘플러를 정의합니다.
- 샘플러를 올바르게 사용하면 다양한 텍스처 효과와 최적화된 그래픽 렌더링을 구현할 수 있습니다.
📖 대마왕의 유니티 URP 셰이더 그래프
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 사용하기
애셋 받아왔을 때 파이프라인이 안 맞아서 마젠타로 나오면 셰이더만 바꿔도 해결되는 경우가 있지만
많은 경우 설정을 바꿔줘야 하는데, 어떤 데이터가 어떤 설정으로 어디에 들어가야 하는지 알고 있으면 된다.

Base Color : 물체가 가진 순수한 색. 텍스쳐를 넣는 곳.
내장 Lit 셰이더에선 컬러를 곱해서 Base Map의 색상을 조절할 수 있다.
(그래서 현재 만드는 Shader에도 Color를 곱해줌)
Diffuse?
Diffuse는 물리 기반 셰이더가 나오기 이전 셰이더에서 물체의 컬러를 나타내는 용어로 쓰였다.
Diffuse는 빛에 의해 난반사된 결과물이라는 의미가 있다.
물리 기반 셰이더는 '순수하게 물체가 갖고 있는 색상'을 가진 텍스쳐가 필요하므로 Albedo라고 부르는게 자연스럽다.
유니티에서는 Albedo를 Base Map이라고 부르기도 한다.

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라는 것도 찾을 수 있을텐데, 이 차트는 물리 기반 셰이더이면서도 스페큘러 컬러를 자유롭게 사용할 수 있도록 만든 셰이더를 위한 차트이다)

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으로 같은 기능을 구현할 수 있다.

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 맵으로 이용하는 것은 어떨까요? 어떻게 응용하는 것이 가장 좋을까요? 단점은 무엇인가요?
채널 합치기의 장점과 단점
장점
- 메모리 최적화:
- 여러 장의 텍스쳐를 한 장으로 합침으로써 텍스쳐의 개수가 줄어들고, 특정 압축 포맷(예: DXT, BC, ASTC 등)에서 메모리 사용량이 줄어듭니다.
- 드로우콜 및 관리 용이:
- 텍스쳐를 로딩하거나 관리할 때 자원을 좀 더 효율적으로 관리 가능.
- 셰이더에서 필요한 텍스쳐 샘플이 줄어 성능에도 긍정적인 영향이 있을 수 있음.
- 작업 효율성:
- 한 장의 텍스쳐만 수정해도 여러 채널이 함께 업데이트되므로, 협업이나 버전 관리 측면에서 편리할 때가 많음.
단점
- 압축 품질 이슈:
- 하나의 텍스쳐 안에 서로 다른 용도의 정보를 담을 경우, 특정 채널이 높은 디테일을 요구하는데 다른 채널 때문에 압축 손실이 발생할 수 있습니다.
- 예: AO는 미세 그라디언트가 중요하지만, Metallic은 크게 차이가 없는 단색 기반이라면 채널별로 다른 압축 방식을 쓰고 싶어도 불가능해짐.
- 유연성 감소:
- AO 맵만 교체하거나, Metallic 맵만 해상도를 낮출 수 있는 유연함이 없어집니다(모두 묶여 있으므로 전체 텍스쳐 교체/수정 필요).
- 파이프라인상의 채널 연결(셰이더 설정)도 복잡해질 수 있음.
- 셰이더/머티리얼 설정 복잡도:
- 각 채널에 어떤 데이터가 들어있는지 셰이더 측에서 인지해야 하고, 알파 채널을 이용하는 경우에는 더더욱 커스텀 셰이더 설정이 필요할 때가 많습니다.
결론 및 팁
-
게임 엔진(또는 렌더 파이프라인)에서 지원 여부
- Unity의 Standard/PBR 셰이더나 Unreal 엔진의 머티리얼 시스템 등, 이미 “R=AO / G=Roughness / B=Metallic” 같은 방식을 지원하는 경우가 많습니다.
- 이런 경우라면 그대로 활용하는 것이 가장 간단합니다.
-
필요 없는 Base Color Alpha 채널의 활용
- 완전 불투명(Opaque)만 사용하는 모델이라면, Base Color의 Alpha 채널을 AO처럼 활용해도 괜찮습니다.
- 단, 알파 채널을 사용하는 다른 파라미터(Blend Mode 등)가 없다면 문제가 없지만, 나중에 투명이나 다른 마스크용도로 사용해야 한다면 다시 파이프라인을 바꿔야 할 수 있습니다.
-
단순 테스트 후 품질 확인
- 실제 게임에서 렌더링된 화면을 보면서, 압축으로 인한 AO/Metallic의 품질 저하가 발생하는지 꼭 확인합니다.
-
유지보수와 협업 고려
- 팀 내에서 다른 아티스트가 이미 분리된 맵 사용을 선호하는 경우, 혹은 아틀라스(Atlas) 최적화를 모두 다른 방식으로 하고 있는 경우 등, 팀 전체의 파이프라인 및 워크플로우를 고려해야 합니다.
추가로, 책 p.293에서 언급하기로는
"너무 많은 텍스쳐가 들어가는 것은 곤란하므로 나중에 포토샵에서 채널별로 합쳐주는 것도 좋은 선택입니다. 예를 들어, 4장의 smoothness는 각 GRBA 채널에 넣어서 한 장의 텍스쳐로 합쳐줄 수도 있습니다. 물론 게임용 텍스쳐 포맷은 압축되면서 채널 침범의 문제가 있어서 신중히 사용해야 합니다."
라고 함.

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

Base Color에 Vertex Color대로 멀티 텍스쳐를 할당했던 shader graph가
(Lit 셰이더가 된 탓에) 6번 반복되기 때문에, sub graph를 만든다.
- sub graph를 수정하려면 더블 클릭하면 된다. 변수의 순서 또한 바꿀 수 있다.
- 아무것도 없는 상태에서 Sub Graph를 만드는 것도 가능하다.
- sub graph를 만들면 검색으로도 추가 가능하다.
스샷은 Texture 4개를 Lerp 3번하는 그래프들을 왼쪽처럼 sub graph로 묶은 모습이다.
TroubleShooting 과정
NullReferenceException: 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들을 생성하고, 묶고자 하는 그래프들을 복붙해서 해결하긴 했다.

물리 기반 셰이더에 입각한 데이터 값 추가하기
- 금속이 아니니 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 좌표를 기반으로 픽셀에 적용하는 과정
🎮 Random Study
애셋 import 과정 troubleshooting
문제 설명
- https://essssam.itch.io/3d-leap-land
- 위의 애셋을 쓰고 싶었음
- 다운을 받아서 보니 fbx, obj, tex 폴더로 나눠짐
- fbx 폴더에는 fbx 파일들이 들어있고, tex에는 color pallete png 파일이 들어 있었음
- fbx 폴더와 tex 폴더를 그대로 import함
- import된 fbx들을 확인해보니 몇몇은 Metalic, 몇몇은 Non Metalic이라는 머테리얼이 자동으로 적용되어 있었음
- 하지만 Metalic과 Non Metalic 머테리얼의 차이는 존재하지 않았음
- Metalic map은 둘 다 0으로 설정돼있고, 그밖의 속성들도 전부 같았음
- 무엇보다, 이 머테리얼들에는 색이 적용돼있지 않았음
- 머테리얼을 만들고 Base map에 color pallete png를 삽입함
- 이 머테리얼로 Metalic이나 Non Metalic Material들을 대체하면 색이 나오긴 함
- fbx 끌어다 씬에 놓은 후에 생긴 오브젝트에 머테리얼 끌어다 놓아도 색이 나오고
- fbx 파일 > Inspector > Metalic 또는 Non Metalic이라 쓰여있는 항목에 머테리얼 끌어다 놓아도 색이 나옴
- 그러니까, '수동'으로 일일이 모델마다 머테리얼 껴서 색을 입혀주는 것까진 됨
- 하지만 60여개에 달하는 모델에 일일이 머테리얼을 적용한다는게 말이 안된다고 생각함
- itch.io 페이지에서 애셋 제작자의 댓글들을 확인해봤지만, 자신은 Unity를 해본지 오래됐고, 머테리얼에 텍스쳐를 입혀서 그 머테리얼을 다시 적용하라는 것 이외에 유의미한 정보를 얻지 못함.
내가 생각한 해결책
- Lit 셰이더를 적용한 Metalic과 Non Metalic 머테리얼을 새로 만든 후에 이름에 맞게 Metalic map의 값을 조절한다
- 유니티 에디터 코드를 작성하여 작업을 자동화한다
- 각 fbx 파일에 대해 이름에 맞게 새로운 Metalic, Non Metalic 머테리얼을 적용
- color pallete 머테리얼을 추가한다
질문
1. import하는 과정에서 무언가 놓친 점이 있었는가?
2. 굳이 에디터 코드까지 작성하지 않고도 머테리얼들을 새로 할당하는 간단한 방법이 있는가?
3. 왜 이런 일이 발생하였는가? fbx 파일에는 material 정보가 들어있는 걸로 알고 있고, 실제로 그러한 정보를 받아와서 Material이 '생성'까지는 된 것으로 생각되는데, 최소한 Metalic map 정보는 가져와야 하는 것 아닌가? 단순히 '특정 플랫폼을 위하여 만들지 않았다면 호환이 잘 되지 않는다'는 이유에 불과한가? 그렇다면 그 호환이 되지 않는 이유는 무엇인가?
아티스트/에셋 제작자마다 FBX 내부에 포함된 머티리얼 설정 및 텍스쳐 임베드 방식을 제각각 사용하기 때문에, Unity 쪽으로 가져왔을 때 머테리얼이나 텍스쳐가 자동으로 잘 할당되지 않는 상황은 흔히 발생합니다. 질문해주신 사항을 하나씩 짚어보겠습니다.
1. Import하는 과정에서 무언가 놓친 점이 있었는가?
(1) FBX 내부 머테리얼 정보의 한계
- FBX 파일은 내부적으로 머테리얼/셰이더 설정을 담을 수 있지만, Unity의 Standard (URP/HDRP Lit) 셰이더와는 호환되지 않는 정보인 경우가 많습니다.
- 특히 FBX 내 “메탈릭” 정보가 있어도, 그것이 Unity가 기대하는 방식(메탈릭/러프니스 맵 등)으로 내장돼 있지 않다면 Unity에서 자동으로 인식하지 못합니다.
(2) 텍스쳐의 임베디드 여부
- FBX에 텍스쳐를 “임베디드 텍스쳐(Embed Media)”로 내보냈다면, Unity가 FBX importer에서 일정 부분 자동 매핑을 시도할 수 있습니다.
- 그러나 실제로는 많은 툴에서 FBX에 텍스쳐가 임베디드되지 않고, 별도의 PNG/JPG 파일로 따로 제공되는 경우가 대부분입니다.
- 질문 내용상, “tex” 폴더에 따로 PNG가 들어 있고 FBX에는 별다른 텍스쳐 정보가 없었던 것으로 보입니다.
(3) Unity FBX Import Settings
- Unity [Project Settings → Editor] 또는 FBX 임포트 Inspector에서 “재질(Material) Import” 옵션이 있습니다.
- “Use External Materials (Legacy)” 등 여러 방식이 있는데, 일반적으로 자동 생성되는 머테리얼은 ‘포인트’만 잡혀 있을 뿐, 텍스쳐가 자동 할당되지 않을 가능성이 높습니다.
결론적으로, Import 과정에서 ‘설정 상’ 놓쳤다기보다, FBX 자체가 Unity가 바로 이해할 수 있는 메탈릭/컬러 정보를 잘 제공하고 있지 않았을 확률이 큽니다.
2. 굳이 에디터 코드까지 작성하지 않고도 머테리얼들을 새로 할당하는 간단한 방법이 있는가?
(1) 프로젝트 내 “머테리얼 자동 매핑” 기능 활용
- Unity 2022 이상에서는 FBX 임포트 시 머테리얼을 검색(재할당)하는 규칙(Remap) 설정이 있습니다.
- FBX 파일을 선택 → Inspector → Materials 탭 → “Location”, “Naming”, “Search” 옵션 등을 조절
- 예: “Search by Name”, “Material Folder” 등을 설정하여, 프로젝트 어딘가에 있는 동일한 이름의 머테리얼을 자동으로 매핑하도록 유도할 수 있습니다.
- 이 기능을 활용하려면, 미리 같은 이름을 가진 머테리얼(예:
Metalic.mat, NonMetalic.mat)을 만들어놓고, FBX 임포트 설정에서 Search 옵션을 적절히 잡아주면 자동 할당이 될 수 있습니다. (단, FBX 내부 재질 이름이 정확히 같아야 합니다.)
(2) Prefab 또는 Override 세팅 이용
- 만약 이미 씬에 배치한 모델이 있다면, 그 모델에 원하는 머테리얼(새로 만든 Metallic/Non Metallic)을 할당하고, 그 상태를 Prefab으로 저장해두는 방식을 사용할 수 있습니다.
- 이후 똑같은 모델을 다시 씬에 배치할 때는 Prefab을 불러와서 배치하면, 수동으로 머테리얼을 붙이지 않아도 됩니다.
(3) 여러 오브젝트를 동시에 선택 후 머테리얼 드래그&드롭
- 하이어라키(혹은 프로젝트 뷰)에서 여러 FBX(Model) 오브젝트를 한꺼번에 선택한 뒤, 프로젝트 뷰에서 머테리얼을 드래그&드롭하면 일괄 적용이 가능합니다.
- 60개 모델을 한 번에 바꾸기는 조금 까다롭더라도, 10개 단위 등 묶어서 드래그하는 식으로 시간을 단축할 수 있습니다.
→ 이건 시도해봤는데 안됐음
3. 왜 이런 일이 발생했는가? (FBX 파일 내부 Material 정보 호환성)
(1) FBX가 Unity용으로 ‘특화된’ 것이 아님
- FBX 포맷은 여러 3D 툴(블렌더, 3dsMax, Maya 등)에서 공용으로 쓰이지만, 각 툴의 셰이더 구조가 달라서 1:1 매핑이 쉽지 않습니다.
- 에셋 제작자가 “Unity에서 쓸 생각으로 만든 FBX”가 아니라면, FBX에 들어간 머테리얼 정보가 Unity Standard/PBR 방식과 전혀 다르게 설정되었을 수 있습니다.
(2) FBX Material은 대부분 “PlaceHolder” 역할
- FBX 임포트 시 자동으로 생성되는 머테리얼들은 대체로 ‘이름’과 ‘색상’ 정도만 가지고 있는 placeholder일 가능성이 높습니다.
- 실제로 “Metalic”, “NonMetalic”이라는 이름은 붙어있어도, Unity가 인식하기 위해서는 메탈릭 맵, 스무스니스(러프니스) 맵, 오클루전 등 PBR 채널 정보를 별도로 적용해줘야 합니다.
- FBX에서 “메탈릭 값이 0으로 설정되어 있다” → 사실상 Unity가 읽어올만한 메탈릭 텍스쳐나 float 값이 없었고, 그냥 0으로 초기화된 것입니다.
(3) ‘특정 플랫폼을 위해 만들어지지 않았다면 호환이 잘 안된다’
- 이것은 사실입니다. Unity 전용 툴(예: Unity Package 형태)로 만들어진 모델이 아니라면, FBX 안에 있는 재질과 텍스쳐 정보가 대부분 호환성 이슈가 생깁니다.
- “호환이 되지 않는 이유”는, FBX는 표준 포맷이지만 셰이더 파이프라인까지 표준으로 정의하지 않기 때문입니다.
- 예: Blender에서 Principled BSDF(메탈릭/러프니스)를 설정해도, 이를 Unity Standard Shader로 바로 1:1 매핑하기엔 여러 정보 손실/불일치가 있을 수 있음.
추가 팁 및 정리
-
FBX Import → Materials 탭에서 “Extract Materials”
- Unity에서 FBX 임포트를 할 때, FBX 내부 재질을 별도로 추출(Extract)할 수 있습니다. 추출 이후 해당 폴더에 위치한 머테리얼들에 직접 텍스쳐를 할당하거나 이름을 변경하여, 후처리를 자동화할 수도 있습니다.
-
머테리얼 이름 매칭 + Color Pallete Texture
- 작성해두신 “Color Pallete” 텍스쳐를 사용하는 새 ‘Standard/Lit’ 머테리얼을 만들어 두고, FBX 재질 이름과 같게 맞춰 놓으면 Unity가 FBX 임포트 시 검색해서 자동 할당해줄 가능성이 높아집니다.
- 예: FBX 내부 머테리얼 이름이 “Metalic”, “NonMetalic”이라면, 프로젝트 폴더에도 “Metalic.mat”, “NonMetalic.mat” 같은 식으로 만들어 두고, FBX Import [Materials → Search → Project] 등으로 설정.
-
에디터 스크립트 / AssetPostprocessor
- 많은 모델 파일에 대해 일괄적으로 머테리얼 할당 과정을 처리해야 한다면, Editor 스크립트(AssetPostprocessor)를 작성해두면 유용합니다.
- 단순 매핑 규칙(“이름에 ‘Metalic’ 포함 → Metallic.mat 할당”) 등을 만들어두면 대량의 FBX 임포트 작업을 자동화할 수 있습니다.
-
왜 메탈릭 맵 정보는 가져오지 않았는가?
- 질문에 대한 직접적인 답변: FBX가 Unity 표준 PBR 구조를 반영해 텍스쳐를 임베디드해주거나, 혹은 별도로 텍스쳐 연결 정보를 넣어주지 않았기 때문입니다.
- 심지어 FBX 마다 “Shading Model”이라는 필드가 다를 수도 있고, Unity가 “FBX 재질 → Standard Shader”로 변환하면서 잡아줄 수 있는 파라미터만 기본값으로 세팅한 것이죠.
결론적으로…
-
놓친 점?
- 큰 맥락에서 “놓친 것”이라기보다는, FBX가 Unity에 맞춰진 형식이 아니어서 발생한 당연한 현상입니다.
- Unity FBX importer가 “메탈릭=0”인 재질을 자동 생성하는 것은 흔한 일입니다.
-
에디터 코드 없이 간단히 매핑하는 법
- FBX Import Settings → Materials 탭에서 [Search] 설정을 활용해보세요.
- 또는, 다량의 모델 오브젝트를 동시에 선택 후, 준비해둔 머테리얼을 한꺼번에 드래그&드롭도 가능합니다.
-
이유와 호환성 문제
- FBX에 포함된 머테리얼 정보가 Unity Standard/PBR에서 요구하는 메탈릭 및 텍스쳐 슬롯과 1:1 대응되지 않기 때문입니다.
- 표준 포맷인 FBX조차도, 셰이더/재질 구조가 달라 호환성이 완벽하지 않습니다.
- 따라서 “이름만 맞아떨어지는 Placeholder 머테리얼이 자동 생성된 뒤, 메탈릭 값은 0으로 초기화”된 것입니다.
이후에도 다양한 3D 모델 에셋을 가져올 일이 많으실 텐데,
- 가장 확실한 방법은 “Unity에서 사용하는 머테리얼(.mat)에 텍스쳐를 세팅하고, FBX 임포트 시 이름 매칭 또는 에디터 스크립트로 자동 할당하는 파이프라인을 구축”하는 것입니다.
- 수작업이 너무 많다면, 짧게라도 Editor 스크립트를 작성해 두면 장기적으로 시간을 크게 줄일 수 있습니다.
이상이 도움이 되길 바랍니다!