본문으로 건너뛰기

도트 노멀맵 생성기 · 스프라이트 밝기나 알파로

2D 조명에는 스프라이트마다 노멀맵이 필요합니다. 텍스처 랩은 스프라이트 자신의 회색 값(또는 알파)에서 높이를 읽어 그 기울기를 탄젠트 공간 노멀맵으로 바꾸고, 규약을 화면에 표시합니다.

도트 그림 노멀맵은 작가가 손으로 찍듯 노멀 방향을 몇 가지로만 쓸 때 가장 보기 좋습니다. 평평한 면, 그리고 각 방향으로 한두 단계 기운 면입니다. 이 페이지는 스프라이트의 밝기나 알파를 픽셀 단위 노멀맵으로 바꾸는 텍스처 랩을 엽니다. Studio 텍스처 작업 공간은 여기에 실루엣에서 1.5px 베벨과 "픽셀아트 노멀"을 더합니다. 기본값으로 모든 픽셀을 8방향 × 2단계 기울기 + 평면, 즉 노멀 17가지로 맞추고 Godot 4·Unity 6용으로 내보냅니다.

텍스처 맵을 끌어다 놓으세요(PNG는 채널 바이트를 그대로 유지)
브라우저에서 처리하며 파일은 업로드되지 않습니다.
텍스처 랩: CC0 텍스처로 만든 노멀맵과 OpenGL/DirectX 규약 표시
CC0 에셋(ambientCG)을 연 실제 텍스처 랩 화면입니다.
출력
  • Channel PNGs측정 확인· numpy
  • Normal map측정 확인· numpy
  • Packed mask / ORM측정 확인· Pillow
  • Engine import미검증

도트 노멀을 양자화하는 이유

기울기로 만든 노멀맵은 거의 모든 픽셀의 벡터가 조금씩 다릅니다. 조명이 움직이면 16 × 16 스프라이트 안에서 부드러운 그러데이션과 한 단계짜리 밝기 계단이 생기고, 제한된 팔레트 옆에서는 잡음처럼 보입니다. 손으로 찍은 도트 노멀은 평면과 방향마다 몇 안 되는 기울기만 쓰기 때문에, 조명을 받으면 깔끔한 띠로 나뉘고 빛이 움직일 때 픽셀 단위로 넘어갑니다.

Studio의 양자화기가 이것을 재현합니다. 픽셀마다 자기 방향과 기울기를 유지하되 방향은 4·8·16·32개의 고른 각도로, 기울기는 60°까지 1~4단계로 맞춥니다. 기본값인 8방향 × 2단계에서는 15° 미만이 평면, 15~45°가 30°, 그보다 가파르면 60°가 됩니다. 픽셀마다 따로 맞추므로 1픽셀 턱은 1픽셀 그대로 남습니다.

그 밑의 높이도 픽셀 크기여야 합니다. 128px 이하 프레임에는 Studio가 1.5px 베벨 테두리와 부드럽게 만들지 않는 단순 중앙 차분인 Pixel 커널을 제안하므로 테두리가 뭉개지지 않습니다. 노멀이 17가지이고 조명이 멀리 있으면 스프라이트의 한 색이 가질 수 있는 밝기는 최대 17단계입니다.

나머지는 엔진이 정합니다. 이중선형 필터를 거친 노멀맵은 이웃 노멀을 다시 섞고, Height가 0인 Godot PointLight2D는 스프라이트를 옆에서 스치듯 비추며, Unity는 Light Render Texture Scale을 1로 바꾸지 않으면 2D 조명을 화면 해상도의 절반으로 계산합니다.

방향 단계
360° ÷ 방향 수. 8방향이면 45°라서 기운 픽셀은 오른쪽, 오른쪽 위, 위 등을 향합니다.
기울기 단계
픽셀이 정면에서 얼마나 기우는지. 60°까지 2단계면 30°와 60°.
Pixel 커널
가로세로로 부드럽게 하지 않는 중앙 차분. 1px 턱이 1px로 남습니다.

예시: 기본 설정의 노멀 17가지(OpenGL 바이트)

양자화기가 쓰는 8방향 × 2단계 + 평면:

평면(기울기 15° 미만)                   128,128,255
30° 고리  오른쪽 191,128,238  위 128,191,238  오른쪽 위 173,173,238
          왼쪽    64,128,238  아래 128,64,238  왼쪽 아래  82, 82,238
