85 lines
5.7 KiB
Markdown
85 lines
5.7 KiB
Markdown
# P4 Live2D 래스터 파츠 프롬프트 검토 노트
|
|
|
|
검토일: 2026-06-27
|
|
|
|
## 검토 범위
|
|
|
|
- 기준: `docs/avatar-art/seoyeon/live2d-psd-v2/detailed-parts/detailed-parts-manifest.json`
|
|
- 대상: `docs/avatar-art/personas/P4/generation-plan.json`, `docs/avatar-art/personas/P4/prompts/*.txt`
|
|
- 요구 조건: 이미지 생성 없음, 시트 금지, 각 파츠는 900x1125 투명 캔버스 기준, `alphaBox`와 `originPercent` 유지
|
|
|
|
## 결론
|
|
|
|
현재 산출물은 바로 이미지 생성으로 넘기면 안 된다. P4 방향성 자체는 맞지만, manifest와 prompt 세트가 서로 다른 runner 출력이 섞인 상태로 보인다. 생성 전에 공통 runner로 한 번 더 정규화하는 게 맞다.
|
|
|
|
## 이미지 생성 전 차단 항목
|
|
|
|
1. `generation-plan.json`이 현재 `brow-sad-left` 1개 파츠만 담고 있다.
|
|
- 기준 manifest는 53개 파츠이고, `prompts/`에는 53개 txt가 있다.
|
|
- plan의 `parts`는 기준 manifest 53개와 1:1로 맞아야 한다.
|
|
- 각 part에는 최소 `id`, `file`, `alphaBox`, `originPercent`, `promptFile`, `priority`가 필요하다.
|
|
|
|
2. prompt 계약이 섞여 있다.
|
|
- `brow-sad-left.txt`는 영어 runner 형식이며 `#00ff00` 크로마키 배경과 "later normalization to 900x1125"를 지시한다.
|
|
- 다른 다수 prompt는 900x1125 투명 PNG를 직접 요구한다.
|
|
- 사용자 요구는 "900x1125 투명 캔버스"라서 최종 계약은 투명 PNG 기준이어야 한다. 중간 생성이 크로마키라면 plan에 후처리 단계를 명시해야 한다.
|
|
|
|
3. 52개 prompt 첫 줄에 리터럴 `$id`가 남아 있다.
|
|
- 예: `Live2D 래스터 파츠 $id 단일 PNG 생성`
|
|
- 모델이 실제 파츠명을 이해하지 못할 수 있으니 각 파일의 실제 part id로 치환해야 한다.
|
|
|
|
## P4 캐릭터 방향성 보정
|
|
|
|
- P4 하늘은 "고2, 학업/시험 불안, 완벽주의, 수면 부족, 자기검열"이 핵심이다.
|
|
- 울음이나 공포를 크게 키우기보다, 성실한 학생이 버티고 있는 긴장감이 보여야 한다.
|
|
- 머리: 기존 first-party P4 설정과 맞게 긴 생머리, 다크 브라운 계열을 유지한다.
|
|
- 눈: 큰 감정보다 피로한 상안검, 미세한 눈 밑 피로, 조심스러운 정면 시선이 좋다.
|
|
- 교복: 단정한 네이비 그레이 교복, 학교명/로고/문자 없음. 시험기간의 약한 구김 정도만 허용한다.
|
|
- 표정: 기본은 `anxious`에 가까워야 한다. `sad`도 울음보다 걱정과 압박감 중심으로 둔다.
|
|
|
|
## 파츠별 보정 제안
|
|
|
|
- `hair-back-base`: 기준 manifest의 `alphaBox`가 `null`이다. 새 픽셀을 만들지 말고 완전 투명 placeholder로 처리하거나 생성 대상에서 제외하는 게 맞다.
|
|
- `tear-left`, `tear-right`: 큰 눈물방울보다 눈가 수분감/고인 눈물 오버레이로 제한해라. P4는 위기/비탄 캐릭터가 아니라 시험 불안 캐릭터다.
|
|
- `brow-sad-left`, `brow-sad-right`: "crying"보다 "anxious / worried brow"로 재명명하거나 prompt 안에서 걱정 중심이라고 명시해라.
|
|
- `mouth-anxious`: 자동사고 문장을 직접 넣으면 출력에 글자가 생길 위험이 있다. 문장은 빼고 "입술을 살짝 누른 긴장선"처럼 시각 묘사로만 두는 편이 낫다.
|
|
- `eye-left`, `eye-right`: 통합 눈 파츠와 세부 눈 파츠가 함께 있으니, runner가 실제로 둘 다 생성한다면 서로 중복되지 않도록 용도를 명시해야 한다.
|
|
- `outfit`, `outfit-inner`, `outfit-outer`: 세 파츠는 겹침이 크다. 전체 outfit은 preview 합성용, inner/outer는 분리 리깅용이라고 역할을 분명히 적어라.
|
|
|
|
## Priority 제안
|
|
|
|
- P1: `face-base`, `face`, `hair-front`, `hair-bangs`, `hair-back-left`, `hair-back-right`, `body`, `outfit`
|
|
- P2: `neck`, `clavicle`, `outfit-inner`, `outfit-outer`, `ribbon`, `ear-left`, `ear-right`, `hair-side-*`
|
|
- P3: `eye-white-*`, `iris-*`, `pupil-*`, `highlight-*`, `lash-*`, `eyelid-*`, `nose`, `blush-*`
|
|
- P4: `brow-left`, `brow-right`, `brow-sad-left`, `brow-sad-right`, `mouth-neutral`, `mouth-open`, `mouth-anxious`
|
|
- P5: `mouth-warm`, `mouth-tired`, `mouth-sad`, `mouth-startled`, `mouth-open-small`, `tear-left`, `tear-right`, `hair-back-base`
|
|
|
|
P4의 기본 표정이 `anxious`라서 `brow-sad-*`, `eyelid-*`, `mouth-anxious`는 일반 파생 표정보다 먼저 확인하는 편이 낫다.
|
|
|
|
## Runner 보정 체크리스트
|
|
|
|
1. 기준 manifest 53개 파츠를 그대로 읽어 plan의 `parts`를 다시 만든다.
|
|
2. prompt 파일 수, plan parts 수, 기준 manifest parts 수가 모두 53인지 확인한다.
|
|
3. 모든 prompt에서 `$id` placeholder가 0건인지 확인한다.
|
|
4. `alphaBox`와 `originPercent`가 기준 manifest와 정확히 같은지 확인한다.
|
|
5. 배경 계약을 하나로 고정한다. 최종 산출물이 투명 PNG라면 prompt와 plan 모두 그 기준으로 써라.
|
|
6. `sheet`, `sprite sheet`, `grid`, `multiple variants`, `text`, `logo`, `watermark` 금지를 모든 prompt에 유지한다.
|
|
|
|
## 빠른 검증 커맨드
|
|
|
|
```powershell
|
|
$ErrorActionPreference = 'Stop'
|
|
[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)
|
|
$OutputEncoding = [System.Text.UTF8Encoding]::new($false)
|
|
|
|
$base = 'D:\workspace\vignette\docs\avatar-art\personas\P4'
|
|
$source = Get-Content 'D:\workspace\vignette\docs\avatar-art\seoyeon\live2d-psd-v2\detailed-parts\detailed-parts-manifest.json' -Raw -Encoding UTF8 | ConvertFrom-Json
|
|
$plan = Get-Content (Join-Path $base 'generation-plan.json') -Raw -Encoding UTF8 | ConvertFrom-Json
|
|
|
|
[pscustomobject]@{
|
|
SourceParts = $source.parts.Count
|
|
PlanParts = @($plan.parts).Count
|
|
PromptFiles = @(Get-ChildItem (Join-Path $base 'prompts') -Filter '*.txt').Count
|
|
IdPlaceholders = @(Select-String -Path (Join-Path $base 'prompts\*.txt') -Pattern '\$id').Count
|
|
}
|
|
```
|