Unity Term Book
그래픽 & 이펙트

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 + 렌더 로직 정의

_BaseColor_Metallic_BaseMap
▼ instantiate

Material A

_BaseColor = Red
_Metallic = 0.9

Material B

_BaseColor = Blue
_Metallic = 0.0

Material C

_BaseColor = Gold
_Metallic = 1.0

▼ assign to

🏠 House
Mat A

🚗 Car
Mat B

🏆 Trophy
Mat C

🔑 Key
Mat C

Trophy + Key가 Mat C를 공유 → draw call 1회 (batching)

실습 단계

1

새 Material 만들기

Project → 우클릭 → Create → Material. 이름 명확히(Metal_Gold, Ground_Grass…).

2

맞는 Shader 고르기

Inspector → Shader 드롭다운: PBR은 URP/Lit, 자체 발광 표면은 URP/Unlit, 2D는 Sprites/Default.

3

텍스처 할당과 속성 조절

Base Map에 텍스처를 넣습니다. Metallic(0=플라스틱, 1=금속), Smoothness(0=무광, 1=거울).

4

MeshRenderer에 Material 할당

MeshRenderer Materials[0]에 넣거나 Scene view에서 GameObject 위로 드래그합니다.

5

스크립트에서 속성 변경

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" 체크박스를 먼저 켜기