Version: 2023.1
言語: 日本語
Smoothness
Heightmap

法線マップ (バンプマッピング)

法線マップは バンプマップ の一種です。モデル表面に凹凸や溝、傷などのディティールを追加する特殊な種類のテクスチャで、実際のジオメトリであるかのようにライトを受けます。

Unity は Y+ 法線マップ (OpenGL 形式とも呼ばれます) を使用します。

例えば、ボルトや溝、またはリベットなどを、航空機の機体のようなサーフェス全体につけたいような場合があります。これを実現する方法の 1 つは、以下のように、それらの細部をジオメトリで作成することです。

細部が実際のジオメトリでモデリングされた航空機の金属板
細部が実際のジオメトリでモデリングされた航空機の金属板

このような場合に、そんな細かい部分を “実際の” ジオメトリで作成するのは、通常、よい方法ではありません。右側に、細部のネジ 1 個を作成するのに必要なポリゴン数が表示されています。実際に表面に細かいサーフェス細部を沢山作り込んだ大きなモデルは、描画するためにとても多くのポリゴンを必要とします。このような状況を避けるために、法線マップを使って細部を表し、大きなモデルには低解像度のポリゴンサーフェスを使用するべきです。

代わりに、この細部をバンプマップで表すと、サーフェスジオメトリがはるかに単純になり、細部は、ライトが表面でどのように反射するかを調整するテクスチャとして表されます。最新のグラフィックスハードウェアはこれを非常に高速に実行できます。これで、メタルサーフェスを低ポリゴン数の平面にすることができ、ネジ、リベット、溝、および引っかき傷がライトを捕らえ、テクスチャのおかげで深度があるように見えます。

ネジ、溝、傷が一つの法線マップ(Normal Map)で設定されています。これにより、平面を低ポリゴン数に抑えたまま、そのサーフェス上での光の反射具合を調整でき、3D ディテールのような印象を与えることができます。リベットやネジのようなものだけでなく、微かな凸凹や傷などの極度に精密な詳細も、1 つのテクスチャに含めて表現することが可能です。
ネジ、溝、傷が一つの法線マップ(Normal Map)で設定されています。これにより、平面を低ポリゴン数に抑えたまま、そのサーフェス上での光の反射具合を調整でき、3D ディテールのような印象を与えることができます。リベットやネジのようなものだけでなく、微かな凸凹や傷などの極度に精密な詳細も、1 つのテクスチャに含めて表現することが可能です。

現代のゲーム開発におけるアートのパイプラインでは、アーティストは 3D モデリングアプリケーションを使って、とても高解像度なモデルから法線マップを作成します。次に、法線マップがモデルの低解像度のゲーム対応バージョンにマップされるため、法線マップを使用して元の高解像度の細部が描画されます。

バンプマップ(Bump Map)の作成と使用

バンプマッピングは比較的古くからあるグラフィックスの手法ですが、いまだに写実的なリアルタイムグラフィックスを作成するための主要な技法の一つです。一般的に、バンプマップは 法線マップハイトマップ とも呼ばれますが、これらの用語は、以下で説明するように少し意味が違います。

面法線(Surface Normal)とは

実際に法線マッピングがどのように機能するかを説明するために、最初に “法線” とは何か、リアルタイムライティングでどのように利用されるかを説明します。おそらく、最も基本的な例は、各サーフェスポリゴンが、ライトに対する表面角度に従って単純に照らされるモデルです。表面の角度は、面から垂直方向に突き出た線として表現することができ、この面からの方向 (ベクトル) は 面法線、もしくは単純に 法線 と呼ばれます。

それぞれ12面を持つ2体の円柱。左側は平たんなシェーディング、右側は滑らかなシェーディングを使用しています。
それぞれ12面を持つ2体の円柱。左側は平たんなシェーディング、右側は滑らかなシェーディングを使用しています。

以下の画像では、左側の円柱は基本的な平らなシェーディング (陰影) になっていて、ポリゴンごとにその光源に対する相対的な角度で陰影がつけられています。面が平らなため、各ポリゴンのライティングはポリゴンの領域全体で一定です。ここに、メッシュのワイヤーフレームが表示された同様の円柱が2つあります。