60° 고리  오른쪽 238,128,191  위 128,238,191  오른쪽 위 206,206,191
          왼쪽    17,128,191  아래 128,17,191  왼쪽 아래  49, 49,191

입력 기울기 14° → 평면   40° → 30°   46° → 60°   80° → 60°

왼쪽 위와 오른쪽 아래도 같은 규칙입니다(30°에서 82,173,238과 173,82,238). 이런 맵의 모든 픽셀은 이 17가지 바이트 조합 중 하나라서, 스포이트로 골라 손으로 고치기도 쉽습니다.

이렇게 작동합니다

  • 밝기나 알파 채널에서 높이를 얻습니다.
  • 같은 강도가 같은 기울기가 되도록 정규화한 Sobel 3×3·Scharr·Sobel 5×5 커널.
  • OpenGL(+Y: Unity·Godot)이나 DirectX(−Y)와 X·Y 반전. 평평한 부분은 정확히 (128, 128, 255).
  • 변환·생성한 맵이 단위 길이 벡터로 디코딩됩니다(확인함).

사용 방법

  1. 스프라이트(또는 직접 그린 높이 맵)를 끌어다 놓습니다.
  2. 높이로 쓸 밝기나 알파, 커널, 강도를 고릅니다.
  3. 엔진이 기대하는 규약을 고릅니다.
  4. 노멀맵을 받습니다.

결과 확인

  • 내보낸 노멀맵의 색 수를 아무 편집기에서 세어 보세요. 픽셀아트 노멀 8 × 2라면 최대 17색입니다.
  • Lit 보기에서 조명을 스프라이트 위로 천천히 옮기세요. 띠가 서서히 번지지 않고 픽셀 단위로 넘어가야 합니다.
  • 엔진에서는 Nearest(Godot)나 Point(Unity) 필터를 쓰세요. 선형 필터는 이웃 노멀을 섞어 부드러운 그러데이션을 되살립니다.

문제 해결

증상유력한 원인확인 방법해결
조명을 받은 스프라이트가 자글자글하거나 디더링처럼 보임양자화하지 않은 기울기 노멀. 이 페이지의 랩 결과이거나 픽셀아트 노멀이 꺼져 있음노멀맵의 색이 수백 가지Studio 노멀맵 패널에서 픽셀아트 노멀 켜기
엔진에서 조명 띠가 흐릿함선형 텍스처 필터, 또는 절반 해상도로 계산되는 Unity 2D 조명400%로 확대하면 띠 경계가 부드러움Godot는 Nearest(Godot 도트 흐림 해결), Unity는 Point 필터와 Light Render Texture Scale 1
외곽선이 능선처럼 빛남어두운 외곽선을 낮은 높이로 읽어 그 가장자리가 경사가 됨높이 보기에서 외곽선을 따라 도랑이 보임밝기 디테일을 낮추거나 높이 브러시로 외곽선을 평평하게
모든 픽셀이 기울고 평평한 곳이 없음픽셀 크기 입체에 비해 강도가 커서 대부분 45°를 넘음대부분 픽셀이 60° 값(빨강이나 초록이 238 또는 17)강도를 낮추거나 기울기 단계를 3~4로

다른 방법

방법이럴 때 더 낫습니다
도트 편집기에서 노멀을 직접 찍기양식화된 그림. Godot 4.7.2에서 비춰 보니, 손으로 칠한 CC0 횃불은 모든 생성기의 맵이 평평한 맵보다 작가의 맵에서 더 멀었습니다(평평 26.6단계, Nerulio 36.2).
픽셀아트 노멀을 켠 Studio 텍스처 작업 공간베벨, 양자화, Godot와 같은 계산의 조명 미리보기, 검증된 Godot·Unity 내보내기가 필요할 때. 스프라이트 노멀맵 페이지에서 시작하세요.
Laigter프리셋과 자체 조명 미리보기가 있는 데스크톱 앱. 양자화한 도트 노멀 기능은 보이지 않았습니다.

출력 파일과 검증 방법

"측정 확인"은 내려받은 파일을 페이지 밖에서(Pillow·numpy·별도 파서) 다시 열어 그 속성을 측정했다는 뜻입니다. 게임 엔진에서 불러오는 것은 시험하지 않았습니다.

