PBR channel packing with texture audit (ORM, Unity mask) avatar

PBR channel packing with texture audit (ORM, Unity mask)

Pricing

from $50.00 / 1,000 pack completeds

Go to Apify Store
PBR channel packing with texture audit (ORM, Unity mask)

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

Jean-Baptiste Couche

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

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:

  • Provenanceroughness ← 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

FieldNotes
roughnessUrl / smoothnessUrl / metalRoughUrlAt least one required — the Actor refuses to invent roughness
occlusionUrlOptional; defaults to neutral white, reported
metallicUrlOptional; defaults to dielectric 0, reported
normalUrlOptional; audited, and converted if normalConvert is set
conventiongltf-orm, unreal-orm, unity-mask, unity-metallic
normalConvertnone, opengl-to-directx, directx-to-opengl
metalRoughHasOcclusionFor pipelines whose packed source already carries AO in R
resolution0 = largest source; otherwise 4–8192, square
outputFormatpng 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.