Material & Shader
Shader는 GPU에서 픽셀을 그리는 프로그램이고 Material은 색·텍스처·Smoothness를 담은 인스턴스입니다. URP Lit·sharedMaterial·MaterialPropertyBlock으로 배칭을 지키며 PBR 표면을 제어하는 그래픽 기초 가이드입니다.
상상해 보세요...
Shader는 페인트 레시피(나무, 금속, 유리…)입니다. Material은 그 페인트의 특정 캔 — 같은 금속 레시피라도 하나는 금, 하나는 은, 하나는 더 광택입니다. 하나의 Shader에서 수천 개의 Material을 만들 수 있고 각각 다르게 보입니다. GameObject는 Mesh Renderer로 할당된 Material을 메시에 “칠합니다”.
개념 자세히
Shader는 GPU에서 도는 HLSL(High Level Shading
Language) 프로그램입니다. 최소 두 단계: Vertex Shader(3D 정점을 2D 화면에)와
Fragment/Pixel Shader(각 픽셀의 최종 색). Unity는 이를 ShaderLab,
Surface Shaders, 또는 URP의 Lit/Unlit Shader Graph로 감쌉니다.
Material은 Shader를 참조하고 그
properties 값을 저장하는 에셋입니다: 메인 색(_BaseColor), 텍스처(
_BaseMap), metallic(_Metallic), roughness(
_Smoothness)… 각 Renderer는 sub-mesh에 맞춰 Material 슬롯을 하나 이상
가질 수 있습니다.
성능에서 Material instancing이 중요합니다:
같은 Material 에셋을 공유하는 많은 오브젝트는 하나의 draw call로 합쳐질 수
있습니다(GPU instancing 또는 static batching). renderer.sharedMaterial 대신
renderer.material(사본)을 쓰면 오브젝트마다 draw call과 추가 메모리가
생깁니다.
Unity 기본 셰이더: URP/Lit(풀 PBR), URP/Unlit(조명 없음),
Sprites/Default(2D), Particles/Standard Unlit
(파티클). Shader Graph와 HLSL로 완전 커스텀 이펙트도 가능합니다.
Shader → Material → Renderer
📄 Shader (HLSL program)
URP/Lit — properties + 렌더 로직 정의
Material A
_BaseColor = Red
_Metallic = 0.9
Material B
_BaseColor = Blue
_Metallic = 0.0
Material C
_BaseColor = Gold
_Metallic = 1.0
🏠 House
Mat A
🚗 Car
Mat B
🏆 Trophy
Mat C
🔑 Key
Mat C
Trophy + Key가 Mat C를 공유 → draw call 1회 (batching)
실습 단계
새 Material 만들기
Project → 우클릭 → Create → Material. 이름 명확히(Metal_Gold, Ground_Grass…).
맞는 Shader 고르기
Inspector → Shader 드롭다운: PBR은 URP/Lit, 자체 발광 표면은 URP/Unlit, 2D는 Sprites/Default.
텍스처 할당과 속성 조절
Base Map에 텍스처를 넣습니다. Metallic(0=플라스틱, 1=금속), Smoothness(0=무광, 1=거울).
MeshRenderer에 Material 할당
MeshRenderer Materials[0]에 넣거나 Scene view에서 GameObject 위로 드래그합니다.
스크립트에서 속성 변경
renderer.sharedMaterial.SetColor("_BaseColor", color) — 또는 MaterialPropertyBlock으로 복제를 피합니다.
인터랙티브 시뮬레이터
PBR 파라미터를 조절하며 구 표면 변화를 보세요 — Unity Material Inspector의 대용입니다.
// Material Properties
_BaseColor = "#4488ff"
_Metallic = 0.50
_Smoothness = 0.70
_Emission = 0.00
Shader: URP/Lit
파란 광택 플라스틱
코드 예제
기본런타임에 Material의 색과 metallic을 변경합니다.
using UnityEngine;
public class MaterialController : MonoBehaviour
{
Renderer rend;
void Start()
{
rend = GetComponent<Renderer>();
// sharedMaterial: shared with every object → no extra copy
rend.sharedMaterial.SetColor("_BaseColor", Color.red);
// material (not shared): a private copy for this object
rend.material.SetFloat("_Metallic", 0.9f);
rend.material.SetFloat("_Smoothness", 0.8f);
}
public void Flash(Color color)
{
// Flash trick: set emission color
rend.material.SetColor("_EmissionColor", color * 2f);
DynamicGI.SetEmissive(rend, color * 2f);
}
}코드 예제
고급MaterialPropertyBlock — Material을 복제하거나 배칭을 깨지 않고 오브젝트별 속성.
using UnityEngine;
// Color each instance differently WITHOUT breaking GPU Instancing/Batching
public class InstanceColorizer : MonoBehaviour
{
static readonly int ColorID = Shader.PropertyToID("_BaseColor");
static readonly int EmitID = Shader.PropertyToID("_EmissionColor");
MaterialPropertyBlock mpb;
Renderer rend;
void Awake()
{
rend = GetComponent<Renderer>();
mpb = new MaterialPropertyBlock();
}
public void SetColor(Color color)
{
rend.GetPropertyBlock(mpb); // Read current state
mpb.SetColor(ColorID, color); // Change color
rend.SetPropertyBlock(mpb); // Apply — no new Material
}
public void SetEmission(Color emitColor)
{
rend.GetPropertyBlock(mpb);
mpb.SetColor(EmitID, emitColor);
rend.SetPropertyBlock(mpb);
}
}📌 빠른 정리
- ▸Shader = 레시피, Material = 구체 값 인스턴스
- ▸sharedMaterial: 공유, 추가 RAM 없음
- ▸MaterialPropertyBlock: 인스턴스별, 배칭 유지
- ▸Metallic=1 + Smoothness=1 = 완벽한 거울
- ▸Shader.PropertyToID()가 매 프레임 문자열보다 빠름
⚠️ 흔한 실수
❌ 스폰 루프에서 renderer.material 사용
매번 Material 복제 → 메모리 누수
✅ MaterialPropertyBlock 또는 sharedMaterial
❌ Material에서 Emission을 켜지 않음
SetColor("_EmissionColor",...)가 Emission 켜기 전까지 무효
✅ Material Inspector → "Emission" 체크박스를 먼저 켜기