Generate 64×64 Minecraft player skins from a text prompt and/or a reference image, using a fine-tuned SDXL + PixelArt-XL + IP-Adapter pipeline.
text ─┐
├─► SDXL + PixelArt-XL fuse + pa_v2 LoRA ──► 64×64 RGBA ──► Minecraft
ref ──┘ (+ optional IP-Adapter-plus) skin PNG player skin
- Web UI with Generate / Edit tabs, 3D in-browser viewer, multi-variation gallery
- Pixel editor built in — touch up the AI output before exporting
- 38 curated example prompts included in
examples/showcase_skins/ - Honest about limits: outputs are interesting but not yet commercial-quality. See § Known Limitations.
This is a research prototype, not a polished product. I'm publishing it to (a) document what worked and what didn't across ~3 weeks of training experiments, and (b) get feedback / ideas from the community on where to take it next. See § Help Wanted.
- Demo
- Quick start
- How it works
- Project structure
- Training experiments — what we tried
- Known limitations
- Roadmap & ideas
- Help wanted
- Data sources & licenses
- Acknowledgments
- License
Browse examples/showcase_skins/contact_sheet.png for 38 sample outputs across
categories (knight, anime, pirate, animal, sci-fi, etc.) generated with the
pa_v2 LoRA at default settings.
The web UI (scripts/web_ui.py) provides:
- Text → skin generation (1–9 variations per prompt)
- Optional reference image input (IP-Adapter)
- 3D in-browser viewer (via skinview3d)
- Pixel editor for manual touch-up
- One-click Minecraft skin PNG download
- Python 3.11+
- NVIDIA GPU with ≥ 16 GB VRAM (RTX 3090/4080/4090, A5000, RTX 5070 Ti, etc.)
- CUDA 12.x
- ~10 GB disk for model weights + dependencies
# 1. Clone
git clone https://github.com/wjddusrb03/minecraft-skin-generator
cd minecraft-skin-generatorOption A — uv (recommended):
uv sync # installs everything including CUDA-12.8 PyTorchOption B — pip:
PyTorch (CUDA 12.x) needs a separate install command because the wheels are hosted on PyTorch's own index, not PyPI:
python -m venv .venv
# Windows
.venv\Scripts\activate
# macOS / Linux
source .venv/bin/activate
# 1. PyTorch + torchvision (CUDA 12.8 wheels)
pip install torch torchvision --index-url https://download.pytorch.org/whl/cu128
# 2. The rest of the project + the "ml" extras (diffusers, peft, etc.)
pip install -e ".[ml]"Why two steps for pip: this project pins CUDA-12.8 PyTorch via a custom index in
pyproject.toml under [tool.uv.sources] — that's a uv-only feature, so pip
users must specify the index by hand. uv sync handles both in one step.
The 1.4 GB fine-tuned LoRA is published on HuggingFace (see release notes for the
upload URL — TODO when uploaded). Place it under checkpoints/sdxl_lora_pa_v2/final/.
Until then, the LoRA must be trained locally — see § Training.
Windows: double-click run_web_ui.bat.
Cross-platform:
PYTHONPATH=. python scripts/web_ui.pyThe browser will open at http://localhost:7860. First model load takes ~30 s.
PYTHONPATH=. python scripts/generate_skin_pa.py \
"anime catboy with brown ears and orange hoodie" \
--seeds 0 42 1234 \
--reference path/to/character_art.png \
--reference-scale 0.6Outputs land in generated/.
┌──────────────────────┐
│ SDXL base (1024 ckpt) │
└──────────┬───────────┘
▼
fuse: nerijs/pixel-art-xl (locks the pixel-art style)
▼
attach: pa_v2 LoRA (taught the Minecraft skin UV layout +
short skin captions on 27.7K examples)
▼
optional: IP-Adapter-plus (color/style guidance from
a reference image)
▼
sample at 768×768 (28 steps, DPM-Solver++)
▼
NEAREST downscale → 64×64
▼
UV mask + symmetry enforcement + N-color quantization
▼
final skin.png (Minecraft 1.8+ format)
- SDXL has strong general visual priors, better than SD 1.5 for stylized character art.
- PixelArt-XL (
nerijs/pixel-art-xl) is fused at load time so every output starts with a pixel-art bias — no anti-aliased blur. - pa_v2 LoRA (rank 64, 18 K steps, 27.7K curated skins) teaches the model what Minecraft skin UV layouts look like, since SDXL has no prior for that specific format.
- IP-Adapter-plus lets a user supply a reference image (anime art, animal photo, another skin) whose palette/style transfers to the output without retraining.
- Post-processing (
src/inference/) enforces the Minecraft format invariants: hard pixel edges, left/right symmetry, limited palette, valid alpha mask.
We only have one consumer GPU. Full SDXL fine-tuning needs 40 GB+ VRAM. LoRA (rank 64 on 8 attention/projection modules) keeps trainable params at ~170 M (6.2 % of the UNet), trainable in bf16 + 8-bit Adam on a 16 GB card.
minecraft-skin-generator/
├── scripts/ # User-facing CLIs
│ ├── web_ui.py # Gradio web app (Generate / Edit / 3D viewer)
│ ├── generate_skin_pa.py # CLI: text → skin (pa_v2 + IP-Adapter)
│ ├── generate_skin_v4.py # Legacy SD 1.5 generator
│ ├── train_sdxl.py # LoRA training entrypoint
│ ├── curate_v16.py # Heuristic dataset curation
│ ├── caption_v17_qwen.py # Re-captioning with Qwen2.5-VL
│ ├── eval_grid.py # Build comparison grids
│ ├── composite_eval.py # LoRA weighted-merge experiment
│ ├── uv_composite_eval.py # UV-region composite experiment
│ ├── ip_adapter_test_pa_v2.py # IP-Adapter probe sweep
│ └── pa_v2_knob_sweep.py # Inference knob sweep
├── src/
│ ├── data/ # Skin format, UV layout, loader, dedup, render
│ ├── inference/ # SDXL/SD1.5 pipelines, quantize, symmetry
│ └── training/ # Dataset, configs, training loops
├── examples/
│ └── showcase_skins/ # 38 sample outputs + contact_sheet.png
├── run_web_ui.bat # Windows launcher
├── pyproject.toml # Python dependencies (uv-managed)
└── README.md # this file
Hidden from version control (see .gitignore):
checkpoints/— model weights (download from releases)data/raw/,data/*.jsonl— training data (see § Data sources)logs/,generated/,eval/— runtime outputs
This is the abbreviated record. Multiple LoRAs were trained over ~3 weeks in search of the best skin quality. Findings, in chronological order:
| Tag | Base | Data | Captions | Steps | Verdict |
|---|---|---|---|---|---|
v9 |
SD 1.5 | 15 K filtered (metadata_v3) |
short | 18 K | OK; v1 production for SD 1.5 |
pa_v1 |
SDXL + PixelArt-XL | 8 K bootstrap | hybrid | 18 K | First SDXL win; data ceiling at 8 K |
pa_v2 ⭐ |
SDXL + PixelArt-XL | 27.7 K (metadata_v13) |
hybrid (short+long) | 18 K | Current production. Loss 0.0251. Generalizes to anime / mecha / pirate / catboy / maid / demon. |
pa_v3 |
same | 32 K + synth (metadata_v15) |
random short/long | 18 K | Quality regression; self-distilled synthesis hurt diversity. |
pa_v4 |
same | 12.8 K strict curation + Qwen2.5-VL structured captions | short | 14 K | Clothing structure improved on some prompts; face quality regressed. Overall: worse than pa_v2. |
pa_v5 |
same, warm-start from pa_v2 | same as pa_v4 (metadata_v17) |
short | 10 K | Closer to pa_v2 (warm-start preserved face) but new captions didn't push past it. |
-
Data variety > data curation tightness. The pa_v4 attempt aggressively curated from 32 K → 12.8 K skins (palette 16-65, outer layers required, classic model only). This lost too much face/style diversity, and structured captions alone couldn't compensate. pa_v2's 27.7 K mixed dataset beat both curated runs.
-
Caption quality matters, but isn't a silver bullet. Replacing the verbose meta-commentary captions from
summykai/minecraft-skins-captioned-900k("This image depicts a blocky character typical of Minecraft...") with structured spatial captions (pirate: head red hat, torso black coat, arms bare, legs blue pants) helped clothing readability but not overall quality. -
Naive LoRA composition destroys quality. Weighted-merging
pa_v2+pa_v4adapters viaadd_weighted_adapterproduced muddier outputs than either alone — the two LoRAs were trained on different caption distributions, and their weight updates point in incompatible directions. -
UV-region image-level compositing is a small win. Cropping pa_v2's head strip (y=0..16 of the UV layout) onto pa_v4's body did give "best of both" in some prompts, but boundaries can look awkward.
-
Inference-time tuning helps only marginally. Sweeping guidance 5–11, steps 28–48, and stronger negative prompts gives subtle improvements but doesn't address the underlying "structural noise" issue.
-
IP-Adapter is the most useful inference-only addition. Adding
h94/IP-Adapter(plus variant, ViT-H/14) gives users style/color control via reference images without any retraining. Doesn't fix structural issues but unlocks an AI-assistance workflow.
I want to be direct about these — they're the reason this is published as "experimental" not "v1.0".
- Structural noise. Bodies and clothing often look like colored noise patterns shaped like a skin, rather than designed character outfits. Faces tend to be more coherent (small UV region, strong prior in data) but bodies are weak.
- Specific characters fail. Prompts like "Deku from My Hero Academia" or "Korean school boy" produce muddy/random outputs. The model only generalizes within the rough categories it saw during training (knight, wizard, anime girl, pirate, etc.).
- Fine details are impossible. At 64×64, a human face is ~8×8 pixels. "Freckles", "round green eyes", "stitched seams" are below the model's resolution budget.
- Short, archetypal prompts:
knight in red plate armor with golden trim - Color palette guided by reference images (IP-Adapter at 0.4–0.7)
- Variety: same prompt with different seeds gives different valid designs
- Specific real characters / IP (Deku, Naruto, etc.)
- Tiny facial features (freckles, specific eye shapes, scars)
- Logos, text, brand marks
- Complex multi-part outfits described in long prompts
- Non-humanoid mobs (animal-shaped skins are weak)
- Requires ~12 GB VRAM at inference, ~14 GB during training.
- One generation: ~10 s.
- Training pa_v2 (18 K steps) takes ~12–16 hours on an RTX 5070 Ti.
Things I'd try next, in roughly priority order. Contributions on any of these would be very welcome.
- Better prompt templates — curated library shipped with the UI for one-click testing
- PNG metadata — embed prompt/seed/timestamp in skin PNGs for reproducibility
- Multiple references — IP-Adapter supports multi-image embedding
- Inpainting workflow — let users re-generate only the head, only the torso, etc.
- Color picker / eyedropper in the pixel editor
- HuggingFace Space deployment — hosted demo
- Mask-weighted loss — weight UV regions (face, body) higher during training
- UV-template ControlNet — train a ControlNet on per-skin color-block hints to enforce region structure
- Curated NameMC scrape — augment training data with top-voted community skins (license permitting)
- DPO / preference tuning — generate pairs, hand-label, fine-tune on preferences
- Flux base model with pixel-art LoRA — community results suggest substantially higher quality than SDXL for pixel art
- Native 64×64 pixel diffusion — abandon SDXL's 768→64 downscale entirely
(we tried this once as
v12; it failed for lack of data, but is worth revisiting) - Two-stage generation — silhouette/segmentation map first, then color fill
If you find this project interesting, the most useful contributions are:
- Try it and report. What worked? What didn't? Which prompts fail? Open an issue with screenshots.
- Better prompts. Add to
examples/showcase_skins/index.tsvand submit a PR. - UI polish. The Gradio UI is minimal — see the Roadmap.
- Training experiments. All training infrastructure is in place — try a new
curation strategy, new caption style, or warm-starting from a different base.
src/training/train_sdxl_lora.pyaccepts--metadataand--init-lora-fromfor easy experimentation. - Evaluation methodology. We currently have no automated "is this skin good?" metric. Visual eval is too subjective. A learned aesthetic scorer would unlock a lot.
- Honest negative results. "I tried X, it didn't work because Y." Those are often more valuable than positive results.
This project was trained on publicly available Minecraft skin datasets:
| Dataset | Records used | License | Link |
|---|---|---|---|
summykai/minecraft-skins-captioned-900k |
~50 K sampled | MIT | HuggingFace |
neurlang/Minecraft-Skins-Captioned-1M |
~7 K added in v14+ | MIT | HuggingFace |
Each metadata record includes the original source, source_url, license,
and scraped_date so attribution can be traced. The raw skin PNGs themselves
are NOT redistributed in this repo — re-download from the source datasets
above using scripts/ingest_hf_rare.py (or your own ingestion script).
The pre-trained models we depend on:
| Model | Purpose | License |
|---|---|---|
stabilityai/stable-diffusion-xl-base-1.0 |
Base diffusion model | CreativeML Open RAIL++-M |
nerijs/pixel-art-xl |
Pixel-art style LoRA, fused into base | (check repo) |
h94/IP-Adapter (sdxl_models/plus) |
Reference-image conditioning | Apache 2.0 |
madebyollin/sdxl-vae-fp16-fix |
bf16/fp16-friendly VAE | MIT |
Qwen/Qwen2.5-VL-7B-Instruct |
Re-captioning pipeline (training only) | Apache 2.0 |
Our pa_v2 LoRA weights inherit from the SDXL base license. If you re-publish
generations commercially, please review the SDXL license terms.
- Diffusers, PEFT, transformers, accelerate by HuggingFace
- The skinview3d library for the in-browser 3D viewer
- The Minecraft skin dataset contributors at summykai and neurlang
- The
nerijs/pixel-art-xlLoRA author - IP-Adapter authors (h94)
This project was developed iteratively with Claude (Anthropic) as a coding collaborator — many of the design decisions, postmortem analyses, and training scripts were built through dialogue. See the commit history.
Code: MIT
Generated outputs: inherit the licenses of the underlying pretrained models (SDXL, PixelArt-XL, IP-Adapter, etc.). See NOTICE for the full list. Most notably, SDXL outputs fall under CreativeML Open RAIL++-M.
이 프로젝트는 텍스트 설명 또는 참고 이미지로 마인크래프트 스킨을 생성하는
실험적 AI 도구입니다. SDXL + PixelArt-XL + 자체 학습한 LoRA(pa_v2) +
IP-Adapter 조합.
3주간의 학습 실험 (pa_v1 ~ pa_v5) 결과 pa_v2가 가장 좋은 품질을
보였으나, 시중 마인크래프트 스킨 수준은 아직 도달 못함. 솔직하게:
- ✅ 일반 카테고리 (기사/마법사/해적/애니메이션 등) 적당히 됨
- ✅ 참고 이미지로 색감/스타일 전이 가능
- ❌ 특정 캐릭터 (예: 데쿠) 재현 불가
- ❌ 작은 디테일 (주근깨, 눈동자 모양) 64×64 해상도 한계
- ❌ "전체적으로 노이즈 패턴" 느낌이 여전
다음 단계 후보: Flux 모델 전환, mask-weighted loss, UV ControlNet, DPO 등. 자세한 내용은 위 Roadmap & Ideas 참조.
피드백 / 아이디어 / 개선 PR 환영합니다.