それぞれ 12 面を持つ 2 体の円柱。左側は平たんなシェーディング、右は滑らかなシェーディングを使用しています。
それぞれ 12 面を持つ 2 体の円柱。左側は平たんなシェーディング、右は滑らかなシェーディングを使用しています。

右側のモデルは左側のモデルと同じポリゴン数ですが、シェーディングはより滑らかに見えます。ポリゴンのライティングによって曲面のように見えます。なぜでしょうか? その理由は、ライトを反射するために使用される各ポイントの 面法線 がポリゴンの幅全体で徐々に変化するため、サーフェス上の任意のポイントで、ライトは そのサーフェスがまるで湾曲しているかのように バウンドします。実際はそうである、平らな定数ポリゴンでないように見えます。

平面図で表すと、平たんなシェーディングを使用した円柱の表面の 3 つのポリゴンは以下のようになります。

平たんなシェーディングを使用した 3 つのポリゴンの平面図
平たんなシェーディングを使用した 3 つのポリゴンの平面図

面法線はオレンジ色の矢印で表されます。 これらは、ライトがサーフェスでどのように反射するかを計算するために使用される値です。サーフェスの法線は同じ方向を指しているため、各ポリゴンの長さ全体でライトが同じように反応することがわかります。 これにより “平たんなシェーディング” が得られ、左の円柱のポリゴンにハードエッジがあるように見えるのはこのためです。

一方、スムーズシェーディングを使用した円柱では、ポリゴンの面の各地点で面法線が変化します。

スムーズシェーディングを使用した3つのポリゴンの平面図
スムーズシェーディングを使用した3つのポリゴンの平面図

法線の向きは平らなポリゴンサーフェス全体で徐々に変化するため、サーフェス全体のシェーディング (陰影) で、滑らかな曲面のように見えます (緑の線で表されています)。これは、メッシュの実際のポリゴンの本質には影響していません。平らな平面上のライティング計算のみに影響します。この見かけの曲面は実際には存在せず、視線角度でサーフェスを表示すると、平らなポリゴンの本質が明らかになります。ただし、ほとんどの表示角度からは、円柱は滑らかな曲面を持っているように見えます。 

この基本的な滑らかなシェーディングを使うと、法線方向は 頂点ごと でしか保存されないので、モデル表面全体にわたって値を変更すると、ある頂点から次の頂点までは補完されます。以下の表では、赤い矢印が頂点ごとに保存された法線方向を表し、オレンジの矢印は、ポリゴンの領域全体にわたって補完された法線方向を例示しています。

法線(Normal)マッピングとは

法線マッピングは、テクスチャを使用してモデル全体の法線を変更する方法に関する情報を格納することにより、この法線の変更をさらに一歩進めます。 法線マップは、通常のカラーテクスチャと同様に、モデルのサーフェスにマップされた画像テクスチャです。ただし、法線マップのテクスチャの各ピクセル (テクセルと呼ばれます) は、平たんな (または滑らかに補間された) ポリゴンの “真の” 面法線から離れた面法線方向の偏差を表します。

3 つのポリゴン上の法線マッピングの平面図
3 つのポリゴン上の法線マッピングの平面図

この図も 3D モデルのサーフェス上の 3 つのポリゴンの 2D 表現であり、各オレンジ色の矢印は法線マップテクスチャのピクセルに対応しています。下は、法線マップテクスチャの 1 つのピクセルスライスです。 中央では、法線が変更されており、ポリゴンの表面にいくつかのバンプの外観が表示されています。これらのバンプは、これらの修正された法線がライティングの計算に使用されるため、サーフェス上でのライトの表示方法によってのみ表われます。

元の法線マップファイルの色は、一般的に青っぽい色相になっています。そしてここには、実際のライトや陰影は、まったく含まれていません。理由は、色そのものを表示することは意図されていないからです。代わりに、各テクセルの RGB 値は、方向ベクトルの X、Y、Z 値に置き換えられ、それらはポリゴンサーフェスの補間された基本的な滑らかな法線への変更に使用されます。

