Open8

Blender備忘録(GeometryNodes編)

thecoolmuseumthecoolmuseum

Blender、世紀末1998年頃からちょっとさわっては挫折し、数年後にまた完全に記憶をうしなってから再び入門するという、記憶が無い系タイムループものの主人公だったことに気づいた俺。
このループから抜け出すために、今回のループではBlenderについて知ったことを書き残しておこうと思う。今回もループから抜け出せなかったとしても、次のループの俺につながるように……

主に Blender の Geometory Nodes でやったことや気づいたことをメモしていくためのスクラップです。
検証環境: Blender4.2~4.3あたり、Windows11

thecoolmuseumthecoolmuseum

まずラインを表示したい

ラインを表示するには色々方法があるが、今回はカーブで表示するためにCurve Lineを使用する。

  • Blenderを起動し上部レイアウト選択タブよりGeometry Nodesレイアウトに切り替える

  • 3Dビューでデフォルトキューブを選択する

  • 下部のジオメトリーノードビューの上部の + New ボタンをクリックして新しいノードを作成

  • Homeキー で、表示内容をビューにフィットさせる

  • @キーで表示されるパイメニューから Top を選択し、XY平面を表示する

  • ジオメトリーノードビューで、 Shift+A で新規ノードの追加

  • Curve>Primitives>Curve Line を選択

  • 追加されたノードを適当な場所に配置

  • ノードのパラメータStartに(-1.0, 0.0, 0.0)、Endに(1.0, 0.0, 0.0)を設定

  • Curve Line ノードの右端のCurveソケットから、Group OutputノードのGeometryソケットに接続

    長さ2mのラインが原点位置に表示できた。

thecoolmuseumthecoolmuseum

座標を変えて関数をグラフ表示したい

まずは位置を変更したい

カーブの表示位置を移動するには Set Position ノードを使用する

  • Shift+A を押し、続けて set pos と入力すると検索結果にSet Positionが出るので選択する
  • 表示されたノードを確定せずに、 Curve Line と Group Output を結ぶ線の間にドロップすると自動的に結線される
  • Offset に (1.0, 0.0, 0,0)を設定するとラインの表示位置が変更されることを確認できる

もとの位置座標を参照して位置を設定したい

頂点単位で位置を設定したいので、Set PositionのPositionにベクトルデータを入力する

  • Set Position ノードの Offset を(0.0, 0.0, 0.0)に戻す
  • Shift+A から CombineXYZ を追加し(XYZで検索すると早い)、 Vector 出力を Set Position 入力に接続する(この時点でいったん頂点が(0.0, 0.0, 0.0)に集約されラインが見えなくなる)
  • Shift+A から SeparateXYZ を追加し SeparateXYZ の X,Y,Z 出力から CombineXYZ の X,Y,Z 入力に接続する

    この時点ではもとの座標情報が入力されていないので、正しくラインが表示されていない
  • Shift+A から (Geometry>Read) Position を追加し、Position の Position 出力を SeparateXYZ の Vector 入力に接続する

    再びラインが正しく表示された
    ※この手順では先を見越して CombineXYZ SeparateXYZ を導入しているが、バラしてまとめ直しているだけなので、結果はこれでも一緒である

    ところで、この Position ノードは突然ポッと置かれており、どこからも値を取っていないように見える。何の座標を取っているのであろうか?ひし形の入出力ソケットで結ばれる接続をフィールドと言うらしい。
    Blender オンラインマニュアルにはこうある

基本的に、フィールドは関数です

https://docs.blender.org/manual/ja/4.2/modeling/geometry_nodes/fields.html

ほーん、そこから類推するとおそらくジオメトリーノードは、左から右に流れるフローに見えるが、実際は右から左に流れる関数の呼び出し階層と理解するのがいいのでは無いだろうか。
つまりこのノードはこんな感じのコードで表されるのでは無いか?(現在の理解に基づく妄想である)

GroupOutput(
    SetPosition(
        CurveLine([-1,0,0],[1,0,0]),
            CombineXYZ(
                SeparateXYZ(ReadPosition, 'X'),
                SeparateXYZ(ReadPosition, 'Y'),
                SeparateXYZ(ReadPosition, 'Z')
            )
    )
)

実行プロセスは多分こんな感じ

  • GroupOutput が SetPostion を呼び出す
  • SetPosition が CurveLine を呼び出す
  • CurveLine が ラインのカーブモデルを返す
  • SetPosition が カーブモデルの点を順にループ
  • SetPosition が点のオブジェクトをそえて CombineXYZ を呼び出す
  • CombineXYZ が XYZ 各軸ぶん順に点のオブジェクトをそえて SeparateXYZ を呼び出す
  • SeparateXYZ は点のオブジェクトをそえて ReadPostion を呼び出す
  • ReadPosition は受け取った点オブジェクトの位置座標を返す
  • SeparateXYZ は返された位置座標(ベクトルデータ)の XYZ 成分をそれぞれ読み出して数値を返す
  • CombineXYZ は返された数値をまとめて再びベクトルデータにまとめて返す
  • SetPosition は返されたベクトルデータを点の座標に設定する
  • SetPosition はすべての点の座標を計算し終わるまでループしたら、座標変換済みのカーブモデルを返す
  • GroupOutput が受け取ったカーブモデルをシステム?に返す
  • 表示される
    「OK完全に理解した。つまりジオメトリーノードは関数型プログラミング言語だったんだよ!人類は滅亡する!」な、なんだってー
    キバヤシポーズで手をワキワキしながら、ぼんやりとこういうふうに考えたらジオメトリーノードとやっと少し仲良く慣れた気がする。

