Hugo-Dz / spritefusion-sprite-normals
git clone https://github.com/Hugo-Dz/spritefusion-sprite-normals.git
A tool to generate normal maps from any sprite and animated sprite sheet.
+255
stars, 24h · #55
+255
stars, 7 days · #237
+255
stars, 30 days · #1,015
255
★ total · +255% this week
14
forks · 0 open issues
Star history starts 2026-10-20; the chart appears after the second daily snapshot.
LanguageRust
LicenseMIT
Created2026-10-19 (1d ago)
Last pushtoday
Watchers2
OwnerUser
GitHub topics
Links
- GitHub: github.com/Hugo-Dz/spritefusion-sprite-normals
- Homepage: https://www.spritefusion.com/sprite-normals
- Releases · Issues · Hacker News mentions
README excerpt
# Sprite Fusion Sprite Normals
- **Online version**: https://www.spritefusion.com/sprite-normals
- **API**: https://www.spritefusion.com/docs/pixel-art-generator/api/generate-and-transform-images#normal-maps
- **MCP**: https://www.spritefusion.com/docs/pixel-art-generator/api/mcp
A tool to generate normal maps for pixel art sprites and animations. Written in Rust, available as a CLI and a WebAssembly library.
## Why ?
**Normal maps let 2D sprites react to dynamic lighting. Ideal for 2.5D games.**
Features:
- ✅ Generate surface relief from a sprite's silhouette and shading.
- ✅ Keep the original pixel resolution and transparency.
- ✅ Process sprites, sprite sheets, and animations locally.
## Perfect for
- **2D games** with moving lights and normal-mapped sprites.
- **Pixel art animations** that need matching normal-map frames.
- **Asset pipelines** using a native CLI or browser-based processing.
## 💻 CLI
### Build from source
Requires Rust 1.85 or newer. From this directory:
[code]
The binary is available at `target/release/spritefusion-sprite-normals`. To install it locally:
[code]
### Usage
[code]
- ` `: PNG sprites or sheets, GIF, or APNG files.
- `-o `: Output normal PNG for one input.
- `--output-dir `: Output directory for a batch.
- `--normal-strength `: Overall strength. Defaults to `1.5`.
- `--detail-strength `: Relief from painted shading. Defaults to `6`.
- `--detail-scale `: Shading smoothing. Defaults to `0.6`.
- `--shape-strength `: Silhouette volume. Defaults to `1.15`.
- `--frame-size `: Isolate uniform PNG sheet cells.
- `--normal-format directx`: Reverse the green channel. Defaults to OpenGL.
- `--force`: Replace existing outputs. Input files are protected.
[code]
Without an output path, maps are saved beside their inputs as ` _n.png`. Run `spritefusion-sprite-normals --help` for every option.
### Animations
GIF and APNG inputs, and PNG sheets with `--frame-size`, produce three files:
- `walk_n.png`: lossless normal-map atlas.
- `walk_n.color.png`: color atlas with the same frame layout.
- `walk_n.frames.json`: atlas dimensions, frame dimensions, columns, frame count, and timing.
Frames are arranged in row-major order. `delays_ms` contains `[numerator, denominator]` pairs in milliseconds. PNG sheets keep their layout and receive a default 100 ms frame delay. Source loop counts are not exported.
Normal PNGs are data textures: disable sRGB sampling in your engine. Use artwork at its native pixel resolution. Generation estimates relief from color and shape; painted highlights can also become surface detail.
## 🌐 Web (WASM)
Build with the `wasm32-unknown-unknown` Rust target and wasm-bindgen CLI `0.2.126`:
[code]
Use the generated package in your project:
[code]
Pass a `Uint8Array` and `"{}"` for default settings. Optional keys are `strength`, `detail`, `smoothing`, `volume`, `frame_width`, `frame_height`, and `directx`. Returned arrays own their bytes and remain valid after `free()`.
The CLI and WASM module use the same