法線マップ テクスチャの一例
法線マップ テクスチャの一例

これは、ちょっとした長方形とテキストを押し出す凹凸情報を内包した、シンプルな法線マップです。この法線マップを Unity にインポートし、スタンダードシェーダーの法線マップスロット内に配置することができます。マテリアルでカラーマップ (アルベドマップ) と複合し、上方の円柱メッシュの表面に適用すると、結果はこのようになります。

上記の円柱メッシュの表面に、上図のサンプル法線マップを適用した状態
上記の円柱メッシュの表面に、上図のサンプル法線マップを適用した状態

繰り返しますが、これは実際のポリゴンメッシュ形状には影響しません。モデル表面の光源計算にのみ影響します。このモデル表面の文字と形状の突き出た部分は本当に突き出ている訳ではないので、視射角から面を見ると、本当は平らな面である事が判ってしまいます。ですが、ほとんどの視野角では、円柱の表面にディティールが浮き出ているように見えます。

法線マップの取得と作成

一般的に、法線マップは、3Dかテクスチャのアーティストが、彼らの製作するモデルやテクスチャの組合せから生成します。アルベドマップの内容やレイアウトは、ミラー (左右反転) される事がよくあります。時には手描きで生成したり、時には3Dアプリケーションでレンダリングしたりします。

3Dアプリケーションで法線マップをレンダリングする方法は、このドキュメントの主題から外れてしまいますが、基本的な考え方としては、3Dアーティストが2種類のモデル(ポリゴンですべてのディティールを作成した超高解像度モデルと、“ゲーム用”の低解像度モデル)を製作する、というものです。高解像度モデルは、快適にゲームを実行するにはディティールが多すぎ(メッシュのトライアングルが多すぎ)ますが、3Dモデリングアプリケーションで法線マップを生成するのに使われます。低解像度モデルは、法線マップに焼き込まれたディティールを使って描画するので、ジオメトリのディティールはかなり省くことができます。典型的な使い方としては、キャラクターの服装のしわ、ボタン、バックルそして縫い目などが挙げられます。

普通の写真的なテクスチャのライティングを分析して、そこから法線マップを生成するソフトウェアも存在します。それらでは、元となるテクスチャが単一方向から照らされているものと仮定して、明部と暗部が解析され、面の角度が設定されます。しかしながら、バンプマップを使う場合には、アルベドテクスチャ画像が特定の方向からのライティングを受けていない状態になっている事を確認してください(ライティングをまったく受けていない状態のモデル表面の色が理想的です)。ライティング情報は、ライトの向き、面の角度、そしてバンプマップ情報などを使ってUnityが計算するからです。

ここに二つの例を挙げます。ひとつは単純な繰り返しの石塀テクスチャと、それに対応した法線マップ。もうひとつはキャラクターのテクスチャアトラスと、それに対応した法線マップです。

石塀テクスチャとそれに対応した法線マップ
石塀テクスチャとそれに対応した法線マップ
キャラクターのテクスチャアトラスとそれに対応した法線マップアトラス
キャラクターのテクスチャアトラスとそれに対応した法線マップアトラス

バンプマップ・法線マップ・ハイトマップの違い

法線マップ(Normal Map)ハイトマップ(Height Map) はそれぞれ、バンプマップ(Bump Map)の タイプ です。両方とも、単純なポリゴンのメッシュ上にある詳細を表現するためのデータを含んでいますが、そのデータの保存方法が異なります。

【左】石塀のバンプマッピング用のハイトマップ 【右】石塀のバンプマッピング用の法線マップ
【左】石塀のバンプマッピング用のハイトマップ 【右】石塀のバンプマッピング用の法線マップ

左上の画像では、石塀のバンプマッピングにハイトマップが使用されています。ハイトマップはシンプルな白黒のテクスチャで、各ピクセルが、表面上のそれぞれの地点がどの位盛り上がって見えるべきかを表しています。ピクセルの色が白に近いほど、そのエリアが高く盛り上がって見えます。

