テクスチャのチャンネル分解 · RGBA・ORMをグレーマップに
ブラウザのCanvasで読んだパック済みテクスチャは、アルファ0の下のバイトをすべて失います。テクスチャラボはPNGを直接デコードするので、各チャンネルが保存されたとおりに出てきます。
チャンネルパックテクスチャは、互いに無関係なグレーマップを最大4枚、R・G・B・Aの各チャンネルに入れたものです。ORMテクスチャはR・G・Bにオクルージョン・ラフネス・メタリックを、Unity HDRPのマスクマップはメタリック・AO・ディテールマスク・スムースネスを持ちます。分解するとは、各チャンネルを1バイトも変えずに単一チャンネルの画像に書き出すことです。チャンネル分解はPNGを直接読み、選んだ配置(HDRP・URP・glTF・Godot ORM・Unreal ORM)に従って各チャンネルに意味を付け、チャンネルの反転(スムースネス ↔ ラフネス)もでき、完全に透明なテクセルの下まで元とバイト一致の8ビットグレーPNGとして保存します。

- Channel PNGs測定確認· numpy
- Normal map測定確認· numpy
- Packed mask / ORM測定確認· Pillow
- Engine import未検証
パックテクスチャの中身と、順番が大事な理由
パックテクスチャの各チャンネルはテクセルごとの独立した0〜255の数値で、色の一部ではありません。絵として見ると不思議な色に見え、Gがラフネス(glTF・Godot ORM)なのか、アンビエントオクルージョン(Unity HDRP)なのか、オクルージョン(Unity URP)なのかは配置を知らないと分かりません。ファイル名から順番はまず分かりません。_ORM・_ARM・_MaskMap・_packedはどれも「パック済み」を意味するだけなので、ラボはすべてパックマップに分類し、配置は自分で選ぶ形にしています。
データが失われるのはアルファチャンネルです。Unityのマスクマップでは、完全に粗いテクセルはスムースネス0、つまりアルファ0です。ブラウザのCanvasはピクセルを乗算済みで保持するため、そのテクセルのメタリック・AO・ディテールのバイトは0として返ります。チャンネル分解は自前のリーダーでPNGをデコードし(インターレース以外の全カラー形式、1〜16ビット、tRNS)、各チャンネルを色変換なしの1テクセル1バイト、カラー形式0のPNGとして書き出します。
反転は厳密です。保存される値は255 − 値で、2回反転すると元のバイトに戻ります。Unityのスムースネスのチャンネルは、こうして他のエンジンが求めるラフネスになります。
- チャンネル平面
- 1チャンネル分のw × hバイト。グレーのPNGとして保存します。
- 乗算済みアルファ
- アルファを掛けた後の色。アルファ0では色がすべて0になり、そこにパックされたバイトは失われます。
- マスクマップ
- Unity HDRPのパックテクスチャ。Rメタリック・Gアンビエントオクルージョン・Bディテールマスク・Aスムースネス。
- 16ビット入力
- 受け付けますが、サンプルごとに上位バイトを使います。出力は常に8ビットです。
例:HDRPマスクマップの1テクセル
AOが200でディテールマスクのない、完全に粗い金属のテクセルです。スムースネスが0なのでアルファも0です。
元のテクセル (crate_MaskMap.png) R 255 G 200 B 0 A 0
ブラウザのCanvasで読む R 0 G 0 B 0 A 0 (乗算済み:色 × 0)
ラボのPNGデコーダーで読む R 255 G 200 B 0 A 0
Unity HDRPの配置で保存、Aを反転:
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:ラフネス)反転したファイルは配置上の名前(smoothness)の前にinverted-が付くので、中身はラフネスです。ほかのツールがファイル名でマップを選ぶ場合は名前を変えてください。
配置ごとの各チャンネルの中身
| チャンネル | Unity HDRPマスクマップ | glTF 2.0 / Godot ORM | Unity URPチャンネルパック |
|---|---|---|---|
| R | メタリック | オクルージョン | メタリック |
| G | アンビエントオクルージョン | ラフネス | オクルージョン |
| B | ディテールマスク(HDRPのみ) | メタリック | 未使用 |
| A | スムースネス — 反転でラフネス | 未使用 | スムースネス — 反転でラフネス |
組み込みのStandardシェーダーのメタリックマップはR(メタリック)とA(スムースネス)だけを読みます。Nerulioの「Unity URP・組み込み」プリセットはこのページに従ってGを「無視」と表示しますが、UnityのURPのページは、同じテクスチャをOcclusionにも割り当てるとGからオクルージョンを読むとしています。
できること
- チャンネル(R・G・B・A)ごとに8ビットのグレーPNGを1枚、元とバイト一致。
- 完全に透明なテクセル下のRGBを保持(2048テクセルで確認)。
- 選んだエンジン配置(Unity HDRP・URP・ORM)での意味つきでチャンネルをプレビュー。
- チャンネルの反転(例:ラフネス ↔ スムースネス)と保存。
使い方
- パック済みPNGをドロップ。
- エンジン配置を選び、各チャンネルの意味を確認。
- 必要ならチャンネルを反転。
- チャンネルPNGをダウンロード。
出力されるファイル
| ファイル | 用途 |
|---|---|
crate_MaskMap-r-metallic.png … -a-smoothness.png | チャンネルごとに8ビットのグレーPNG(カラー形式0)を1枚。名前はファイル-チャンネル-役割で、反転した場合は役割の前にinverted-が付きます。 |
crate_MaskMap-channels.zip | 4チャンネルのPNGを1つのアーカイブに(4チャンネルすべて保存)。 |
パックテクスチャを別のエンジンの配置へ移す
例:Unity HDRPのマスクマップをGodot 4やglTFへ移す場合。エンジンの設定は各ドキュメントに従ったもので、Nerulioは読み込みを実行していません。
- パック済みのPNGを開き、「チャンネルの解釈」を元の配置(ここではUnity HDRPマスクマップ)にします。チャンネルの統計を見てください。最小 = 最大のチャンネルは定数で埋められたものです。
- Aの「反転」を押してスムースネスをラフネスにし、「4チャンネルすべて保存(ZIP)」を押します。
- Godot 4で個別マップとして使う:
StandardMaterial3Dのテクスチャスロットにラフネス・メタリック・AOのPNGを割り当てます(Ambient Occlusionは先に有効化)。各スロットの*_texture_channelの既定はRedなので、グレーPNGはそのまま読まれます。 - Godotの
ORMMaterial3DやglTF:マスクパッカーのORMプリセット(Rオクルージョン・Gラフネス・Bメタリック)でAO・ラフネス・メタリックをパックし直します。 - Unity:グレーPNGやパックし直したテクスチャはすべて
sRGB (Color Texture)をオフにして読み込みます。URP・HDRPにはラフネス専用のスロットがないため、平面を1枚ずつ使わず、メタリックとスムースネスをパックし直してください。
結果の確認
- 分解したときと同じ配置で平面をパックし直し、それを分解します。各チャンネルの最小・最大・平均・固有値の数が前と同じはずです(ラボの測定:最大差0)。
- 保存したPNGを任意の画像ツールで開きます。RGBのコピーではなく、元の解像度の単一チャンネル8ビットグレー画像のはずです。
- 反転した平面では、以前vだったテクセルが255 − vになっているはずです(ステージに元 → 結果が並んで表示されます)。
トラブルシューティング
| 症状 | 考えられる原因 | 確認方法 | 対処 |
|---|---|---|---|
| 別のツールで、透明な場所ごとにチャンネルが黒くなる | そのツールが乗算済みアルファでファイルを読んだ | 同じPNGをチャンネルステージで開くとバイトは残っている | ラボで分解し、パックデータはCanvasを使うツールに通さない |
| ファイルに「ブラウザでデコード(バイト一致ではない)」と出る | JPEG・WebPの入力。JPEGの圧縮はチャンネル同士を混ぜることもある | ファイル一覧とレポートのexactChannels: false | テクスチャの元になったPNGを分解する |
| 分解した「AO」がラフネスに見える、メタリックが荒れている | 配置の選択が違う(GはHDRPではAO、glTFではラフネス) | 「チャンネルの解釈」を切り替えて統計とプレビューを比べる | テクスチャを書き出したソフトの配置を選ぶ |
| 移した先のエンジンでラフネスが逆に見える | 元のチャンネルがスムースネス(Unity)で、反転していない | ファイル名にinverted-がない | そのチャンネルの「反転」を押して保存し直す |
| 16ビットのテクスチャの精度が落ちる | 出力は8ビットで、サンプルごとに上位バイトだけを残す | レポートのビット深度 | 16ビットの平面が必要なら16ビット対応の編集ソフトを使う |
ほかの方法
| 方法 | こんなときに向いています |
|---|---|
| パックしたまま使う | GodotのStandardMaterial3Dはマップごとに読むチャンネルを選べる(roughness_texture_channel・metallic_texture_channel・ao_texture_channel)ため、順番が違うだけなら分解は不要です。 |
| 画像編集ソフトのチャンネル分解 | アルファ0のテクセルがない不透明なテクスチャを、すでにそのソフトで扱っているとき。マスクマップなら透明な部分を先に確認してください。 |
| ラフネスをスムースネスに | Unity向けに反転したグレーマップが1枚だけ必要なとき。 |
出力ファイルと検証方法
「測定確認」は、ダウンロードしたファイルをページ外(Pillow・numpy・独立したパーサー)で開き直して性質を測ったという意味です。ゲームエンジンでの読み込みは試していません。
| 書き出し先 | ファイル | 検証 |
|---|---|---|
| Channel PNGs | <name>-r/g/b/a.png (8-bit grey) | 測定確認 numpyチャンネルごとにバイト一致。完全に透明なテクセル下のRGBも保持。 |
| Normal map | PNG · OpenGL (+Y) or DirectX (−Y) | 測定確認 numpyデコードしたベクトルは単位長(最大誤差0.0002)。OpenGLとDirectXは緑だけが異なります。 |
| Packed mask / ORM | Unity HDRP mask · URP metallic · ORM (glTF, Godot) | 測定確認 Pillowパック後のバイトを確認:ORMプリセット、AO 10 / ラフネス 80 / メタリック 220 → (10, 80, 220, 255)。 |
| Engine import | Unity · Unreal · Godot | 未検証どのエンジンでも読み込んでいません。 |
検証の根拠
チャンネル分解は4チャンネルすべてでバイト一致(最大差0)、透明テクセル2048個のRGBを保持。エッジブリードはアルファ0のテクセル448個だけを変更し、アルファは一切変更なし。OpenGL ↔ DirectXは緑(255 − g)だけが異なり、変換後の法線は単位ベクトル。
制限
- チャンネルのバイトを正確に扱えるのはPNGだけです。JPEG・WebPはブラウザがデコードし「バイト一致ではない」と表示します。
- インターレースPNGと16ビット出力は非対応。正確な経路は3,355万ピクセルまで。
- ノーマルマップの規約はピクセルから判定できず、変換のみ可能です。
- Unity・Unreal・Godotへの読み込みは行っていません。チャンネル順は各ドキュメントとエンジンのソースに基づきます。
バージョンと出典
テクスチャラボで測定(docs/TEXTURE-LAB.md):ランダムなバイトの64×64 ORMを分解するとR・G・B・Aすべて最大差0、アルファ0のテクセル2048個がすべてRGBを保持(わざと入れた(1, 2, 3, 0)の角はR = 1で復元)、ファイルはPillowでモードL・64×64として開け、反転したラフネスの平面は正確に255 − ラフネス。配置は下記のエンジンのドキュメントのもので(GodotのORMの順序はエンジンのソース)、エンジンへの読み込みは行っていません。
参照した公式ドキュメント
よくある質問
画像編集ソフトで開くのではだめ?
多くの編集ソフトとすべてのブラウザCanvasはアルファを乗算するため、透明テクセル下のメタリック・ラフネスのバイトが0になります。この経路はPNGのバイトを直接読みます。
JPEGでも使えますか?
使えます。ただしJPEGはブラウザがデコードし、「バイト一致ではない」と表示します。
無料ですか?アカウントは必要ですか?
このページの機能はすべて無料で、アカウントなしで使えます。透かしや制限された書き出しはありません。
スプライトはアップロードされますか?
いいえ。Studioはこのブラウザのタブ内でデコード・パック・書き出しを行います。プロジェクトはブラウザ(IndexedDB)に自動保存され、.nerulioファイルとして保存できます。
Asepriteやエンジンのプラグインは必要ですか?
いいえ。.asepriteファイルはブラウザで読み書きします。エンジン別のバンドルには必要なものが入っています(Godotはインポート設定とシーン、UnityとGodotのタイルセットは小さなエディタースクリプト)。