土屋つかさの技術ブログは今か無しか

土屋つかさが主にプログラミングについて語るブログです。

Unity Tips(13:テクスチャを重ねて描画する)

 これまで食わず嫌い的に3Dプログラミングを避けて通ってきたこともあって、「こういう処理は3Dプログラミングでは通常こういうアプローチを取る」というのがわからず、難しいことではないのに解法にたどりつけない事がよくあります。今回もそのパターンの一つ。

 キャラモデルの肌のテクスチャに、例えばホクロとかタトゥーとかを重ねて表示したい時があります(ありますよね?)。このような描画処理のことを「デカール」といいます。このデカール処理をUnityで実現するにはどうすれば良いでしょうか。

 UnityのスタンダードシェーダーにはSecondery Mapsというパラメーターを使って2枚目のテクスチャを指定する機能があります。しかしこの機能はDetail map(詳細マップ。肌の質感などを表現するためにディティール用のテクスチャを重ねる技法)での使用が前提とされていて、設定できるテクスチャマップに制限があります。

セカンダリマップ(詳細マップ)& 詳細マスク
https://docs.unity3d.com/jp/540/Manual/StandardShaderMaterialParameterDetail.html

 また、投影テクスチャマップという技法があります(Unityでは「プロジェクター」という機能として実装)。これは、メッシュに対して動的にテクスチャを投影(プロジェクション)するという物で、FPSで壁に弾痕を開ける場合などに活用されます。ただ、これは投影先が静的なオブジェクトであることが前提であり、今回の事例には大げさです

プロジェクター
https://docs.unity3d.com/ja/current/Manual/class-Projector.html

 いっそのことスタンダードシェーダーを拡張して複数のカラーマップ(実際に描画される色が書かれたテクスチャのこと。Albedo、Diffuseと呼ばれることが多い)を入力とするシェーダーを自作する方法もあるかもしれませんが、もっと手軽にできないものでしょうか。

 解答はシンプルで、MeshRendererオブジェクトのInspectorからMaterialsの数を増やします。
f:id:t_tutiya:20201004222657p:plain
 Materialsには、そのMeshRendererが管理するサブメッシュ(メッシュ3Dモデルデータの管理単位。メッシュ(一つの3Dモデル)は複数のサブメッシュから構成される)に適用されるMaterialオブジェクトを保持する配列です。

 サブメッシュには複数のマテリアルを持たせることがあります。例えば、ヘッドとボディを1つのサブメッシュで作っているものの、マッピングするマテリアル(≒テクスチャ)はヘッドとボディで分けたい時などです。

 このMaterialsの配列要素が、モデルデータ側で設定されているよりも多い場合、その分は全て最初の要素に上書きされます(ベースのマテリアルが2個あったら、交互に適用されても良さそうな物ですが、まあそういう物なのでしょう)。これによって、通常のテクスチャの上に、任意のテクスチャを重ねて描画することができます。

 注意点として、Materialsは配列なので、実行時に要素数を増やす事はできません(多分間違い。下記コメント欄参照)。なのであるメッシュに最大何枚重ねる予定なのかは先に決まっている必要があります。また当然ながら、上書きする方のテクスチャに透明or半透明な部分が無ければ意味がありません。

Mesh Renderer(ドキュメントがアップデートした直後のため、この記事を書いている時点では大半が原文のままですが、一番下のパラグラフに関連記事があります)
https://docs.unity3d.com/ja/current/Manual/class-MeshRenderer.html

追記

今回は静的(?)な解決手段を示しましたが、動的に解決するならRenderTextureを使うという手もあるかもです。

[asin:4862464130:detail]