Channel Unpacker

Split an ORM or mask texture into R/G/B/A greyscale PNGs with the original bytes.

A packed texture keeps up to four unrelated grey maps in its R, G, B and A channels — an ORM texture holds occlusion, roughness and metallic in R, G and B; a Unity HDRP mask map holds metallic, AO, detail mask and smoothness. Splitting it means writing each channel to its own single-channel image without changing a byte. The Channel Unpacker reads the PNG itself, labels each channel for the layout you pick (HDRP, URP, glTF, Godot ORM, Unreal ORM), can invert a channel (smoothness ↔ roughness) and saves 8-bit grey PNGs that are byte-identical to the source, including under fully transparent texels.

Drop image files hereProcess many files at once
No upload · processed on this device

What is inside a packed texture, and why the order matters

Each channel of a packed texture is an independent 0–255 number per texel, not part of a colour. Viewed as a picture it shows odd colours; only the layout tells you that G means roughness (glTF, Godot ORM), ambient occlusion (Unity HDRP) or occlusion (Unity URP). The file name rarely tells the order: _ORM, _ARM, _MaskMap and _packed all just say "packed", so the Lab classifies them all as a packed map and lets you choose the layout.

The alpha channel is where tools lose data. In a Unity mask map, a fully rough texel has smoothness 0, which is alpha 0. A browser canvas stores pixels premultiplied, so that texel's metallic, AO and detail bytes come back as 0. The Unpacker decodes PNG files with its own reader (all non-interlaced colour types, bit depths 1–16, tRNS) and writes each channel as a colour-type-0 PNG, one byte per texel, with no colour conversion.

Inverting is exact: the saved plane is 255 − value, and inverting twice returns the original bytes. That is how a Unity smoothness channel becomes the roughness another engine wants.

Channel plane
The w × h bytes of one channel, saved as a greyscale PNG.
Premultiplied alpha
Colour stored already multiplied by alpha; at alpha 0 every colour becomes 0, so packed bytes there are lost.
Mask map
Unity HDRP's packed texture: R metallic, G ambient occlusion, B detail mask, A smoothness.
16-bit input
Accepted; the Lab keeps the high byte of each sample. Output is always 8-bit.

Example: one texel of an HDRP mask map

A fully rough metal texel with AO 200 and no detail mask. Its smoothness is 0, so its alpha is 0:

Source texel (crate_MaskMap.png)   R 255   G 200   B 0   A 0
Read through a browser canvas      R 0     G 0     B 0   A 0     (premultiplied: colour × 0)
Read by the Lab's PNG decoder      R 255   G 200   B 0   A 0

Saved with the Unity HDRP layout, A inverted:
  crate_MaskMap-r-metallic.png                 255
  crate_MaskMap-g-ao.png                       200
  crate_MaskMap-b-detail.png                   0
  crate_MaskMap-a-inverted-smoothness.png      255   (255 − 0: roughness)

The inverted file keeps the channel's layout name (smoothness) with inverted- in front, so its content is roughness. Rename it if another tool picks maps by file name.

Which channel holds what, per layout

ChannelUnity HDRP Mask MapglTF 2.0 / Godot ORMUnity URP channel-packed
RMetallicOcclusionMetallic
GAmbient occlusionRoughnessOcclusion
BDetail mask (HDRP only)MetallicNot used
ASmoothness — invert for roughnessNot usedSmoothness — invert for roughness

The Built-in Standard shader's metallic map reads only R (metallic) and A (smoothness). Nerulio's "Unity URP / Built-in" preset follows that page and labels G "ignored"; Unity's URP page reads occlusion from G when the same texture is also assigned to Occlusion.

Files you get

FileWhat it is for
crate_MaskMap-r-metallic.png … -a-smoothness.pngOne 8-bit grey PNG per channel (colour type 0), named file-channel-role; inverted- is added before the role when you inverted it.
crate_MaskMap-channels.zipAll four channel PNGs in one archive (Save all four channels).

Move a packed texture to another engine's layout