一次関数をグラフ表示したい

一次関数 Y=X のグラフを表示したい。Y座標の値がXになればよいのだから

  • SeparateXYZの X 出力から CombineXYZ の X 入力に接続する ( Z-Z の接続は削除しても良い )

    懐かしの斜め線グラフが表示された
thecoolmuseumthecoolmuseum

さらに関数をグラフ表示したい

さらに一次関数を表示したい

一次関数といえばやはり Y=AX+B ではないだろうか。

  • いろいろ書けるように、SeparateXYZより左をドラッグで矩形選択して左に移動、残りも選択して右に移動する
  • Shift+A から (Utility>Math) Math を追加して、SeparateXYZ の X 出力と CombineXYZ の Y入力の間に挿入する
  • あたらしく追加した Math のドロップダウンから Multiply(乗算) を選択する、 Value 数値入力欄に -1.0 を設定する
  • Shift+A から (Utility>Math) Math を追加して、Math の Value 出力と CombineXYZ の Y入力の間に挿入する
  • あたらしく追加した Math のドロップダウンから Add(加算) を選択する、 Value 数値入力欄に 0.5 を設定する

    Y=AX+BにA=-1,B=0.5を代入した、Y=-X+0.5のグラフが表示された

二次関数を表示したい、が

次は順当に二次関数を表示したい。Y=X^2を考える。X^2はX*Xとして考える

  • Math Multiply ノードの Value 入力の空いている方にも SeparateXYZ の X 出力から接続する
  • Math Add ノードを選択し、 M キーを押すとミュートして実行を抑制できる

    無事に Y=X^2 のグラフが表示され……ていない

カーブを細分割する

Curve Line は始点と終点の2点しか無い直線カーブ(?)であるため曲線が表現できない。再分割して中間点にも座標を設定できるようにする

  • Shift-A から Resample Curve を追加し、Curve Line の Curve 出力と Set Position の Geometry 入力の間に挿入する

    曲線として表示されたが、Resample Curve の分割数が10のため曲線は荒い
    ※みやすさのため Viewport Overlays から 3D Cursor を非表示にした

    また拡大してよくよく見ると原点を通っていない。頂点数が偶数の場合、真ん中の点が存在しないため
  • Resample Curve の Count 数値入力欄に奇数である 51 を設定する

    原点を通る滑らかなカーブとして表示された
thecoolmuseumthecoolmuseum

さらにさらに関数を表示したい

三角関数を表示したい

関数といえば、何に役立つのかわからないでおなじみの三角関数を書いていく

  • Math Multiply ノードと Math Add ノードをマウスでドラッグして矩形選択して、 Ctrl+X で削除する(Xで削除する場合と異なり入出力の接続は残るので便利)
  • Shift+A から (Utility>Math) Math を追加し、ドロップダウンで Sine を選択
  • SeparateXYZ の X 出力と CombineXYZ の Y 入力の接続の間に挿入する

    無事にサイン波が表示……思っていたのと違う。そういえば三角関数の入力は0~1ではなく-180°~180°だった
  • Shift+A から (Utility>Math) Math を追加し、ドロップダウンで Multiply を選択する
  • SeparateXYZ の X 出力と Math Sine の Value 入力の間に接続する
  • Math Multiply の Value 入力欄に180を入力する

    ぐわー!
  • Resample Curve のカウントに 517 を入力する

    ぐわー!
    どうやら Sine の入力は -180°~180° ではなくラジアン(弧度法)で -π~π にする必要があるらしい
  • Resample Curve のカウントに 101 を入力する
  • Math Multiply の Value 入力欄にpi と入力すると 3.142 に変換される

    無事にサイン波らしきものが表示された

三角関数って何の役に立ってるの?

音楽やってる人向けにはこういうのはどうでしょう?

Frequency Modulation!
https://x.com/TheCoolMuseum/status/1853743438300348514
ふりけんしーもじゅれーしょん!

どうやら (Input>Scene) Scene Time>Frame でアニメーションの現在時間が取れるらしいです

thecoolmuseumthecoolmuseum

[随時更新]ノード操作メモ

設定

Preferences>Add-ons>Node Wrangler を有効化

ノード操作

Shift-A : ノード追加
ノードを選択中 X : ノード削除
ノードを選択中 Ctrl+X : ノード削除(接続維持)
ノードを選択中 M : ノードをミュートトグル(一時無効化/有効化)
ノード ドラッグ : ノードを移動
ノード Alt+ドラッグ : ノードを接続から独立して移動
ノード Ctrl+Shift+クリック: Viewer ノードを追加して Geometry 出力に接続する

