ORM & Mask Map Packer — Channel Pack Textures for Unity, Godot, glTF
Put AO, roughness, metallic and more into the channels your engine reads. Each preset states where its channel order comes from, and the PNG is written by the Lab itself, so bytes survive alpha 0.

- Channel PNGsMeasured· numpy
- Normal mapMeasured· numpy
- Packed mask / ORMMeasured· Pillow
- Engine importUNVERIFIED
What it does
- Presets: Unity HDRP mask (M, AO, detail, smoothness), URP metallic (M, –, –, smoothness), ORM (glTF 2.0, Godot 4).
- Custom mapping per channel, constant 0/255, and per-channel inversion (roughness → smoothness).
- Written as PNG by the Lab (not a canvas), so RGB under alpha 0 is kept.
- Each preset links the documentation or engine source its order is taken from.
How to do it
- Drop the grey maps.
- Choose a preset or map the channels by hand.
- Invert channels where the engine expects the opposite.
- Download the packed PNG.
Outputs and how each was checked
"Measured" means the downloaded file was opened again outside the page (Pillow, numpy or an independent parser) and the property was measured. Loading these files in a game engine was not tested.
| Target | Files | Check |
|---|---|---|
| Channel PNGs | <name>-r/g/b/a.png (8-bit grey) | Measured numpyByte-identical per channel, including RGB under fully transparent texels. |
| Normal map | PNG · OpenGL (+Y) or DirectX (−Y) | Measured numpyDecoded vectors are unit length (worst deviation 0.0002); OpenGL and DirectX differ in green only. |
| Packed mask / ORM | Unity HDRP mask · URP metallic · ORM (glTF, Godot) | Measured PillowPacked bytes checked: ORM preset over AO 10 / roughness 80 / metallic 220 → (10, 80, 220, 255). |
| Engine import | Unity · Unreal · Godot | UNVERIFIEDNot imported in any engine. |
Evidence
Channel unpack byte-identical on all four channels (max difference 0), 2048 transparent texels keep their RGB; edge bleed changed 448 texels, all with alpha 0, and no alpha byte; OpenGL ↔ DirectX differ exactly in green (255 − g); converted normals decode to unit vectors.
Limits
- Exact channel bytes need PNG; JPEG/WebP are decoded by the browser and marked "not byte-exact".
- Interlaced PNG and 16-bit output are not supported; up to 33.5 million pixels on the exact path.
- A normal map's convention cannot be detected from its pixels, only converted.
- Nothing was imported into Unity, Unreal or Godot: channel orders rest on their documentation and engine source.
Questions
Is the Unreal ORM order official?
Epic does not document an R=AO, G=roughness, B=metallic order; the ORM preset follows glTF 2.0 and is labelled that way.
Was it imported into the engines?
No. The packed bytes were checked, e.g. (10, 80, 220, 255) for the ORM preset; import into Unity, Unreal or Godot is not tested.
Is it free, and do I need an account?
Everything on these pages is free and works without an account. There is no watermark and no export that is held back.
Are my sprites uploaded?
No. The Studio decodes, packs and exports in this browser tab. Projects are autosaved in the browser (IndexedDB) and can be saved as a .nerulio file.
Does it need Aseprite or an engine plugin installed?
No. .aseprite files are read and written in the browser, and each engine bundle carries what that engine needs (for Godot, the import settings and scene; for Unity and the Godot TileSet, a small editor script).