-Cycles Displacement ノードを使ってみよう-

0. Displacement

Cycles や Eevee を使うと、ノードを組み合わせたシェーダーでマテリアルを表現します。
多くの場合は、色や見た目のでこぼこだけを設定するわけですが…
時々、表面の見た目だけではなくて、本当に変形しているとしか思えない表現を見かけます。
すごい立体感!超絶技術で見た目を制御している…だけではなくて、ほんとうに変形していることがあります。
そう、シェーダーで形状の制御もできるのです。
(2.91現在は Cycles 限定の機能です。Eevee の土台になっている Open GL 上でも原理的には不可能ではないはずですが…現状では未実装です)

シェーダーから形状を制御する、Displacement の機能を使ってみましょう。

1. Displacement ノード

まずは、一般的な疑似凹凸表現である、Bump(バンプ)を使ってみます。

ノイズテクスチャをバンプにつないで、シェーダーの Normal ソケットにつなぎます。
普通に Princepled BSDF を使っても良いのですが、キャプチャ画面を小さくするために Diffuse BSDF を使いました。


表面に凹凸が付きました。
厳密には、凹凸ができたように見える陰影が表示されました。

次に、(処理が二重にならないように)バンプを外して、
(Displacement)ディスプレイスメントノードを、マテリアル出力の Displacement ソケットにつなぎます。


ところが、結果はほとんど同じです。
デフォルト設定では、バンプと同じことをするだけです。
(そのため、Eevee 上でもここまでは Cycles と同じ結果になり、互換性があります)


ここで、マテリアルの設定の Displacement の設定を変更します。
「バンプのみ」、から「ディスプレイスメントのみ」にします。

「ディスプレイスメントとバンプ」にすると処理が二重になります。
後述の理由で、わざと二重がけする場合もあるのですが、話がややこしくなるので、今回は「のみ」を選びます。


結果は、凸凹どころか効果が消えてしまったように見えますが…
これは、デフォルトキューブが頂点が 8 つしかないためです。
変形は、無制限にかかるわけではなく、あくまで頂点の位置を変形することしかできません。
そのため、デフォルトキューブのような場合は頂点数が足りな過ぎて凹凸が見えなくなってしまいます。



そこでSubdivision Suface (サブディビジョンサーフェス)のモディファイアをセットしてみましょう。
凹凸をはっきり見るにはある程度の頂点数が必要なので、数値をやや多めにします。



シェーダーによって、実際の形状を変えることができました。



実際に使うには、頂点の数を十分に増やせない場合もあります。
そのような場合に、大まかな形は変形、細部はバンプ、という処理をするために、どちらも有効にすることができます。
(これは、本当のところは二重がけになっているので弊害もあるはずなのですが、凹凸の頂点が少なすぎるよりは良い、という時に使います)

2. Adaptive Subdivision

さて、Subdivision Surface でメッシュを細かくできるとしても、カメラから離れた遥か向こうのオブジェクトに対して大量の頂点を使ったりしたくはありません。
距離に応じて細かさが変えられたら。できれば自動で変えられたら…
という気がします。実は「実験的機能」として実装されています。
「実験的」の名目がなかなか取れないので、何らかの問題を抱えているのかもしれませんが、難しいことをしなければ普通に使えるようです。



Cycles の設定で、Experimental (実験的)機能を有効にします。



すると、Subdivision Surface に Adaptive Subdivision (適応サブディビジョン)の項目が現れるので、有効にします。



近くの物は細かく、遠くの物は粗く分割されています。
遠くの物は、遠いので粗いのかどうか良く分からないのですが…
おそらくそうなっています。

3. Vector Displacement

バンプによる凹凸に相当する変形をする Displacement ノードは、法線の方向に頂点が移動します。

変形をもっと自由に好きな方向に制御したい場合は、Vector Displacement を使います。
ベクトルのソケットが、色用のソケット(黄色)なのが気になりますが…
色としてはおかしい負の値も問題なく受け付けるようです。

座標系は、ワールド座標系や、オブジェクト座標系を使います。
タンジェント座標系を利用するのは、UV の貼り方などに依存するので難易度が高いです。
ソケットに単純なベクトルをつなげば、平行移動が簡単に表現できます。


平面から球を作る変形をさせてみましょう。



元の平面の(x,y) を、球座標の(θ,φ)とみなすようにします。

Map Range (範囲マッピング) を使って、
それぞれ [-1, +1] の範囲を [-pi/2, +pi/2]、[-pi, +pi]に焼きなおします。
(pi はピじゃなくて、円周率3.15159...です)



(θ,φ)座標を、XYZ の空間に戻して、半径1の球にします。

X = cosθcosφ
Y = cosθsinφ
Z = sinθ

これで、球の表面の位置が求まったわけですが、
元の平面の位置から変形させて球にするので、(球の位置 - 平面の位置) の差が必要な移動量になります。
ベクトル演算の Substract(減算)を使って、元の位置(Position)との差を取ります。



差分を Vector Displacement ノードにつないで、Material Output につなぎます。
折角なので、変形が分かりやすくなるように市松模様も表示するようにしましょう。
この Checker Texture は、UV に従った模様なので、変形の際の位置の対応関係を把握することができます。



変形の度合いを [0-1] で変化させるアニメーションにすると、このようになります。

最後に、ノード構成全体の画面をつけて、今回の内容を終わりましょう。
この内容は、2020 Blender Advent Calendar に合わせて公開されたものです。
まだ空きが多いようなので。
明日は1枚の板から4つのパーツに分割する方法を見てみます。






しかし、ノードの弱点の一つは、表示に面積を必要とする(でかい)ことですね。
ノード内のコメントで書いた式の部分は、
スクリプトが可能であれば、数行で済むところです。

ノードすごい!と、手放しで称賛していると、この辺の改善が後周りになってしまうので、
ぜひ、ノードも良いけど、スクリプトが欲しいよね!
という風潮にしたいところです。

(スクリプトノードが実装されれば、一気に事態は改善されるはずですが、さて!)

inserted by FC2 system