ひとことで
白黒で表せる複数のマスク(AO、粗さ、金属度、発光マスクなど)を、1 枚のテクスチャの R・G・B・A の各チャンネルに 1 つずつ詰め込む手法です。テクスチャの枚数、メモリ、GPU での読み込み回数をまとめて減らせるため、PBR マテリアルでは事実上の標準になっています。glTF の ORM(Occlusion / Roughness / Metallic)テクスチャや、Unreal の「ORM」「MRA」テクスチャがその代表例です。
ゲームでの使いどころ
- PBR マテリアル:AO・粗さ・金属度を 1 枚の ORM テクスチャにまとめる。
- エフェクト用マスク:炎のエフェクトで、R に形、G に歪み用ノイズ、B に色の変化用グラデーションなど、複数の要素を 1 枚にまとめる。
- 地形のスプラットマップ:R = 草、G = 土、B = 岩、A = 雪のように、4 種類の素材の混ぜ具合を 1 枚で持つ。
- UI・フォント:複数のアイコンや、MSDF のように距離情報を別チャンネルに持たせる。
しくみ
カラー画像の各画素は 4 つの独立した数値(R, G, B, A)を持っています。白黒のマスクは 1 つの数値しか使わないので、4 枚のマスクを 1 枚にまとめられます。
| チャンネル | 内容(デモ) | glTF の ORM の慣例 |
|---|---|---|
| R | AO(隙間の暗さ) | Occlusion |
| G | 粗さ(Roughness) | Roughness |
| B | 金属度(Metalness) | Metallic |
| A | 発光マスク | (未使用・用途は自由) |
シェーダーでは 1 回テクスチャを読み、.r .g .b .a を別々の用途に使います。
得られるもの
- テクスチャの枚数が 4 分の 1 → 読み込みの命令数、バインドするテクスチャの数が減る
- メモリ・ダウンロード容量が減る(圧縮形式によっては 4 チャンネルでも 1 チャンネルと同じ効率)
- アセット管理が単純になる
実装のポイント
- 色空間は線形で:マスクは色ではなく数値なので、sRGB として読み込むとガンマ補正がかかって値がずれます。必ず線形(非カラー)テクスチャとして扱います。
- 圧縮形式とチャンネルの品質:BC1(DXT1)などの圧縮では、G チャンネルの精度が高く、R・B は低めです。最も重要なマスク(多くの場合は粗さ)を G に置くのが慣例です。アルファを含めると圧縮率が下がる形式もあります。
- three.js の対応:
MeshStandardMaterialはaoMapを R、roughnessMapを G、metalnessMapを B から読みます。同じテクスチャを 3 つに渡すだけで ORM として機能します(デモもこの方法です)。
つまずきやすい点
- 解像度がそろう:詰め込んだマスクはすべて同じ解像度になります。細かさが必要なマスクと粗くてよいマスクが混在する場合は、分けたほうが効率的なこともあります。
- チャンネルの取り違え:エンジンやツールによって慣例(ORM か MRA かなど)が異なります。書き出し設定と読み込み側の設定をそろえないと、金属と粗さが入れ替わった奇妙な材質になります。
- ミップマップの平均:ミップマップは各チャンネルを独立に平均するので問題ありませんが、アルファで切り抜きも兼ねている場合は、遠景で切り抜きが薄れることがあります。
デモで試すこと
- 右の 4 枚のパネルは、1 枚のテクスチャの R・G・B・A を白黒で表示したものです。それぞれがまったく違うマスクになっています。
- 「B を金属度に使う」をオフにすると、パネル全体が同じ金属度になり、金属と塗装の区別がなくなります。「G を粗さに使う」をオフにすると、光沢のむらが消えます。
- 視点を回して、金属の部分だけが周囲の景色を映し込み、塗装部分がつや消しになっていることを確かめてください。これらすべてを 1 枚のテクスチャで制御しています。