How the packer fills each channel
Each input is read as a grey value per texel: its Rec. 709 luminance, 0.2126 R + 0.7152 G + 0.0722 B, rounded. For a real grey map (R = G = B) that is exactly the stored value, so a grey byte goes into its channel unchanged. A coloured image would be mixed down to luminance, which is rarely what you want for a data map.
Presets only choose where inputs go. Inputs fill the meaningful channels in the order you dropped them; a channel the layout ignores is written as 0 and an unused alpha as 255, so the file stays opaque. Nothing is inverted automatically: Unity's smoothness is 1 − roughness, so if you hold a roughness map you tick Invert on the smoothness channel (255 − value).
Alpha is data here. In an HDRP or URP texture, smoothness 0 means alpha 0. The packer writes the PNG with its own encoder (32 rows at a time), not through a canvas, so the metallic and AO bytes under those texels survive. Its inputs are read by the browser's image decoder, so feed it plain grey PNGs rather than files with transparency.
Import it as data. Unity's HDRP page asks you to disable sRGB (Color Texture) and use Texture Type Default for the mask map, and URP's page asks for sRGB off on its channel-packed texture; glTF 2.0 requires metallic and roughness values to be linear.
- Mask map
- Unity HDRP's packed texture: R metallic, G AO, B detail mask, A smoothness.
- ORM
- Occlusion, roughness, metallic in R, G, B — glTF 2.0's order, also Godot's ORMMaterial3D.
- Constant channel
- A channel written as 0 or 255 everywhere because the layout needs no map there.
- Invert
- 255 − value, the 8-bit form of 1 − x; turns roughness into smoothness and back.
Example: the same three maps in three layouts
Three grey maps of one texel: AO 10, roughness 80, metallic 220. The mapping line is how the packer shows it (number = dropped file, ⁻ = inverted):
ORM (glTF 2.0, Godot 4) files: ao, roughness, metallic R←1 · G←2 · B←3 · A←255 → (10, 80, 220, 255)
Unity HDRP mask map files: metallic, ao, roughness R←1 · G←2 · B←0 · A←3⁻ → (220, 10, 0, 175)
Unity URP packed files: metallic, ao, roughness R←1 · G←2 · B←0 · A←3⁻ → (220, 10, 0, 175)
smoothness = 255 − 80 = 175 (1 − 0.314 = 0.686)
Measured in the Lab: ORM preset (10, 80, 220, 255); custom mapping (220, 10, 80, 0); R inverted (245, 80, 220, 255)
The HDRP and URP rows are identical here because there is no detail mask; HDRP would read B as detail mask, URP ignores it. With the HDRP preset and only three files dropped, the third file lands in B, so set B to 0 and A to file 3 with Invert, as shown.
Where each grey map goes
| Grey map you have | Unity HDRP Mask Map | Unity URP channel-packed | glTF 2.0 / Godot ORM |
|---|
| Metallic | R | R | B |
|---|
| Ambient occlusion | G | G (read when the texture is also assigned to Occlusion) | R |
|---|
| Roughness | A, inverted (smoothness) | A, inverted (smoothness) | G |
|---|
| Detail mask | B | — | — |
|---|
| No map for a channel | Constant 0 (e.g. B without detail) | B = 0 | A = 255 (unused) |
|---|
Nerulio's "Unity metallic + smoothness" preset follows the Built-in Standard shader page (G and B unused) and writes G = 0. For URP with occlusion, choose Custom and map the AO file to G.
Files you get
| File | What it is for |
|---|
rock_metallic-mask.png | The packed texture, named after the first file you dropped: 8-bit RGBA PNG, RGB kept where alpha is 0. |
|---|
rock_metallic-mask-channels.zip | Optional check: open the packed file in the channel unpacker and save its four planes to compare with your inputs. |
|---|
Use the packed texture in the engine
Steps from the engines' documentation; Nerulio did not run these imports.
- Unity HDRP: import the PNG, disable
sRGB (Color Texture), set Texture Type to Default, and assign it to Mask Map under Surface Inputs of the HDRP Lit material. Metallic, Smoothness and AO Remapping sliders appear once a mask map is assigned. - Unity URP: import with
sRGB (Color Texture) off, set the Lit material's Workflow Mode to Metallic, assign the texture to Metallic Map and to Occlusion Map, and keep Smoothness › Source at Metallic Alpha (the default). - Godot 4: create an
ORMMaterial3D and assign the ORM PNG as its ORM texture. A StandardMaterial3D can read the same file by setting ao_texture_channel to Red, roughness_texture_channel to Green and metallic_texture_channel to Blue. - glTF 2.0: reference the ORM image as the material's metallicRoughness texture and, if it carries occlusion, as its occlusion texture too; base colour stays a separate sRGB image.
Check the result
- Open the packed PNG in the channel unpacker with the same layout: each plane should match the grey map you put there (the capability check measured byte-identical channels on ambientCG grey maps), and inverted channels read 255 − value.
- A constant channel shows min = max (0 or 255) in the channel stats.
- In the engine, a rough area should look dull and a polished one sharp; if it is the other way round, the smoothness channel was not inverted.
Troubleshooting
| Symptom | Likely cause | How to check | Fix |
|---|
| Rough areas look polished in Unity | Roughness went into alpha without Invert | Unpack A: it equals the roughness map instead of 255 − roughness | Tick Invert on A and pack again |
|---|
| A map landed in the wrong channel | Inputs fill channels in the order they were dropped | The mapping line (e.g. R←1 · G←2 · B←3 · A←255) under the preview | Pick the right file in each channel's drop-down |
|---|
| "All channel inputs must have the same dimensions" | One grey map has another size | The file list shows each size | Export every map at the same size first |
|---|
| URP material goes dark in ambient light | The texture is assigned to Occlusion, and the Unity preset wrote G = 0 | Unpack G: min = max = 0 | Map the AO file to G with Custom, or leave Occlusion Map empty |
|---|
| Everything too glossy or too matte after import | The packed texture was imported with sRGB on | Unity: the texture's sRGB (Color Texture) checkbox | Turn sRGB off; the values are data |
|---|
| A channel has unexpected values | A coloured input was reduced to its luminance | The input is not grey (R, G, B differ) | Unpack the coloured source to its real channel first, then pack that plane |
|---|
Other ways to do it
| Option | When it is the better choice |
|---|
| Godot's channel selectors, no packing | Godot only: StandardMaterial3D reads each map from a chosen channel of one texture, so an existing packed file in another order needs no repacking. |
|---|
| Your texturing application's export preset | The maps come from a painting tool that can export in the engine's layout directly; Godot's docs name Substance Painter and ArmorPaint (Unreal Engine preset) for ORM. |
|---|
| Shader Graph (Unity) | Your textures use a layout no preset covers; Unity's URP page points to Shader Graph for channels packed differently. |
|---|
Versions and sources
Measured on the Texture Lab (docs/TEXTURE-LAB.md): the ORM preset over AO 10 / roughness 80 / metallic 220 wrote (10, 80, 220, 255) from inside the Lab and from this page; a custom mapping gave (220, 10, 80, 0) and an inverted R (245, 80, 220, 255). The browser capability check packs three ambientCG grey maps and finds each channel byte-identical to its input. The layouts come from the documentation below (Godot's ORM order from its engine source); no engine import was run.
Official documentation used
RGBA Mask Packer
Map luminance from equally sized images into your chosen RGBA channels.
How it works
- Add images
- Adjust settings and review the result
- Download a new file
Supported formats
PNG / JPG / WebP / AVIF / HEIC → PNG — Input decoding depends on browser support and optional engines.
What this tool does
Map luminance from equally sized images into your chosen RGBA channels.
Implementation and verified quality
advanced · sequential row-transfer channel packing / incremental PNG. Quality qualification is in progress. Pro/Flagship quality has not been established.
Before you export
Input dimensions must match. Uses Canvas byte luminance without a linear-color workflow.