Blender シェーダーノードで反復処理(拡張/侵食)
当noteは、拙著『Blender 4 制作テクニック大全』
に書ききれなかったネタを書き連ねていきます。
使用バージョン4.3.2
概要
ジオメトリノードには[リピートゾーン]が用意されていて反復処理が可能ですが、シェーダーの方にはやる気がないのか技術的な問題か分かりませんが今のところ反復の仕組みがありません。
もしあったら表現の幅は確実に広がるので、無理矢理作っちゃおうというのが今回のネタです。
だけど今後公式にシェーダーの方にもリピートゾーンが実装されれば全くの無用の長物と化す技術なので、本には載せませんでした。
結論から言うと、真の反復は不可能です。
なので、手動による疑似反復をなるべくやりやすくするという方向で考えます。
ノードには、リンクで繋がっている間に他のノードをドロップするとそのノードを間に挿入するようにリンクを繋ぎ直してくれるという機能があります。
これを利用し、ノードをShift+Dで複製、ドラッグで挿入を繰り返し、更にグループ化してまた複製と挿入を繰り返し。。とやるとあっという間に5桁回反復くらいなら簡単に出来てしまいます。
画像処理の方面では5桁回も反復させれば激重になる場合が多いので、これだけ反復できればじゅうぶんでしょう。
ただし、このリンク自動繋ぎ直し機能はリンク一本にしか対応できないため、ソケットの接続を複数必要とするようなノードグループでは一個一個手動で接続しなければいけなくなり大幅に時間がかかってしまいます。
つまり、入力出力共にたったひとつだけのソケットで済ませ、且つそのノードグループを連続して繋げるだけで反復処理となるようなノードグループの中身を作る必要があります。
これが実際やってみるとその難しさに気づきます。
変態ノード芸人の腕の見せ所です。
そもそもの反復の意味
例えば本の267ページ冒頭、リピートの例として示したノードは総和の記号で表現するとこうなります。
$$
\sum_{n=1}^{5}1
$$
つまりこれは
1+1+1+1+1
となり、単なる
1×5
にすぎません。わざわざ総和を使うまでもありません。
一方、例えば1から10の数をすべて足すといくつになるか?という問題を総和記号で表現すると
$$
\sum_{n=1}^{10}n
$$
となり、これは
(1×1)+(1×2)+(1×3)+(1×4)+(1×5)+(1×6)+(1×7)+(1×8)+(1×9)+(1×10)
を意味します。
こちらは総和記号を使わずに短い式で表現することは出来ません(三角数の話は置いておいて)。
つまり、∑の右側にnの記号があること、要するに「今何反復目か?」という変数を式中で使用することで初めて反復に意味が生まれます(無限の話は置いておいて)。
その1から10までの数をすべて足すという操作を、ジオメトリノードで最も簡単に実現するならばこうなります。
この「イテレーション」こそが「今何反復目か?」を出力するソケットであり、0から開始するので11回反復して足し合わせれば0から10までの数字全てを足し合わせた数字が出力されます。
ただし、本の対応バージョンである4.2ではこの「イテレーション」がまだ実装されていないため、こうする必要があります。
もうひとつ整数のソケットを用意し、片方では反復毎に1を足していく仕組みを作り、もう片方のソケットでは先ほどと同じようにそれを足し合わせる仕組みを作っています。つまり、1ずつカウントアップする仕組みを自分で作らなければいけません。
ソケットの数は変数の数です。イテレーションの機能がなければ意味のある反復を行うには必ずソケット(変数)が2つ以上必要になることがおわかりいただけたでしょうか。そしてそもそも反復機能のないシェーダーノードの方ではもちろんこのイテレーションなど用意されていません。
我々にはXYZ分離があるじゃあないか
この解決の鍵となるのが、XYZ分離/合成ノードです。
以下はコンポジターの[拡張/侵食]ノードの[拡張]をシェーダーノードで作ってみたものです。
XYZ分離/合成ノードを使えば、3つのデータをひとつのソケットで入出力させることが出来ます。Xの値でカウントアップ(イテレーション)の仕組みを作り、Yのソケットで実際に処理を行う画像データを扱っています(Zは不使用)。最後に、グループノード外でXYZ分離によりYのみを取り出すことで、結果画像を取得しています。
このグループノードを8つ重ねることで、8方向にそれぞれずらした画像を重ね[拡張]のような見た目を作っています。
8方向では荒いなぁと感じたとしても、この仕組みであれば状況に応じて反復数を簡単に増やすことが出来ます。もっと複雑にすれば[侵食]にも対応できますがそれはまた次回とします。
XYZ分離/合成ノードではなくカラー分離/合成ノードも同じことなのでどちらを使っても構いませんが、XYZの方が数値を直接入力できるので便利かもしれません。また、RGBの1チャンネルを使っちゃってるので、この方法ではカラー画像に対応できません。カラーに対応できる方法も思いついてはいますがだいぶ複雑になりそうなので割愛。カラーに対応できれば、それを利用したシェーダーノードによる「ぼかし」も可能になります。
我ながら天才的発想だと思った三大技術が本のP167のコントラストノードの応用、P178のエッジ抽出、P228の平均値を利用したキャスト変形、そしてこのXYZ分離を利用した疑似反復です。あれ、4つになってる。
すぐ陳腐化しそうな技術ですし、あの本にすら載せなかったらもう発表の場が無いのでここで供養しました。