대상파일검증
Channel PNGs<name>-r/g/b/a.png (8-bit grey)측정 확인 numpy채널마다 바이트가 같고 완전히 투명한 텍셀 아래의 RGB도 유지됩니다.
Normal mapPNG · OpenGL (+Y) or DirectX (−Y)측정 확인 numpy디코딩한 벡터가 단위 길이(최대 오차 0.0002)이고, OpenGL과 DirectX는 초록 채널만 다릅니다.
Packed mask / ORMUnity HDRP mask · URP metallic · ORM (glTF, Godot)측정 확인 Pillow패킹된 바이트 확인: ORM 프리셋, AO 10 / 러프니스 80 / 메탈릭 220 → (10, 80, 220, 255).
Engine importUnity · Unreal · Godot미검증어떤 엔진에서도 불러오지 않았습니다.

검증 근거

채널 분리가 네 채널 모두 바이트 동일(최대 차이 0), 투명 텍셀 2048개가 RGB 유지. 가장자리 번짐은 알파 0인 텍셀 448개만 바꾸고 알파 바이트는 하나도 건드리지 않음. OpenGL ↔ DirectX는 초록(255 − g)만 다름. 변환한 노멀은 단위 벡터.

한계

  • 이 페이지의 텍스처 랩은 기울기만 계산합니다. 베벨·양자화·엔진 시험이 없고, 양자화 노멀은 Studio에 있습니다.
  • 어떤 생성기도 색에서 작가의 양식화된 음영을 계산해 내지 못합니다. 양자화는 생성한 맵을 손으로 찍은 듯 보이게 할 뿐, 정답으로 만들지는 않습니다.
  • 최대 기울기는 60°로 고정입니다.
  • 정확한 채널 바이트는 PNG에서만 보장됩니다. JPEG·WebP는 브라우저가 디코딩하며 "바이트 동일 아님"으로 표시합니다.
  • 인터레이스 PNG와 16비트 출력은 지원하지 않습니다. 정확 경로는 3,355만 픽셀까지입니다.
  • 노멀맵의 규약은 픽셀로 알아낼 수 없고 변환만 할 수 있습니다.
  • Unity·Unreal·Godot에서 불러오지 않았습니다. 채널 순서는 각 문서와 엔진 소스에 근거합니다.

버전과 출처

tests/normals.test.mjs는 허용된 방향과 기울기만 나오고 평면은 평면으로 남는지 확인합니다. Studio의 Godot 내보내기는 도트 사례 2건(6프레임 32px 횃불, 60프레임 48px 사무라이)을 Godot 4.7.2가 렌더해 확인한 모든 프레임이 1/255 이내였습니다. 이것은 내보내기 경로의 검증이며 양자화기 자체의 검증은 아닙니다. 이 페이지의 랩 맵은 수치로만 확인했습니다. 엔진 설정은 아래 Godot·Unity 문서를 따릅니다.

참고한 공식 문서

자주 묻는 질문

Laigter나 SpriteIlluminator 같은 건가요?

아닙니다. 높이나 밝기의 기울기를 계산하며 실루엣을 부풀리거나 경사를 만들지 않고 브러시도 없습니다. 세밀하게 하려면 높이 맵을 직접 그리세요.

Godot·Unity 조명에서 시험했나요?

아니요. 규약은 엔진 문서에 따르며, 맵은 수치로 확인했을 뿐 엔진에서 렌더링하지 않았습니다.

무료인가요? 계정이 필요한가요?

이 페이지의 기능은 모두 무료이며 계정 없이 쓸 수 있습니다. 워터마크나 막혀 있는 내보내기가 없습니다.

스프라이트가 업로드되나요?

아니요. Studio는 이 브라우저 탭 안에서 디코딩·패킹·내보내기를 합니다. 프로젝트는 브라우저(IndexedDB)에 자동 저장되며 .nerulio 파일로 저장할 수 있습니다.

Aseprite나 엔진 플러그인을 설치해야 하나요?

아니요. .aseprite 파일은 브라우저에서 읽고 씁니다. 엔진별 번들에는 그 엔진에 필요한 것이 들어 있습니다(Godot는 가져오기 설정과 씬, Unity와 Godot 타일셋은 작은 편집기 스크립트).