아트 디렉션 — Pour Decisions
화면의 약 80%는 모의 픽셀입니다. 미술 예산은 재료 팔레트, 발광/후처리, UI, 아이콘, Steam 캡슐 이미지에만 사용됩니다. 하드 규칙: 생성형 AI 이미지를 사용하지 않습니다(Steam 공개 규정 위반). 외부 자료는 화이트리스트(
docs/research/03_assets_legal.md)에 등록된 것만 사용하며,docs/art/ASSET_LICENSES.md에 기록합니다. 우리의 강점: 셰이더, 절차적 드로잉, 색상 수학. 약점: 손 그림 일러스트레이션 → 모든 결정은 '코드로 계산한다'는 방향으로 기울입니다.
추가 자료(세부 사항이 필요할 때만 참조):
references/material-palette.md— 14가지 재료의 램프(Ramp), HEX, 노이즈 및 발광 매개변수(시작값)references/urp-postfx.md— URP Volume 레시피, CRT 셰이더 사양, Pixel Perfect 설정references/ui-juice.md— Balatro UI 분해, 점수 애니메이션 타이밍, Easing 값references/steam-capsule.md— 캡슐 이미지 사양, Valve 규칙, 일러스트레이터가 아닌 사람을 위한 접근법
1. 색상 이론 (이 순서대로 결정)
1.1 Value(명도)가 Hue(색상)보다 우선
- 먼저 그레이스케일로 화면을 디자인합니다: 그레이스케일로 변환(
luma = 0.299R + 0.587G + 0.114B또는 OKLab L) 후 배경, 재료, UI가 여전히 레이어를 구분할 수 있어야 합니다. 그레이스케일에서 구분되지 않는 것은 색상을 바꿔도 해결되지 않습니다. - 본 게임의 명도 계층(목표 L, OKLab 0–1):
레이어 L 범위 내용 배경/비커 내벽 0.12–0.22 어둡고, 낮은 채도, 차가운 보라색 계열 불활성 재료(stone, sand, gunpowder, seeds) 0.30–0.65 중간 명도, 중저 채도 유체(water, oil, acid) 0.35–0.75 중간 명도, 동적 움직임과 반투명으로 식별 반응/발광(fire, lava, spark, 점수 입자) 0.75–1.0 + HDR 전체에서 가장 밝고 채도 높음 UI 숫자/버튼 0.85–1.0 독립 패널 위에 위치, 패널 배경색으로 구분 - 규칙: 초점은 가장 밝고 채도가 높은 것이어야 합니다. 초점 = 반응이 일어나는 위치 + 점수 숫자. 다른 것은 이것보다 밝아서는 안 됩니다.
1.2 색상 변이(Hue shifting)
- 하나의 램프(Ramp, 어두움→밝음)는 단순히 명도만 조절하지 않습니다: 밝은 부분은 따뜻하게(노란색), 어두운 부분은 차갑게(파랑/보라) 치우칩니다. 각 단계당 10–20° 치우칩니다, 20°가 상한선입니다(Slynyrd Pixelblog 1).
- 그림자에 '검정 더하기', 밝은 부분에 '흰색 더하기'를 사용하지 마십시오 → 지저분해지고 회색이 됩니다(베개/진흙 효과).
- 채도 곡선: 중간 부분이 가장 높고 양 끝으로 갈수록 낮아지지만 0%나 100%가 되지는 않습니다; 어두운 색상이 밝은 색상보다 채도가 높을 수 있습니다. 높은 채도와 높은 명도를 동시에 사용하지 마십시오(눈부심), 그 위치는 발광 재료를 위해 남겨둡니다.
1.3 채도 계층
- 채도는 두 번째 주의 끌개입니다. 세 가지 등급으로 나눕니다:
- 높음: 발광 재료, 점수 효과, Mult 숫자.
- 중간: 일반 재료의 주요 색상, 상호작용 가능한 UI.
- 낮음: 배경, 비커 유리, 패널, 비상호작용 텍스트.
- 배경 채도 ≤ 25%(HSV S). 전체 화면은 대부분 낮은 채도, 소수만 높은 채도여야 초점이 생깁니다.
1.4 제한된 팔레트(Limited palette)
- 단일 메인 팔레트를 사용하며, 모든 재료, UI, 아이콘은 여기서만 색상을 가져옵니다. 장점: 일관성이 자동으로 유지되며 AI 에이전트가 제멋대로 색상을 선택하지 않습니다.
- 시작점: Resurrect 64(lospec.com/palette-list/resurrect-64), 64색, 램프에 hue shift가 이미 적용되어 있고 어두운 부분은 보라색 계열이며, 어두운 배경+발광에 적합합니다. 대안: Endesga 32, Apollo(46색), AAP-64. 팔레트 색상 값 자체는 저작권 보호를 받지 않으며, Lospec 페이지에서 출처를 기록할 수 있지만 필수는 아닙니다(가정, 낮은 위험).
- 자체 구축 프로세스(필요한 경우):
- 선명한 중간색 하나를 선택합니다(S, B가 가장 중요, H는 자유).
- 양쪽으로 5–9단계를 확장합니다: B는 어두움에서 밝음으로(100에 가까울수록 단계 간격이 작아짐), S는 중간 부분이 가장 높음, H는 각 단계당 +10~20°(밝을수록 따뜻해짐).
- 전체 램프를 H 45° 회전시켜 다른 색상 계열을 생성합니다.
- 중간 부분을 복사하고 채도를 낮춥니다 → 중성 회색 램프(UI/배경용).
- 모든 색상 값을
Game/Assets/Art/Palette/palette.png(1픽셀당 1색) + C#PaletteSO에 저장합니다. 코드는 인덱스만 참조하고 HEX를 하드코딩하지 않습니다.
- 허용되는 예외: HDR 발광 값(>1.0)은 팔레트 색상에 강도를 곱하여 생성해야 하며, 새로운 색상을 만들지 않습니다.
2. 가독성 규칙
- 그레이스케일 테스트: 색상을 변경할 때마다 스크린샷을 찍어 그레이스케일로 변환하여 확인합니다(QA 체크리스트 항목 1).
- 인접한 재료는 value 또는 hue 중 적어도 하나에서 명확한 차이가 있어야 합니다: ΔL(OKLab) ≥ 0.08 또는 Δhue ≥ 40°. 혼동하기 쉬운 조합은 특별히 처리해야 합니다:
- fire vs lava vs sand(모두 따뜻한 색상) → fire은 가장 밝고 움직임이 있음, lava는 어두운 빨간색 바탕에 밝은 무늬가 있고 느림, sand는 발광하지 않고 중간 명도.
- acid vs plant(모두 녹색) → acid는 황록색+약간 발광+거품, plant는 진한 청록색이며 발광하지 않음.
- steam vs smoke → steam은 흰색에 가깝고 차갑고 빠르게 상승함, smoke는 회보라색이고 더 어둡고 천천히 퍼짐.
- 색맹: 빨강/초록만으로 구분해서는 안 됩니다. 각 재료는 또 다른 비색상 특징(움직임, 텍스처 노이즈 유형, 발광, 투명도)을 가지고 있어야 합니다. Coblis 또는 셰이더로 적색맹(deuteranopia)을 시뮬레이션하여 확인합니다.
- UI와 게임 화면 분리: 시뮬레이션 영역은 재료 픽셀만 있습니다. UI는 비커 외부의 패널에 배치하며, 패널은 중성 저채도 색상+1px 테두리를 사용합니다. UI는 어떤 재료 색상도 배경색으로 사용하지 않습니다("이게 모래인가?" 혼동 방지). 점수 숫자는 시뮬레이션 영역으로 떠다닐 수 있지만, 테두리/그림자가 있어야 하며 0.6초 내에 사라져야 합니다.
- 초점은 하나만: 동시에 '눈에 띄는' 것은 한 그룹만 있어야 합니다. 대량 반응 시, 부차적인 입자의 글로우(Glow)를 낮춥니다(§4의 glow budget 참조).
- 실루엣: 비커, 버튼, 아이콘의 외형은 순수 검정색 실루엣으로도 식별 가능해야 합니다.
3. 픽셀 아트 기본
- 고정 픽셀 스케일: 시뮬레이션 그리드 1 cell = 1 게임 픽셀. UI 픽셀 에셋도 동일한 배율을 사용합니다(권장 sim 해상도 320×180 또는 384×216, 1080p/1440p/4K로 정수배 확대). 다른 배율을 혼합하는 것을 금지합니다.
- 믹셀(Mixels) 금지: 모든 픽셀 에셋은 정수가 아닌 배율로 확대/축소하거나 회전해서는 안 됩니다(회전하면 크기가 다른 픽셀이 생성됨). 회전이 필요한 UI(카드 흔들기)는 고해상도 UI 레이어를 사용하거나, 저해상도 렌더 텍스처에서 회전한 후 정수배로 확대합니다.
- 램프(Ramp): 각 재료는 3–5색입니다(참조: references/material-palette.md). 5색 이상은 1px 입자에서 구분할 수 없습니다.
- 디더링(Dithering) 올바른 사용: (a) 넓은 면적의 그라데이션(배경, 비커 유리 반사), (b) 반투명 효과(연기, 증기에 체커보드/Bayer 4×4 알파 사용)에만 사용합니다. 작은 물체, 아이콘, 텍스트에는 디더링을 사용하지 마십시오; 움직이는 입자에 월드 공간 디더링을 사용하지 마십시오(깜빡임 발생), 디더 패턴은 화면 공간 또는 셀 좌표에 고정해야 합니다.
- 수동 안티앨리어싱(Anti-aliasing): UI 아이콘과 로고의 대각선/곡선에만, 선 색상과 배경 색상 사이의 중간색으로 1px을 채웁니다. 외곽선과 투명 배경 사이의 경계에는 AA를 적용하지 마십시오(배경이 바뀌면 더러운 테두리가 나타남).
- 밴딩(Banding) 방지: 등고선처럼 외곽선을 따라 평행하고 동일한 너비의 색상 띠가 생기지 않도록 합니다.
- 베개 셰이딩(Pillow shading) 금지: 광원 방향은 고정(왼쪽 위), 그림자는 "가장자리에서 중앙으로 갈수록 밝아지는" 방식이 아닙니다.
- 글꼴: 픽셀 글꼴은 화이트리스트(Cubic 11, Fusion Pixel Font, Kenney Fonts)에 등록된 것만 사용합니다; 원시 픽셀 크기의 정수 배수로 표시합니다; TMP는 Point 샘플링 비트맵 또는 높은 샘플링 SDF를 사용합니다.
4. 낙사 게임에서 재료에 색상을 입히는 방법
참고 작품 관찰(Noita, The Powder Toy, Sandspiel, Sandustry; 일부는 관찰 추론이며 "미검증"으로 표시):
- 입자별 색상 노이즈: 입자 생성 시 랜덤 바이트 하나를 저장하고(Sandspiel의
ra), 렌더링 시 이 값을 사용하여 재료 램프 내에서 색상을 선택하거나 밝기를 조정합니다 → 모래, 돌에 입자 감이 생깁니다. 노이즈는 생성 시 고정되며, 입자가 이동해도 색상이 따라갑니다(매 프레임 다시 추출하지 마십시오, 깜빡임 발생). - 고체는 월드 좌표 텍스처 사용: Noita 재료는
texture_file을 지정할 수 있으며, 고체는 월드 위치에 따라 텍스처를 샘플링합니다; 낙하 입자가 될 때 해당 순간의 색상을 유지합니다(wiki 속성 추론, 세부 사항 미검증). 우리의 stone/glass/ice는 셀 좌표 해시로 램프를 샘플링하여 안정적인 텍스처를 생성할 수 있습니다. - 유체는 노이즈보다 움직임에 의존: water/oil 노이즈 진폭은 작습니다(±3% L). 여기에 (a) 표면의 한 픽셀 더 밝은 하이라이트, (b) 속도/시간에 따른 미세한 깜빡임을 더합니다.
- 발광 재료(Emissive): Noita에는
gfx_glow(0–255)와gfx_glow_color가 있습니다. 우리 방식: 각 셀은emission값을 가지며, 렌더링 시 HDR 색상 = 팔레트 색상 × (1 + emission × k)로 계산되어 URP Bloom에 전달됩니다. fire, lava, spark, acid(약함), 뜨거운 glass가 발광합니다. - 온도 색상: The Powder Toy에는 열 표시 모드가 있습니다; 우리는 그 정신만 차용합니다 — 물질 온도가 높을 때 흑체 색상(어두운 빨강→주황→노랑→흰색)을 따라 밝은 쪽으로 치우치고, 냉각되면 원래 램프로 돌아옵니다.
- 반응 섬광(Reaction flash): 반응이 발생한 해당 셀의 emission을 해당 프레임에 최대로 올리고 2–4프레임에 걸쳐 감쇠시킵니다 → 플레이어가 반응을 '볼' 수 있습니다. 이것이 가장 중요한 가독성 피드백입니다.
- 글로우 예산(Glow budget): 동시에 발광하는 셀 수가 N(시작값 2,000)을 초과하면, 각 셀의 emission을 비례적으로 낮추어 전체 밝기를 안정적으로 유지하고 화면이 과도하게 밝아지는 것을 방지합니다.
구현 핵심: 시뮬레이션 데이터(material id, random byte, temperature, emission)를 RGBA8 텍스처로 패킹하여 업로드하고, 프래그먼트 셰이더가 팔레트 LUT(256×1 또는 materials×ramp 크기의 작은 텍스처)를 조회하여 색상을 결정합니다. CPU는 색상을 계산하지 않습니다.
5. 후처리(Unity 6 URP) 핵심
자세한 레시피는 references/urp-postfx.md를 참조하십시오. 핵심:
- 카메라 HDR 켜기; Bloom Threshold 1.0–1.1(HDR>1인 발광 재료만 번지게 하고 일반 재료는 Bloom 처리하지 않음), Intensity 0.6–1.0부터 조정, Scatter 0.6–0.75, High Quality Filtering 켜기(깜빡임 감소).
- 톤 매핑(Tonemapping): Neutral(ACES는 색상을 변경하고 팔레트를 어둡게 만듦). 또는 None + 직접 제어.
- Color grading LUT: 미세한 통일화만 수행(분위기 전환 "난로 느낌"), 팔레트의 value 구조를 변경하지 않음;
Color Lookup기여도 ≤ 0.5. - CRT/스캔라인은 기본적으로 꺼져 있으며, 설정 메뉴에서 켜기/끄기와 강도를 제공합니다; Steam 스크린샷/트레일러는 "꺼짐"을 기본으로 하고, 최대 1장의 켜진 스크린샷만 허용합니다.
- Pixel Perfect Camera(URP 내장, 오래된 2D Pixel Perfect 패키지 설치 금지): Grid Snapping = Upscale Render Texture; Bloom은 확대된 해상도에서 처리해야 사각형 모양의 광택이 나타나지 않습니다.
6. UI 스타일(Balatro 스타일 score-attack)
자세한 타이밍은 references/ui-juice.md를 참조하십시오. 필수:
- 색상이 곧 점수 언어입니다: Chips = 파랑, Mult = 빨강, Money = 금, ×Mult = 빨간 바탕에 흰 글자. 게임 전체에서 고정되며 변경할 수 없습니다.
- 항목별 결산: 반응이 하나씩 튀어나옵니다(+chips / +mult). 각 항목은 number pop(scale 1.0→1.3→1.0, overshoot easing), 음정이 올라갑니다.
- 진동은 크기 등급별로 구분: 점수가 클수록 진폭이 커지고 시간이 길어집니다; 최대 8px / 1°를 초과하지 않습니다. "화면 진동 줄이기" 옵션을 제공합니다(접근성).
- 숫자는 항상 읽을 수 있어야 합니다: 굵은 테두리(2px 어두운 색상) + 그림자; 큰 숫자는 과학적 표기법을 사용하기 전에 천 단위 구분 기호를 먼저 사용합니다.
- Juice가 정보를 가려서는 안 됩니다: 입자와 섬광이 chips×mult와 목표 점수를 가려서는 안 됩니다.
7. 아이콘(16–32px)
- 먼저 16px 버전을 만든 다음, 32px로 확대하여 세부 사항을 추가합니다(32px를 16px로 축소하지 마십시오).
- 하나의 아이콘 = 하나의 개념, 하나의 실루엣; 1px 어두운 색상 외곽선(팔레트에서 가장 어두운 색상)으로 어떤 배경에서든 식별 가능하게 합니다.
- 각 아이콘은 최대 4–5색(외곽선, 어두움, 중간, 밝음, 강조). 광원은 항상 왼쪽 위입니다.
- Vial(재료 병) 아이콘: 병 모양은 통일하고, 액체 색상과 작은 기호(불꽃, 물방울, 해골…)만 변경합니다 → 플레이어는 색상+기호 이중 인식으로 식별합니다(색맹 친화적).
- Catalyst 유물: 희귀도에 따라 외형 구분(원형 / 육각형 / 별 모양 테두리), 테두리 색상은 희귀도에 따라(회색, 파랑, 보라, 금).
- 절차적 생성: 아이콘은 C# 또는 Python으로 '모양 + palette index'를 사용하여 PNG를 출력할 수 있으며, 재현 가능하고 일괄 수정 가능합니다.
- 테스트: 실제 UI 배경에서 100% 축소로 확인; 50%로 축소해도 서로 다른 아이콘을 구분할 수 있어야 합니다.
8. Steam 캡슐 이미지
자세한 내용은 references/steam-capsule.md를 참조하십시오. 핵심:
- 사양: Header 920×430, Small 462×174, Main 1232×706, Vertical 748×896, Library 600×900, Hero 3840×1240(텍스트 없음), Logo 투명 PNG.
- Valve 규칙: 캡슐에는 게임 화면/아트와 게임 이름 로고(및 공식 부제목)만 넣을 수 있습니다; 평점, 수상, 할인 문구, 기타 텍스트는 넣을 수 없습니다.
- 우리의 접근 방식(일러스트레이터가 아니어도 잘할 수 있음): 글꼴 기반의 큰 로고 + 고해상도 시뮬레이션 렌더링(폭발적 반응 순간) + 하나의 명확한 초점. 로고 자체가 낙사입니다: 시뮬레이션으로 문자를 "부어서" 만들거나 문자를 다른 재료로 구성합니다.
- 먼저 Small 캡슐(120×45 미리보기에서도 로고가 보여야 함)을 만든 다음, 큰 사이즈로 확장합니다.
9. 작업 흐름 규칙
- 새로운 색상 → 먼저 팔레트 파일에 추가한 후 참조합니다; PR/커밋 설명에 추가된 인덱스를 나열합니다.
- 모든 외부 자료(글꼴, Kenney UI) →
docs/art/ASSET_LICENSES.md에 기록합니다(파일명, URL, 저자, 라이선스, 날짜). - 모든 절차적 아트(아이콘, 로고, 캡슐 이미지)는 생성 스크립트와 매개변수를 보존하여
Game/Tools/ArtGen/또는tools/에 배치하고, 다시 실행할 수 있어야 합니다. - 불확실한 매개변수는 "시작값"으로 표시하고, 프로토타입 플레이 후 references에 다시 채웁니다.
10. 제출 전 시각 QA 체크리스트(pre-commit)
- 그레이스케일 스크린샷: 배경 / 재료 / 발광 / UI 네 계층의 명도가 구분됨
- 초점(반응 지점, 점수 숫자)이 화면에서 가장 밝고 채도가 높음
- 새로 추가된 색상이 모두 팔레트에서 왔음(하드코딩된 HEX 없음)
- 인접하여 혼동하기 쉬운 재료(fire/lava/sand, acid/plant, steam/smoke)가 100% 및 50% 축소에서도 구분됨
- 색맹 시뮬레이션(deuteranopia, protanopia)에서도 재료와 Chips/Mult를 식별할 수 있음
- 믹셀(Mixel) 없음: 픽셀 에셋이 모두 정수 배율로 확대/축소되었고 회전되지 않음
- 입자 색상 노이즈가 이동 중 깜빡이지 않음
- Bloom: 일반 재료는 번지지 않음; 500개 이상의 반응이 동시에 발생해도 화면이 과도하게 밝아지지 않음(glow budget 적용)
- UI 텍스트에 테두리가 있고, 가장 밝은 폭발 위에서도 읽을 수 있음
- 화면 진동 ≤ 8px, "진동 줄이기" 옵션을 끄면 완전히 진동하지 않음
- CRT 필터는 기본적으로 꺼져 있고, 켜기/끄기가 제대로 작동함
- 아이콘 16px 원본 크기에서 식별 가능하고, 서로 구분됨
- 1080p, 1440p, Steam Deck 1280×800에서 모두 정수배 확대 또는 올바른 레터박스 적용됨
- 생성형 AI로 생성된 이미지 없음; 새 자료는 라이선스가 등록됨
- 스크린샷이
docs/art/qa/<날짜>_<기능>.png에 저장되어 회고 가능함
출처
- Slynyrd Pixelblog 1 – Color Palettes(hue shift ≤20°, 채도 곡선): https://www.slynyrd.com/blog/2018/1/10/pixelblog-1-color-palettes
- Lospec Palette List: https://lospec.com/palette-list ; Resurrect 64: https://lospec.com/palette-list/resurrect-64 ; Endesga 32: https://lospec.com/palette-list/endesga-32 ; Apollo: https://lospec.com/palette-list/apollo ; AAP-64: https://lospec.com/palette-list/aap-64
- Lospec 픽셀 아트 튜토리얼 인덱스: https://lospec.com/pixel-art-tutorials
- GameDev.net – Color Palettes: https://www.gamedev.net/articles/visual-arts/color-palettes-r4964/
- Noita wiki – Making a custom material(
texture_file,gfx_glow): https://noita.wiki.gg/wiki/Modding:_Making_a_custom_material - 80.lv – Noita 낙사 시뮬레이션: https://80.lv/articles/noita-a-game-based-on-falling-sand-simulation/
- Making Sandspiel(입자별
ra로 밝기 결정, GPU 채색): https://maxbittker.com/making-sandspiel - The Powder Toy 소스 코드: https://github.com/The-Powder-Toy/The-Powder-Toy
- Unity URP Bloom: https://docs.unity3d.com/Packages/[email protected]/manual/post-processing-bloom.html
- Unity URP Pixel Perfect Camera: https://docs.unity3d.com/6000.0/Documentation/Manual/urp/2d-pixelperfect-ref.html
- Balatro 피드백 디자인 분해: https://blakecrosley.com/guides/design/balatro
- Steamworks 상점 이미지 에셋: https://partner.steamgames.com/doc/store/assets/standard
- presskit.gg Steam Capsule Art Guide: https://presskit.gg/field-guides/steam-capsule-art-guide
- Coblis 색맹 시뮬레이터: https://www.color-blindness.com/coblis-color-blindness-simulator/