Smoothness
ハイトマップ

法線マップ(Normal Map)(Bump mapping)

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

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

ディテールが実際のジオメトリでモデリングされた航空機の金属板
ディテールが実際のジオメトリでモデリングされた航空機の金属板

このような場合に、そんな小さなディティールを “実際の” ジオメトリで作成するのは、通常、よい方法ではありません。右側に、ディティールのネジ一個を作成するのに必要なポリゴン数が表示されています。実際にモデル表面にディティールを沢山作り込んだ大きなモデルは、描画するためにとても多くのポリゴンを必要とします。このような状況は避けるべきなので、実際のディティールを作り込む代わりに法線マップを使い、大きなモデルのポリゴン数をできるだけ抑えます。

このディティールをバンプマップで置き換えると、サーフェイスジオメトリをより単純化することができ、ディティールはモデル表面の光の反射具合を変調するテクスチャで置き換えられます。これは、現代のグラフィックスハードウェアが極度に高速処理できるものです。金属質感のサーフェイスは、低ポリゴン数の平面に変えてしまえるし、ネジ、リベット、溝そして傷などもテクスチャによって立体であるかのように光を受けて見えます。

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

現代のゲーム開発におけるアートのパイプラインでは、アーティストは 3D モデリングアプリケーションを使って、とても高解像度なモデルから法線マップを作成します。その後、法線マップはゲーム用に準備されたローポリゴンモデルに適用され、これにより、元の高解像度モデルのディティールは法線マップを使ってレンダリングされる事になります。

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

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

面法線(Surface Normal)とは

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

それぞれ12面を持つ2体の円柱。左側はフラットシェーディング、右側はスムーズシェーディングを使用しています。
それぞれ12面を持つ2体の円柱。左側はフラットシェーディング、右側はスムーズシェーディングを使用しています。

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

それぞれ12面を持つ2体の円柱。左側はフラットシェーディング、右側はスムーズシェーディングを使用しています。
それぞれ12面を持つ2体の円柱。左側はフラットシェーディング、右側はスムーズシェーディングを使用しています。

右側のモデルは左側のモデルと同じポリゴン数ですが、シェーディングはより滑らかに見えます - ポリゴンのライティングは、曲面のように見えます。なぜでしょうか? 答えは、各点で光を反射するための 面法線 が使われており、ポリゴンの幅に渡って徐々に光を変化させているからです。そのため、サーフェイス上の各点では、光は実際の平坦なポリゴンではなく 面が曲がっているかのように 反射します。

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

フラットシェーディングを使用した3つのポリゴンの平面図
フラットシェーディングを使用した3つのポリゴンの平面図

面法線は、オレンジの矢印で表されています。それらは、光がモデル表面でどのように反射するかを計算するのに使われる値であり、面法線が同じ方向を向いているため、どのポリゴンも全体にわたって、光が同じように反応しているのが判ると思います。これが “フラットシェーディング” になります。そしてこれが、左の円柱のポリゴンのエッジが立って見える理由です。

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

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

法線の向きが平らなポリゴンによるモデル表面全体にわたって徐々に変化していると、モデル表面のシェーディングは、滑らかな曲面のように見えます(緑の線で表されています)。これは、メッシュの実際のポリゴン形状には影響していません。フラットな表面上のライティング計算のみに影響します。形状が実際に曲面に変わった訳ではないので、照角から見ると実際の角ばったポリゴン形状が露わになりますが、大体の画角では、円柱は滑らかな曲面に見えます。

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

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

法線マッピングは、一歩進んで、モデル全体で面法線をどのように変更するかという情報を保存するのにテクスチャを使い、この面法線の変更を行います。法線マップはモデル表面に貼られるテクスチャ画像で、普通のカラーテクスチャに似ていますが、法線マップテクスチャの各ピクセル(テクセルと呼ぶ)は、面法線の向きと、フラットな(または滑らかに補完された)ポリゴンによる“本当の”面法線の差分を表しています。

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

この表では、3D モデル表面の 3 ポリゴンのうち、何が再び 2D で置き換えられるかを示していて、オレンジ色の各矢印は、法線マップテクスチャのピクセルに対応しています。下は、法線マップテクスチャを単一ピクセルでスライスしたものです。中央では、法線が変更されたことにより、ポリゴン表面にあるいくらかの凹凸の 見た目 が変わっています。変更された法線がライティングの計算内で使用されるため、これらの凹凸は光が当たったときだけ表面に現れます。

元の法線マップファイルの色味は、一般的に青っぽい色相になっています。そしてここには、実際の明暗による陰影は、まったく含まれていません。これは、色情報をそのまま表示することは意図していないからです。代わりに、各テクセルの RGB 値は、向きベクトルの XYZ 値に置き換えられ、ポリゴンサーフェイスを滑らかに見せるための補完された法線として使われます。

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

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

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

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

法線マップの取得と作成

一般的に、法線マップは、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 倍密度を上げ、表面上のとても小さなひっかき傷やすり傷の凹凸をつけます。それらのディティールは、かなり近づいたときだけ見えるぐらい細かくすることができます。これだけの量のディティールをベースの法線マップ上に描こうとすると、かなり巨大なテクスチャになってしまいますが、異なるスケールで合成すれば、二枚の小さな法線マップテクスチャだけで、全体を覆う高密度なディティールを実現できます。

Smoothness
ハイトマップ