Ctrl+右ドラッグ : リンクを切る(削除)
Shift+右ドラッグ : リンクにリルートノードを追加
Ctrl+Alt+右ドラッグ : リンクをミュート/有効化

Shift-Tab : グリッドスナップトグル

thecoolmuseumthecoolmuseum

メッシュジオメトリの要素

メッシュジオメトリの要素を見る

  • 新規シーンを作成して、 Geometry Nodes Layout に切り替える
  • 3Dビューでデフォルトキューブを選択する
  • ジオメトリノードビューで +New をクリックして新しいジオメトリノードを作成する(これをジオメトリノードグループと呼ぶ)
  • Group Input の Geometry 出力ソケットにマウスポインタを合わせる

    出力ソケットにマウスポインタを合わせると、そのソケットが出力している(最後に出力した)値が表示される。
    ここではジオメトリがメッシュであること、頂点数8個、辺数12本、面数6面であることが表示されている。
  • 左上のスプレッドシートビューで Domain>Mesh>Vertex を選択する

    各頂点の情報が表示されている。頂点にはそれぞれ番号がつけられており、ここでは0~7の8個あることがわかる(これを ID と呼ぶ)。次にそれぞれの頂点の位置座標( Postion )が3次元ベクトルで表示されている。
  • 同様に Domain>Mesh>Edge を選択する

    各辺の情報が表示されている。辺にもIDがあり、0~11の12個あることがわかる。辺には座標が表示されていない。
  • 同様に Domain>Mesh>Face を選択する

    各面の情報が表示されている。面のIDは0~5の6個あることがわかる。 sharp_face というチェックボックスが表示されており、すべてチェック状態になっており、これはすべての面のシェーディングにスムースをかけないことを示している。
  • 同様に Domain>Mesh>Face Corner を選択する

    これは各面の角(頂点)の情報を表示している。面角のIDは0~23の24個存在する。 UVMap という2次元ベクトルの値が表示されており、これはテクスチャを割り当てる際のテクスチャ上の位置(UV座標)を表している。
  • Group Input ノードと Group Output ノードの Geometry リンクの間に、Transform Geometry ノードを挿入する
  • Rotation パラメータに (45°, 45°, 0°) を設定する
  • スプレッドシートビューで Domain>Mesh>Vertex を選択する

    3Dビューで立方体の向きが回転し、スプレッドシートの各頂点の座標も変化していることがわかる。

グラフの途中の状態を確認する

動作の確認や問題の解決のために、ノードの途中で正しく動作しているか確認したいことがある。

  • Group Input ノードを Ctrl+Shift+クリックする( Viewer ノードが追加されて接続される)
  • スプレッドシートビューを左右に分割して増やす
  • スプレッドシートビュー左上部のドロップダウンをそれぞれ Evaluated と Viewer Node に変更する

    Viewer ノードが表示され、3Dビューの立方体の回転がキャンセルされた。

    また2つのスプレッドシートビューでは異なった座標値が表示されている。
    Viewer ノードにグラフ途中のノードからジオメトリを接続すると、そのノードが出力している状態を3Dビューとスプレッドシートビューで表示確認することができる。
    Viewer ノードを削除すると、もとの表示に戻る。
thecoolmuseumthecoolmuseum

ジオメトリのアトリビュート

Viewer ノードでジオメトリの持っている情報を表示する

Viewer ノードは接続されたジオメトリの座標値以外にも様々な情報を表示できる

  • Transform Geometry ノードを Ctrl+Shift+クリック して Viewer ノードで注目する
  • shift+A から (Geometry>Read) ID ノードを追加する
  • IDノードの ID 出力から Viewer ノードの何も接続されていないグレーのソケットに接続する

    立方体の色が白く表示された

    さらにスプレッドシートに Viewer という列が増え、0.000, 1.000, 2.000 ... 6.000 と ID を小数表示した値が表示されている。 Viewer ノードの空き入力ソケットに接続すると、入力された値をスプレッドシートビューで確認できるようになる。

    また立方体が真っ白に表示されるようになったが、3Dビューを回転してみると、立方体の頂点が一つだけ黒くなっていることが確認できる。これは Viewer ノードの入力ソケットから取得した値をカラーとして視覚的に確認することができる機能だ。
  • ID ノードを削除する
  • Shift+A から (Geometry Read) Position ノードを追加する
  • Position ノードの Position 出力から Viewer ノードの入力ソケットに接続する

    立方体が白黒に塗り分けられて表示された
  • ジオメトリノードビューで N キーを押す
  • 表示されたサイドバーの右側のタブから Node タブを選択する
  • Properties の Float と表示されているドロップダウンから Vector を選択し変更する

    立方体の各頂点がカラフルなカラーで表示された。これは Position の3次元ベクトルの XYZ の値をカラーの RGB に割り当てることで、座標を視覚的に確認することができる機能だ。

    またスプレッドシートでは Viewer の列が3列で表示されるようになり、 Position と同じ値が表示されるようになっている。
    このようにViewer ノードを使用することで、ジオメトリの持っている情報を表示することができる。