法線マップは、変更を加えていない面法線によるサーフェイスの向きと、各ピクセルの方向の違いを表しているRGBのテクスチャです。ベクトルをRGB値として保存している事から、これらのテクスチャの色味は、青っぽい紫色になります。

最新のリアルタイム 3D グラフィックスハードウェアは、法線マップに依存しています。これは、法線マップがサーフェスでの光の反射結果に変更を加える際に必要なベクトルを内包できるためです。Unity では、バンプマップ用にハイトマップも設定できますが、ハイトマップは使用するためにインポートする際に法線マップへ変換する必要があります。

青紫色になる理由

法線マップを使うのに、この事を理解する必要はありません。この段落は、とばしても大丈夫です。RGBのカラー値はX,Y,Zのベクトルの方向を保存するために使われます。Zが“上方向”になります(逆に、Unityでは慣例的にYが“上”)。加えて、テクスチャのZ値は、0.5が足されて半分になります。これは、すべての向きのベクトルを保存するためです。そのため、RGBカラーをベクトル方向に変換するには、2倍してから1をひかなくてはなりません。例えば、RGB値が (0.5, 0.5, 1) つまり16進数で #8080FF の場合、ベクトルにした結果は(0,0,1)になります。この値は法線マッピングでの“上方向”になり、モデル表面は何も変わりません。これはこのページの最初の方にあった“実例”の法線マップの、平らなエリアの色と同じです。

 法線マップ全体が #8080FF になっていると、これは法線方向 0,0,1 つまりまっすぐ上 に変換されます。この場合、ポリゴンの面法線や、光の当たり方には何の変更も加えません。各ピクセルが結果的に異なる色になった場合は、その地点のベクトル方向が他とは異なっている事を示しており、そのため、その地点で光が反射する角度の計算に変更を加えます。
法線マップ全体が #8080FF になっていると、これは法線方向 0,0,1 つまり“まっすぐ上” に変換されます。この場合、ポリゴンの面法線や、光の当たり方には何の変更も加えません。各ピクセルが結果的に異なる色になった場合は、その地点のベクトル方向が他とは異なっている事を示しており、そのため、その地点で光が反射する角度の計算に変更を加えます。

値が (0.43, 0.91, 0.80) の場合、ベクトルは (–0.14, 0.82, 0.6) になり、サーフェイスはかなり急斜面になります。このような場合の色味は、石壁上部のフチ部分の法線マップに見受けられるような、明るいシアンになります。これは、それらフチ部分が、石の平坦な部分とはまったく違う角度として光を受ける事を表しています。

 これらの石の法線マップにある明るいシアンの領域は、それぞれの石の、角部分のポリゴンの面法線を急角度に変更するため、光は修正された角度に当たります
これらの石の法線マップにある明るいシアンの領域は、それぞれの石の、角部分のポリゴンの面法線を急角度に変更するため、光は修正された角度に当たります

法線マップ(Normal Map)

バンプマップエフェクトのない石塀。石の縁や面は、シーン内の太陽の Directional ライト(日光)を受けていません。
バンプマップエフェクトのない石塀。石の縁や面は、シーン内の太陽の Directional ライト(日光)を受けていません。
同じ石塀にバンプマッピングを適用したもの。日光(Directional ライト)による石の照らされ方が、太陽に面した部分と面してない部分でまったく異なっています。
同じ石塀にバンプマッピングを適用したもの。日光(Directional ライト)による石の照らされ方が、太陽に面した部分と面してない部分でまったく異なっています。
上図と同じバンプマップが適用された石塀で、ライティング条件を変えた例。たいまつのポイントライトが石を照らしています。石塀の各ピクセルの照らされかたは、ベースモデル(ポリゴン)に光が当たる角度(法線マップのベクターで調整)に応じて異なっています。したがって光に面したピクセルは明るく、面していないピクセルは暗く、あるいは影になっています。
上図と同じバンプマップが適用された石塀で、ライティング条件を変えた例。たいまつのポイントライトが石を照らしています。石塀の各ピクセルの照らされかたは、ベースモデル(ポリゴン)に光が当たる角度(法線マップのベクターで調整)に応じて異なっています。したがって光に面したピクセルは明るく、面していないピクセルは暗く、あるいは影になっています。

