あらすじ
【入門編】Blenderのシェーダーエディターを使ってみよう(2/3)の続きです.
前回のあらすじ:シェーダーの基本形となるDiffuse×Glossyの組み方と,テクスチャの設定方法を解説しました.
今回も下記サイトのテクスチャ画像を使用させていただきます.必要に応じてダウンロードしてください.
無料で使えるPBRテクスチャのサイト(CC0ライセンス)
『CC0 Textures - Public Domain PBR Materials』
物体表面に細かな凹凸を加える手法
ここではオブジェクトに細かな凹凸(ディテール)を加えて質感をクオリティアップさせていく方法について解説していきます.

そもそもの話ですが,人間は映像から3次元の物体を認識することはできないので,何か物体を認識するときは推測に頼っています.これは言い換えると,光と影さえ描写すれば物体の立体感を疑似的に表現できてしまうことになります.
3DCGにおいてはシェーダーを組むことで光と影の描画を行いますが,ほとんどの一般的なシェーダーでは影の濃さは法線(ノーマル)に依存します.

細かい凹凸を表現したいときにポリゴンを細分化しまくって実際に凹凸を作ってしまうというやり方ももちろんありますが,計算負荷を考慮するのであればシェーダーだけで凹凸を表現したくなるはずです.
実際によく使われる手法として,レンダリング時に法線を変更するシェーダーを組むことで,ポリゴンを変形することなく凹凸を表現するという方法があります.
この時,どのように法線を書き換えるかを指定する入力データとして,
バンプマップ,
ノーマルマップと呼ばれる画像データを使用します.
両者とも凹凸を加えるときに使用するという点で似ているので,よく混同されますが「
バンプマップと
ノーマルマップは違うんだぜ」って話は各所で散々説明されてるのでここではさらっと説明する程度にしておきます.
バンプマップとは
バンプマップはポリゴン表面の高さ情報をグレースケールで指定するテクスチャです.もちろん画像データなので色情報が含まれていますが,ここでは色情報を「高さの情報」として使用します.

特徴としては扱うデータが高さのみの1次元データなので,テクスチャの作成は比較的容易です.ただし,通常の画像形式(8bit/チャンネル)で
バンプマップを作成しようとすると256段階でしか高さを指定できないので,
高低差のある長い傾斜なんかは表現しづらいというデメリットがあります.
ノーマルマップとは
ノーマルマップは物体表面の法線を直接ベクトルで指定するテクスチャです.法線は3次元のベクトルなので,画像の各チャンネル(R,G,B)をそれぞれ法線の各要素に割り当てて使用します.

ノーマルマップは
バンプマップとは異なり,単一の画像で直接法線を変更するためやや高速に処理できます.
ノーマルマップを使用することで凹凸を加えることはもちろん,
逆に凹凸を減らして余計な影を消したいときにも用いられます.
上記のように一見メリットは多いのですが,そもそもテクスチャを作成するにはBlenderでベイクしたり,専用のペイントツールを使用したりする必要があります.
これに加えて,
ノーマルマップは正しく扱わないとレンダリング結果がおかしなことになるので,作るにも使うにも少しハードルが高めというデメリットがあります.
バンプマップで凹凸を加えてみる
まずは扱い方が簡単な
バンプマップから見ていきたいと思います.下準備として,以下のようなシェーダー(Diffuse×Glossyの基本形)を組んでおきます.

[画像テクスチャ]ノードを追加後,バンプマップ画像を読み込んでください.ここで色空間を
"sRGB"から
"Non-Color"にしておきます.
バンプマップようにテクスチャの色情報を色以外の用途として使用する場合は基本的に色空間を
"Non-Color"にしておきましょう.(
"sRGB"はガンマ値による補正がかかってしまうため,意図しないレンダリング結果を招くことがあります)

続いて,
[Shift]+[A]>[ベクトル]>[バンプ]から
[バンプ]ノードを追加します.
[バンプ]ノードの
高さソケットにはバンプマップ画像を接続して,
[バンプ]ノードの出力ソケットからそれぞれの
ノーマルソケットに接続するとバンプが適用されます.

バンプマップを適用した結果が下図です.ご覧の通り,かなり強力な効果があることがわかると思います.

ノーマルマップで凹凸を加えてみる
ノーマルマップについても見ていきたいと思います.前項と同様に下準備として,以下のようなシェーダー(Diffuse×Glossyの基本形)を組んでおきます.

[画像テクスチャ]ノードを追加後,ノーマルマップ画像を読み込んでください.ここで色空間を
"sRGB"から
"Non-Color"にしておきます.実は
ノーマルマップを使用するときは特に注意が必要で,
色空間が
"sRGB"のままだと余計な補正処理が加えられてしまうため,法線がおかしなことになってしまいます.

続いて,
[Shift]+[A]>[ベクトル]>[ノーマルマップ]から
[ノーマルマップ]ノードを追加します.
[ノーマルマップ]ノードの入力ソケットにはノーマルマップ画像を接続して,
[ノーマルマップ]ノードの出力ソケットからそれぞれの
ノーマルソケットに接続するとノーマルマップが適用されます.

