본문으로 건너뛰기
CHOI HONGSU
1 min read

VAT Outline

 

 

Problem

기존 CH_Lit 기반 아웃라인은 VAT + GPU Indirect 캐릭터에 사용할 수 없었다.

  1. CH_Lit에 Outline Pass가 없다 — 아웃라인 자체를 렌더링할 Pass가 없음
  2. VAT 포지션 복원 없이 노멀 확장 불가 — 아웃라인의 노멀 확장은 실제 스킨된 위치 기준이어야 하는데, VAT 샘플링 없이 확장하면 T-포즈에서 아웃라인이 생김
  3. GPU Indirect 데이터 접근 불가 — 팀 컬러와 프레임이 unity_ObjectToWorld._m31/_m32에 패킹되어 있어 일반 셰이더에서는 읽지 않음

Approach

VAT_Lit 전용 셰이더 + OutlinePass 제작

Chosen

Pros

  • VAT에 필요한 버퍼만 포함, CH_Lit 무영향

Cons

CH_Lit에 Outline pass 추가

Pros

  • VAT 코드 전체 이식 필요, 기존 캐릭터 전체 리그레션 위험

Cons

Post-process 외곽선

Pros

  • 팀 컬러 구분 불가, GPU Indirect와 무관

Cons

Why VAT_Lit 전용 셰이더 + OutlinePass 제작: 팀 컬러 문제는 _m32에서 언팩한 컬러를 버텍스 컬러로 넘기고 OUTLINE_TINTCOLOR 키워드로 아웃라인에 적용 — 전용 파라미터 슬롯 없이 해결.

Architecture

VAT_Lit.shader
├── Outline pass (LightMode = "Outline")
│ └── OutlinePass.hlsl
│ ├── VAT 포지션 복원 (_m31 = 프레임)
│ ├── 월드스페이스 노멀 확장
│ └── 팀 컬러 (_m32 언팩 → vertex color → OUTLINE_TINTCOLOR)
├── ForwardLit pass → LitForwardPass.hlsl (VAT + CUSTOMINDIRECT)
└── ShadowCaster pass → VAT 동일 적용

 

 

URP Renderer Feature — GnomeOutline
Event: BeforeRenderingOpaques
LightMode Tag: "Outline"
Depth Test: Always ← 아웃라인을 먼저 쓰고 이후 캐릭터가 덮어씌움

Implementation

  1. 01

    1. VAT 포지션 복원 → 노멀 확장 순서

     
  2. 02

    2. 팀 컬러를 아웃라인에 전달

     
  3. 03

    3. URP Renderer Feature 설정

    BeforeRenderingOpaques + Depth Test: Always 조합 — 아웃라인을 먼저 depth에 기록하고, 이후 캐릭터 본체(Opaque)가 렌더되면서 안쪽을 덮어씌워 외곽선만 남음.

Tradeoffs & Future Work

Tradeoffs

  • CH_Lit 분리 유지 — 나중에 CH_Lit에 통합 가능하나 현재는 VAT 전용으로 격리
  • SRP Batcher 비호환 — _CUSTOM_INDIRECT가 ObjectToWorld를 커스텀 용도로 사용하는 구조적 한계
  • 버텍스 ID를 UV1에 베이킹 — SV_VertexID 대신 texcoord1.x 사용 — VAT 베이킹 파이프라인에서 미리 구워야 함

Architecture

Unity Frame Debugger 정상적으로 분리된 패스에서 작동