🇬🇧 English
Sprite2Normal is an ultra-lightweight neural network (~7 MB) designed to instantly generate tangent-space Normal Maps from flat 2D sprites, textures, and pixel art.
Built for indie game developers to easily add dynamic 2D lighting to their games without manually drawing height or normal maps.
Trained completely from scratch with a custom lightweight U-Net architecture.
✨ Features
- Ultra-Compact: Model file is only ~7 MB in ONNX format.
- CPU & GPU Friendly: Runs in 3–10 ms on standard CPUs without requiring a dedicated GPU.
- Engine Compatible: Generates standard OpenGL tangent-space normal maps (X: Red, Y: Green, Z: Blue), ready for Godot, Unity, GameMaker, Unreal Engine, and custom shaders.
- Dynamic Resolution: Fully convolutional architecture supporting sprites of any size.
🚀 Quick Start (Python)
1. Install dependencies
pip install onnxruntime pillow numpy
2. Inference script
import numpy as np
from PIL import Image
import onnxruntime as ort
session = ort.InferenceSession("sprite2normal.onnx", providers=["CPUExecutionProvider"])
input_name = session.get_inputs()[0].name
output_name = session.get_outputs()[0].name
img = Image.open("character.png").convert("RGB")
orig_w, orig_h = img.size
img_resized = img.resize((128, 128), Image.Resampling.BILINEAR)
arr = np.array(img_resized, dtype=np.float32) / 255.0
arr = np.transpose(arr, (2, 0, 1))
input_tensor = np.expand_dims(arr, axis=0)
output = session.run([output_name], {input_name: input_tensor})[0][0]
pred = (output + 1.0) * 0.5 * 255.0
pred = np.clip(pred, 0, 255).astype(np.uint8)
pred = np.transpose(pred, (1, 2, 0))
normal_map = Image.fromarray(pred).resize((orig_w, orig_h), Image.Resampling.BILINEAR)
normal_map.save("character_normal.png")
print("Saved to character_normal.png!")
🕹️ Game Engine Integration
- Godot Engine: Place
character.pngandcharacter_normal.pngin your project folder. Assign the normal map to the Normal Map slot of yourSprite2Dnode and add aPointLight2D. - Unity (URP 2D): Set texture type of
character_normal.pngto Normal Map. Assign it to Secondary Textures of your Sprite Renderer.
🇷🇺 Русский
Нажмите, чтобы свернуть / развернуть русский текст
Sprite2Normal — это сверхлёгкая нейросеть (~7 МБ), предназначенная для мгновенной генерации карт нормалей (Normal Maps) из плоских 2D-спрайтов, текстур и пиксель-арта.
Создана специально для инди-разработчиков игр, чтобы быстро добавлять динамическое 2D-освещение без необходимости вручную прорисовывать объём каждого кадра анимации.
Обучена полностью с нуля на специализированной компактной архитектуре U-Net.
✨ Особенности
- Минимальный вес: Модель весит всего ~7 МБ в формате ONNX.
- Работает без мощной видеокарты: Время инференса всего 3–10 мс на обычном офисном процессоре (CPU).
- Готовность к игровым движкам: Создаёт стандартные OpenGL-карты нормалей (X: Красный, Y: Зелёный, Z: Синий), совместимые с Godot, Unity, GameMaker, Unreal Engine и кастомными шейдерами.
- Любое разрешение: Свёрточная архитектура принимает спрайты произвольного размера.
🚀 Быстрый старт (Python)
1. Установка библиотек
pip install onnxruntime pillow numpy
2. Скрипт запуска
import numpy as np
from PIL import Image
import onnxruntime as ort
session = ort.InferenceSession("sprite2normal.onnx", providers=["CPUExecutionProvider"])
input_name = session.get_inputs()[0].name
output_name = session.get_outputs()[0].name
img = Image.open("character.png").convert("RGB")
orig_w, orig_h = img.size
img_resized = img.resize((128, 128), Image.Resampling.BILINEAR)
arr = np.array(img_resized, dtype=np.float32) / 255.0
arr = np.transpose(arr, (2, 0, 1))
input_tensor = np.expand_dims(arr, axis=0)
output = session.run([output_name], {input_name: input_tensor})[0][0]
pred = (output + 1.0) * 0.5 * 255.0
pred = np.clip(pred, 0, 255).astype(np.uint8)
pred = np.transpose(pred, (1, 2, 0))
normal_map = Image.fromarray(pred).resize((orig_w, orig_h), Image.Resampling.BILINEAR)
normal_map.save("character_normal.png")
print("Сохранено в character_normal.png!")
🕹️ Интеграция в движки
- Godot Engine: Поместите спрайт и карту нормалей в проект. В ноде
Sprite2Dв поле Normal Map выберите созданный файл и добавьтеPointLight2D. - Unity (URP 2D): В настройках текстуры укажите тип Normal Map и назначьте её во вкладку Secondary Textures компонента Sprite Renderer.
📄 License / Лицензия
This project is open-sourced under the Apache-2.0 License.
Проект распространяется под открытой лицензией Apache-2.0.