Example: a Unity HDRP mask map going to Godot 4 or glTF. The engine settings follow their documentation; Nerulio did not run the imports.

  1. Open the packed PNG and set Read channels as to the layout it came from (here Unity HDRP Mask Map). Check the channel stats: a channel with min = max is a constant filler.
  2. Click Invert on A so smoothness becomes roughness, then Save all four channels (ZIP).
  3. Godot 4 with separate maps: in a StandardMaterial3D assign the roughness, metallic and AO PNGs to their texture slots (enable Ambient Occlusion first). Each slot's *_texture_channel defaults to Red, which a grey PNG satisfies.
  4. Godot ORMMaterial3D or glTF: repack AO, roughness and metallic with the ORM preset in the mask packer (R occlusion, G roughness, B metallic).
  5. Unity: import every grey PNG or repacked texture with sRGB (Color Texture) off. URP and HDRP have no separate roughness slot, so pack metallic and smoothness again rather than using the planes one by one.

Check the result

  • Repack the planes with the layout you unpacked them with and unpack the result: every channel should read the same min, max, mean and unique-value count as before (the Lab measured max difference 0).
  • Open a saved PNG in any image tool: it is a single-channel 8-bit grey image at full resolution, not an RGB copy.
  • For an inverted plane, a texel that read v before reads 255 − v after (the stage shows the in → out pair side by side).

Troubleshooting

SymptomLikely causeHow to checkFix
A channel is black wherever the texture is transparent (in another tool)That tool read the file through premultiplied alphaOpen the same PNG in the Channels stage: the bytes are thereUnpack in the Lab, and keep packed data out of tools that use a canvas
The file is marked "decoded by the browser (not byte-exact)"JPEG or WebP input; JPEG compression also mixes channelsThe file list and the report (exactChannels: false)Unpack the PNG the texture was made from
The unpacked "AO" looks like roughness, or metallic looks noisyThe wrong layout is selected (G is AO in HDRP, roughness in glTF)Switch Read channels as and compare the stats and previewsPick the layout of the program that exported the texture
Roughness looks inverted in the target engineThe source channel was smoothness (Unity) and was not invertedIts file name has no inverted-Click Invert on that channel and save again
A 16-bit texture loses precisionOutput is 8-bit; the high byte of each sample is keptBit depth in the reportUse a 16-bit capable editor when you need 16-bit planes

Other ways to do it

OptionWhen it is the better choice
Keep the texture packedGodot's StandardMaterial3D can read each map from a chosen channel (roughness_texture_channel, metallic_texture_channel, ao_texture_channel), so no split is needed when the order is simply different.
An image editor's channel splitOpaque textures with no alpha-0 texels, when you are already in that editor; check the alpha area before trusting it with a mask map.
Roughness to smoothnessYou only need one inverted grey map for Unity.

Versions and sources

Measured on the Texture Lab (docs/TEXTURE-LAB.md): a 64×64 ORM of random bytes unpacked with max difference 0 on R, G, B and A; all 2048 alpha-0 texels kept their RGB (an explicit (1, 2, 3, 0) corner came back with R = 1); the files re-opened in Pillow as mode L, 64×64; the inverted roughness plane equalled 255 − roughness exactly. The layouts are the engines' documented ones listed below (Godot's ORM order from its engine source); nothing was imported into an engine.

Official documentation used

Channel Unpacker

Split an ORM or mask texture into R/G/B/A greyscale PNGs with the original bytes.

How it works

  1. Add images
  2. Adjust settings and review the result
  3. Download a new file

Supported formats

PNG / JPG / WebP / AVIF / HEIC → PNG (ZIP) — Input decoding depends on browser support and optional engines.

What this tool does

Split an ORM or mask texture into R/G/B/A greyscale PNGs with the original bytes.

Implementation and verified quality

advanced · raw PNG decode / exact channel planes / greyscale PNG writer. Quality qualification is in progress. Pro/Flagship quality has not been established.

Before you export

Channel meaning comes from the engine preset you pick; a file cannot say which engine it was packed for.

Frequently asked questions

What are this tool’s limitations?

Channel meaning comes from the engine preset you pick; a file cannot say which engine it was packed for.

Are my files uploaded?

This tool processes the files you open on your device without uploading them. Images you explicitly attach to community posts are uploaded separately. Optional engines and models are downloaded from third parties; those requests expose connection information such as your IP address.

Will my work be saved automatically?

No. Images and editing state stay in this tab; media output can use local temporary storage. Changing language preserves your work; reloading, closing the tab, or following a link to another page can clear it.