TOOLS GAMES DEVLOG DOCS ABOUT CONTACT
HOME > DOCS > Shader / URP > 2D 픽셀 스프라이트 노멀맵(Normal Map)과 URP 2D 동적 광원 입체 라이팅
Shader / URP Intermediate Unity 2022.3+ / Unity 6 (URP 2D)

2D 픽셀 스프라이트 노멀맵(Normal Map)과 URP 2D 동적 광원 입체 라이팅

Dead Cells 스타일: 2D 도트 스프라이트에 Secondary Texture _NormalMap을 연결하고 URP 2D Point/Spot Light로 실시간 입체 명암과 림라이트를 연출하는 기법.

#Shader #URP #2D #NormalMap #DeadCells #Lighting
핵심 개념*Dead Cells*의 그래픽이 경이로운 이유는 평면적인 2D 픽셀 캐릭터가 횃불이나 마법 광원을 지나갈 때 몸체 굴곡에 따라 빛이 실시간으로 흐르기 때문입니다. 이는 2D 스프라이트에 노멀맵(Normal Map)을 바인딩하고 URP의 2D 라이팅 파이프라인(Sprite-Lit-Default)을 활용해 3D 벡터 내적($N \cdot L$) 연산을 수행한 결과입니다.

1. 스프라이트 에디터 Secondary Texture 설정

단계작업 경로 및 옵션설명
1단계Texture Import > Texture Type = Sprite (2D and UI)플레이어 스프라이트 시트 기본 임포트
2단계Sprite Editor 열기 > Secondary Textures 선택스프라이트 메타데이터에 추가 텍스처 슬롯 개방
3단계Name: _NormalMap, Texture: 캐릭터_Normal 텍스처 등록픽셀별 법선 벡터 텍스처를 1:1 좌표로 바인딩
4단계캐릭터 Material = Universal Render Pipeline/2D/Sprite-Lit-Default노멀 연산을 지원하는 URP 2D 기본 셰이더 머티리얼 적용

2. 커스텀 2D 도트 계단식(Cel-stepped) 노멀 라이트 셰이더

PixelSpriteNormalLit.hlsl
// 2D 픽셀 스프라이트의 동적 광원을 도트 계단식으로 양자화하는 연산 블록
half3 CalculateCel2DLighting(half3 baseColor, half3 normalTS, float3 worldPos, float3 lightPos, half3 lightColor, float lightRange)
{
    float3 lightDir = lightPos - worldPos;
    float dist = length(lightDir);
    if (dist > lightRange) return baseColor;

    lightDir = normalize(lightDir);

    // 2D 스프라이트 접선 공간 노멀 언패킹
    half3 N = normalTS;
    half3 L = half3(lightDir.xy, lightDir.z);

    // 램버트 도트곱
    float NdotL = max(0.0, dot(N, L));

    // 부드러운 3D 조명을 3단계 도트 명암으로 양자화 (Dead Cells 룩)
    float celFactor = floor(NdotL * 3.0) / 3.0;

    // 감쇠 적용
    float atten = saturate(1.0 - (dist / lightRange));
    half3 finalLight = lightColor * celFactor * atten;

    return baseColor * (half3(0.2, 0.2, 0.3) + finalLight); // 환경광 + 동적광
}

3. 실전 제작 팁

  • 노멀맵 자동 생성 도구: 스프라이트를 한 장씩 수작업으로 노멀을 그릴 필요 없이, SpriteIlluminator나 Laigter(무료 오픈소스)를 사용하면 2D 도트 그림의 외곽선과 음영을 분석해 입체 노멀맵을 1초 만에 자동 추출할 수 있습니다.
  • Z축 깊이(Z-Depth) 배치: 2D 씬에서 조명이 정상적으로 림라이트를 비추려면 광원(Light 2D)의 Transform Z 좌표가 스프라이트보다 살짝 앞(카메라 쪽, 예: z = -1.0f)에 위치해야 입체적인 각도가 형성됩니다.