RGBA Mask Packer

Map luminance from equally sized images into your chosen RGBA channels.

Channel packing puts separate grey maps into the R, G, B and A of one PNG in the order your engine reads: Unity HDRP Mask Map = R metallic, G ambient occlusion, B detail mask, A smoothness; Unity URP channel-packed texture = R metallic, G occlusion, A smoothness; ORM for glTF 2.0 and Godot 4 = R occlusion, G roughness, B metallic. Drop up to four same-size grey maps, pick a preset or map each channel yourself, tick Invert where the engine wants smoothness instead of roughness, and download …-mask.png. The packed bytes were measured; import into an engine was not run.

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

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 haveUnity HDRP Mask MapUnity URP channel-packedglTF 2.0 / Godot ORM
MetallicRRB
Ambient occlusionGG (read when the texture is also assigned to Occlusion)R
RoughnessA, inverted (smoothness)A, inverted (smoothness)G
Detail maskB——
No map for a channelConstant 0 (e.g. B without detail)B = 0A = 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

FileWhat it is for
rock_metallic-mask.pngThe packed texture, named after the first file you dropped: 8-bit RGBA PNG, RGB kept where alpha is 0.
rock_metallic-mask-channels.zipOptional 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.

  1. 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.
  2. 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).
  3. 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.
  4. 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

SymptomLikely causeHow to checkFix
Rough areas look polished in UnityRoughness went into alpha without InvertUnpack A: it equals the roughness map instead of 255 − roughnessTick Invert on A and pack again
A map landed in the wrong channelInputs fill channels in the order they were droppedThe mapping line (e.g. R←1 · G←2 · B←3 · A←255) under the previewPick the right file in each channel's drop-down
"All channel inputs must have the same dimensions"One grey map has another sizeThe file list shows each sizeExport every map at the same size first
URP material goes dark in ambient lightThe texture is assigned to Occlusion, and the Unity preset wrote G = 0Unpack G: min = max = 0Map the AO file to G with Custom, or leave Occlusion Map empty
Everything too glossy or too matte after importThe packed texture was imported with sRGB onUnity: the texture's sRGB (Color Texture) checkboxTurn sRGB off; the values are data
A channel has unexpected valuesA coloured input was reduced to its luminanceThe 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

OptionWhen it is the better choice
Godot's channel selectors, no packingGodot 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 presetThe 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

Example

Original geometric sample · 96 × 64
Original geometric sample · 96 × 64
Processed sample · 96 × 64
Processed sample · 96 × 64

Example generated with this tool. ZIP tools show their preview; inspect the downloaded archive for every file.

RGBA Mask Packer

Map luminance from equally sized images into your chosen RGBA channels.

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 — 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.

Frequently asked questions

What are this tool’s limitations?

Input dimensions must match. Uses Canvas byte luminance without a linear-color workflow.

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.