法線マップとハイトマップのインポートと使用

法線マップは、アセットフォルダーのテクスチャファイル置き場から普通にインポートできます。ですが、Unityにそのテクスチャが法線マップであることを宣言する必要があります。これは、インポート設定のインスペクターで “Texture Type” を “Normal Map” に変更することで行います。

白黒のハイトマップを法線マップとしてインポートするときは、 “Create from Greyscale” オプションにチェックを入れます。それ以外は同じです。

“Create From Greyscale” を選択すると、インスペクターに Bumpiness のスライダーが表示されます。これを使うと、ハイトマップを法線マップに変換する際の角度を、どのぐらい急にするか調節できます。値を低くすると、ハイトマップでコントラストが高い部分でも、緩やかな角度の凹凸になります。値を高くすると、凹凸は誇張され、当たった光の明暗差が激しくなります。

【上】ハイトマップを法線マップとしてインポートする際に Bumpiness を低く設定した場合と、高く設定した場合。【下】それぞれがモデルに反映されたもの。settings when importing a height map as a normal map, and the resulting effect on the model.
【上】ハイトマップを法線マップとしてインポートする際に Bumpiness を低く設定した場合と、高く設定した場合。【下】それぞれがモデルに反映されたもの。settings when importing a height map as a normal map, and the resulting effect on the model.

法線マップをアセットに登録したら、マテリアルインスペクターにある Normal Map スロットに入れる事ができるようになります。もちろん Standard Shader には Normal Map スロットがありますし、古いシェーダーでも、その多くは法線マップをサポートしています。

法線マップテクスチャをマテリアルの適切なスロットに配置します。ここでは標準シェーダーを使用しています。
法線マップテクスチャをマテリアルの適切なスロットに配置します。ここでは標準シェーダーを使用しています。

法線マップやハイトマップをインポートしたのに、法線マップである印(上で説明した Texture Type: Normal Map の選択)をつけなかった場合、マテリアルインスペクターは警告を出し、以下のように解決を指示します。

インスペクター上で法線マップである事を示す印を付けないまま使おうとすると Fix Now 警告が出現します。
インスペクター上で法線マップである事を示す印を付けないまま使おうとすると “Fix Now” 警告が出現します。

“Fix Now” をクリックするのは、テクスチャインスペクターの設定で Texture Type: Normal Map を選択するのと同じ事になります。これは、テクスチャが本当に法線マップだった場合は機能しますが、グレースケールのハイトマップだった場合、自動的に検出される事はありません。ハイトマップの場合は必ずテクスチャインスペクターウインドウにある “Create from Greyscale” オプションを選択してください。

補助の法線マップ

スタンダードシェーダーのマテリアルインスペクター下段に、補助法線マップ用スロットがある事にも注意してください。これは、ディティールを増やすための追加法線マップを使える、という事です。通常の法線マップ用スロットと同じ方法で、このスロットに法線マップを追加することができますが、補助法線マップのスケールやタイリング数を変えて、高レベルのディティールを作成することが意図されています。例えば、通常の法線マップで乗り物や壁のパネルのディテールを定義し、パネルのエッジに木立を加えます。補助法線マップは、基本となる法線マップより 5 - 10 倍密度を上げ、表面上のとても小さなひっかき傷やすり傷の凹凸をつけます。それらの詳細は、かなり近づいたときだけ見えるぐらい細かくすることができます。これだけの量の詳細を基本の法線マップ上に描こうとすると、かなり巨大な基本法線マップになってしまいますが、異なるスケールで 2 つを組み合わせると、補助の小さな法線マップテクスチャだけで、全体的な詳細レベルを高くすることができます。

Smoothness
Heightmap