PBR channel packing with texture audit (ORM, Unity mask)
Pricing
from $50.00 / 1,000 pack completeds
PBR channel packing with texture audit (ORM, Unity mask)
Pack PBR maps into glTF/Unreal ORM or Unity mask maps, with an audit of the set: value ranges, roughness/smoothness consistency, normal-map normalization, resolution mismatches, per-channel provenance. Data maps written raw, never colour-managed. PNG or EXR out.
Pricing
from $50.00 / 1,000 pack completeds
Rating
0.0
(0)
Developer
Jean-Baptiste Couche
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Pack PBR maps the way the engine actually wants them
Give it your texture maps — separate grayscales, or a glTF-style packed metallicRoughness — and get back one correctly packed file for your target: glTF/Unreal ORM, Unity HDRP/URP mask map, or Unity Built-in MetallicGlossMap. Plus an audit of the set, because the values being in the right channels is only half the job.
Headless Blender 4.5 LTS image I/O underneath (EXR included), no UI, no login, callable by agents over MCP.
The two inversions that ruin texture sets
Roughness vs smoothness. Unity stores smoothness where everyone else
stores roughness. Both Unity layouts here write A = 1 − roughness —
inverted exactly once, never twice — and if you supply a genuine smoothness
map it's used as-is. Supply both and they get audited against each other:
if smoothness ≠ 1 − roughness beyond tolerance, they describe two
different surfaces and the report says which percentage of texels disagree.
OpenGL vs DirectX normals. glTF, Unity and Blender put +Y in the green
channel; Unreal puts −Y. The flip is exact (G' = 1 − G, zero
renormalization needed) but the source convention cannot be detected from
pixels — so it is never guessed. You declare the direction, the converted
map ships alongside the packed texture, and the report records your
declaration with a plain warning: flip an already-correct map and bumps
become dents.
Data maps are written raw — and the build proves it
An ORM must never pass through colour management: a gamma curve applied to a roughness channel is invisible in a viewer and wrong in every render. This Actor's Docker build writes known pixel values through the exact production code path, reads them back, and fails the build if they come back off by more than 8-bit quantization. That guard has already caught one real corruption — Blender silently sRGB-encoding float buffers saved to PNG — before any customer could hit it.
Output PNG is lossless 8-bit; EXR is float and bit-exact. JPEG is deliberately refused: chroma subsampling averages neighbouring texels across channels that mean different things.
The audit
Every run reports, per channel and per source map:
- Provenance —
roughness ← G channel of metalRough.jpg. Traceable, not magic. Defaulted channels (no AO supplied → neutral white) are declared loudly, never silent. - Value statistics — min/max/mean, % pure black, % pure white. Metallic is physically near-binary, so a metallic map living in midtones gets flagged: it's usually a spec/gloss map that landed in the wrong slot.
- Normal map normalization — decoded vector lengths, p95 deviation from unit. Catches maps damaged by resizing or colour management upstream.
- Resolution handling — mismatched sources are resampled to the working resolution and each resize is reported; NPOT sizes get a warning.
- An engine import checklist — the settings that silently undo correct files: sRGB flag, Unreal's Masks compression preset, which slot, which normal convention the engine expects. In the report, next to the file it applies to.
Input
| Field | Notes |
|---|---|
roughnessUrl / smoothnessUrl / metalRoughUrl | At least one required — the Actor refuses to invent roughness |
occlusionUrl | Optional; defaults to neutral white, reported |
metallicUrl | Optional; defaults to dielectric 0, reported |
normalUrl | Optional; audited, and converted if normalConvert is set |
convention | gltf-orm, unreal-orm, unity-mask, unity-metallic |
normalConvert | none, opengl-to-directx, directx-to-opengl |
metalRoughHasOcclusion | For pipelines whose packed source already carries AO in R |
resolution | 0 = largest source; otherwise 4–8192, square |
outputFormat | png or exr |
Output
The packed map under OUTPUT in the run's key-value store — a ZIP when a
converted normal ships alongside. The dataset record carries the full
report; the unabridged copy lives under REPORT_FULL. The packed file is a
data map in Non-Color space: sample it linear, never sRGB — the checklist
in the report says exactly where that switch lives in your engine.
Verified against
Real assets, end to end on Apify: DamagedHelmet's AO + packed
metallicRoughness recombined into a true 2048² ORM with per-channel
provenance; the same set to a Unity mask map with an OpenGL→DirectX normal
conversion shipping alongside; and the reject path (no roughness source →
explicit NO_ROUGHNESS_SOURCE-class refusal, nothing charged).
Limits worth knowing
Colorspace of input files is assumed, not read — image formats carry no reliable metadata, so values are copied verbatim (the correct handling for data maps) and the assumption is stated in the report. Channel packing trusts your labels: it cannot detect that a file named roughness is actually gloss — though the value statistics often expose it. High→low baking (normal/AO from a source mesh) is the next tool in this suite, not this one.