下図がノーマルマップを適用した結果です.「やったぜ!」と言いたいところですが,視点グリグリ動かすとどうも影に違和感があります.これは一体どういうことでしょうか.

そのノーマルマップ、使い方合ってますか?
ということでノーマルマップ反転問題について触れていきたいと思います.どうも一般的に使用されているノーマルマップには主に2種類の仕様(OpenGL形式,DirectX形式)があるのだそうだ.そして厄介なことに,Gチャンネル(Y軸方向)の扱いがそれぞれ異なるらしい.
確かに先ほどレンダリングした画像についても,X方向の影は問題なさそうだが,Y軸方向の影だけが反転しているように見える.

これを修正するには,ペイントソフトで直接ノーマルマップ画像を修正するという選択肢もありますが,私は面倒なのでシェーダー上で修正してしまいます.
ノーマルマップの修正をするために
[RGB分離]ノードでノーマルマップ画像のチャンネルを分離してしまいます.最終的にそれぞれのチャンネルを合成する必要があるので
[RGB合成]ノードも追加しておきます.

今回はGチャンネルを反転させたいので
[Shift]+[A]>[カラー]>[反転]から
[反転]ノードを追加してGチャンネルを反転させます.また,線とノードが重なって見づらかったのでRerouteノードを配置しています.

めでたく影の向きを修正することができました.やったぜ!

ディスプレイスメントマップを使ってみる
ここまで
バンプマップ,
ノーマルマップによる凹凸の追加方法を見てきましたが,実は凹凸を追加する方法はもう1つあります.(まだあるのかよとか言わない)
バンプマップ,
ノーマルマップではジオメトリを変更せずに影の描写のみでディテールを追加するため,オブジェクトの輪郭が凹凸によって変化することはありませんでした.
でも場合によっては「輪郭もデコボコさせたい」っていうことがあるかもしれません.そんなときには
ディスプレイスメントマップを使用するとよいでしょう.
――
Cyclesのみの対応です(
Eeveeでは使用不可)
シェーダーの組み方は簡単です.ディスプレイスメント画像を
[ディスプレイスメント]ノードでベクトルに変換してから
[マテリアル出力]ノードの
ディスプレイスメントソケットに接続するだけです.

ただし,デフォルトではディスプレイスメントがレンダリング結果に反映されないので,
[プロパティ]ウィンドウ>[マテリアルプロパティ]タブ>[▼設定]>[▼サーフェス]の中にある
[ディスプレイスメント]項目から
"ディスプレイスメントとバンプ"を選択してみてください.

そしてこちらがディスプレイスメントマップを適用したときのレンダリング結果です.圧倒的凹凸感である.

まあ難点としては,凹凸を作るためにはポリゴンを細分化しまくる必要があるってことですかね.(はいネタばらし↓↓↓)

このようにディスプレイスメントは頂点単位でしか適用されません.マシンスペックでゴリ押しできる余裕のある方は是非お試しあれ.
ですが,ディテールを加えるという目的に対して効果が大きいのは明らかです.加えて,テクスチャで表面のジオメトリを制御できるので,直接ポリゴンを編集してしまうよりかは後で修正が効きやすいというメリットはあると思います.
ラフネスマップで濡れ表現
今回はこれで最後の項目としておきます.ここからは
ラフネスマップを用いたオブジェクト表面の濡れ表現をやってみたいと思います.
ラフネス値については前回も少しだけ触れましたが,物体表面の粗さを定義する値です.ラフネス値が小さければ表面がツルツルになり,大きければザラザラとした質感になります.
今回使用してるテクスチャには
ラフネスマップ画像が含まれていたので,まずはこちらのテクスチャを適用したいと思います.

ラフネスマップ画像を
[光沢BSDF]ノードの
粗さソケットに接続します.

レンダリング結果はこんな感じになります.全体的にしっとりした感じになりました.

上図が本来の
ラフネスマップですが,ここから雨上がりの石畳ような質感にしていきたいと思います.物体表面の一部だけを濡れたような見た目にしたいので,
濡らしたい場所を定義する新たなテクスチャをBlenderで新規作成します.
ここではBlendeのテクスチャペイント機能を使用して,濡らしたい部分を適当に暗くペイントしています.

上図のような2つ目のラフネスマップ画像が用意できたらシェーダーを組んでいきます.下図のように
"ラフネスマップ①"と,
"ラフネスマップ②"を
[RGBミックス]ノードを使用して乗算ミックスします.

そしてこちらがレンダリング結果になります(クリック推奨).
"ラフネスマップ②"で暗くした部分が濡れているように見えます.これも静止画だと中々伝わりづらいのですが,リアルタイムレンダリングで視点をグリグリ動かすと質感がよく伝わってきます.

3DCGをやっている人はこのようにラフネスマップを適用させてニヤニヤしながら作業しています(偏見).
最後に
ということで今回も思ったより長くなってしまったのですが,PBRを扱うための基本的な部分は一通り書けたのではないかと思っています.本当はプロシージャルテクスチャとか,ライトパスとかまだまだ書きたいことはたくさんあるのですが,それはまたの機会にしておきたいと思います.
ここまで雑に書いているのでうまくまとまっていない部分もありますが,何かのお役に立てて頂ければ幸いです.