Closed7

【Houdini】Mardini 2025解説記事

nekoconekoco

Mardini 2025を完走した(ヤッター!)ので、その中でも気に入っているものを解説していこうと思います。

解説記事は、日記とノード情報からAIによって作成されました。
AIを用いたHoudini解説記事の作り方は以下で解説しています。ぜひ読んでみてください。
https://zenn.dev/nekoco/articles/ae834a0cb5ab47

この記事は実験的試みなのですが、一応対象読者のレベルとしては、完全初心者の方やHoudiniに興味がある方に向けています!
あとは、AIに投げたらこんな文章になるんだな~と感じたり、今時のAI(Gemini 2.5 Pro)の理解力に驚いたりしてください!(?)
なお解説記事の画像に関しては筆者が随時撮影しました。(これも自動だったら嬉しいのに…)

AIが記述した部分は、AI解説記事と囲われた範囲です
Zenn君、detailsで囲ったら空白改行が動作しないの直して…(記事が読みづらいかもしれません)

nekoconekoco

Day04 : FOLIAGE (SOP)


日記

植物をプロシージャルモデリングしました。
この頃はまだHoudiniを始めて4日目くらいだったので、Curveの使い方も分からず悪戦苦闘していました…
本当はチュートリアルなどを作って楽をしたかったのですが、この頃はモチベも高く、せっかくなら百合の花を作ってみたいと思い作成することにしました。

百合は花びらが独特の形をしていて素敵ですよね~
1枚作成すればあとはプロシージャルに配置できるので、そこが楽しかったですね
Foreachの使い方を学びました

百合には雄蕊と雌蕊がついているので、そこも再現しました
カーブで円柱を作り、その端っこに細長い球体をくっつけました
線の端っこにCopy to pointしたのですが、線の端っこという定義が難しくて、この時はresampleで始点と終点を取得していましたね。今考えたらWrangleとかが使えそうです。

葉っぱについては、茎の各点から生やせばいいのですが、いろんな方向にばらけていた方が良いですよね。そこでwrangleを使用して適当に回転させました、プログラムは以下の通りです。
TODO:ここにプログラムを記載

これら全てを組み合わせることで、花が完成しました。バラバラに作っていたパーツがくっつくとモデリングの楽しさを実感します!

AI解説記事

解説記事

STEP 1: 美しい花びらを作る - CurveとForeachの連携

百合の特徴である優雅な花びらから作ります。

  1. Curveで輪郭と中心線を描く: Curveノードを使い、花びらの片側の輪郭線 (curve3) と、反り返りを表現する中心線 (curve2) を描きます。
    • Tips: Curveノード選択中にEnterキーで編集ツールに切り替えられます。後からEditノードでも編集できますが、プロシージャル性を保つならCurveノードの操作がおすすめです。

  1. Mirrorで対称化: Mirrorノード (mirror1) で輪郭線を反転コピーし、対称な形にします。
  2. Mergeで統合: 輪郭線と中心線をMergeノード (merge1) で一つにまとめます。

  1. Polypatchで面張り: Polypatchノード (polypatch1) で線から滑らかな面を作成し、花びらの形状を完成させます。

  2. Foreachで増殖: Foreachブロック (foreach_begin1foreach_end1) を使い、花びらを複製・回転させます。

    • Transformノード (transform1) をループ内で使用し、detail("../foreach_count1", "iteration", 0) のような式で各イテレーションごとに回転角度を変えることで、花びらを円状に配置します。(例: 3枚なら120度ずつ)
  3. TransformとMergeで内外の花びらを表現: Foreachで作った3枚の花びらを、そのままのものと、Transformノード (transform2) で少し回転・移動させたものをMergeノード (merge2) で結合し、計6枚の花びら構成にします。

    • 「1枚作成すればあとはプロシージャルに配置できるので、そこが楽しかった」 - まさにプロシージャルモデリングの醍醐味ですね!

STEP 2: 雄蕊(おしべ)と雌蕊(めしべ)を作る - SweepとCopyToPoints

花の内部構造を作ります。

  1. Curveで芯を描く: 雄蕊用 (curve1, curve4, curve5) と雌蕊用 (curve6) の芯となる線をCurveノードで描きます。雄蕊の線はMergeノード (merge5) でまとめます。

  2. Sweepで太さ付け: Sweepノードを使い、芯の線に断面形状(Circleノードで作成: circle1, circle2)を沿わせて立体化します。

    • Resampleノード (resample3, resample7) で事前にカーブ上の点を増やしておくと、Sweepが綺麗にかかります。
    • 雄蕊: resample3 + circle1sweep2
    • 雌蕊: resample7 + circle2sweep4
  3. CopyToPointsで先端パーツを配置: 雄蕊の葯(やく)と雌蕊の柱頭(ちゅうとう)をSphereノード (sphere1, sphere2) で作り、CopyToPointsノードで各芯の先端にコピーします。

    • Tips: 線の先端点を取得するために、Resampleノード (resample2, 4, 6, 8) のSegments1にして始点と終点のみの線分にし、終点を選択する方法を取りました。Wrangleを使う方がスマートかもしれません。
    • 雄蕊: sphere1copytopoints1, 2, 3
    • 雌蕊: sphere2copytopoints4
  4. Mergeで合体: 雄蕊・雌蕊の棒 (sweep2, sweep4) と先端パーツ (copytopoints14) をMergeノード (merge3) でまとめます。

    • 「CopyToPointとかMergeはよく使い過ぎて殿堂入り」 - 非常に使用頻度の高いノードです!

STEP 3: 茎と葉を作る - Wrangleで個性を出す

花全体を支える部分です。

  1. 茎の作成: Curveノード (curve8) で茎の形を描き、Circleノード (circle3) を断面としてSweepノード (sweep5) で立体化します。

  2. 葉の作成: Curveノード (curve7) で葉の片側を描き、Mirrorノード (mirror2) で対称化、Polypatchノード (polypatch2) で面を張ります。

  3. AttribWrangleで葉にランダムな回転を付与: 茎の各点から生える葉の向きが単調にならないよう、AttribWrangleノード (attribwrangle1) を使います。

    • 茎のカーブ (curve8) を入力し、以下のVEXコードで各点にランダムなY軸回転情報 (@orient) を追加します。
      float angle = rand(@ptnum) * 360;
      vector axis = {0, 1, 0};
      vector4 q = quaternion(radians(angle), axis);
      @orient = q;
      
    • 「葉っぱは、いろんな方向にばらけていた方が良い。そこでwrangleを使用して適当に回転させた」 - Wrangleを使うと、こうしたランダム性を簡単に追加できます。
  4. CopyToPointsで葉を配置: 作成した葉 (polypatch2) を、回転情報が付与された茎の点 (attribwrangle1) にCopyToPointsノード (copytopoints5) でコピーします。@orientアトリビュートにより、葉がランダムな方向を向きます。

  5. Mergeで合体: 茎 (sweep5) と葉 (copytopoints5) をMergeノード (merge6) でまとめます。

STEP 4: 全てを一つに!完成へ

最後に、作成したパーツを統合します。

  1. 花びら (merge2)
  2. 雄蕊・雌蕊 (merge3)
  3. 茎と葉 (merge6)

これらをMergeノード (merge4) で一つにまとめ、百合の花が完成!

  • 「バラバラに作っていたパーツがくっつくとモデリングの楽しさを実感します!」 - この達成感がたまりませんね!

最後にTransformノード (transform3) で全体の位置を調整し、Gridノード (grid1) で作成した地面とMergeノード (merge7) で結合してシーンの完成です。

まとめ

Houdini初心者の奮闘記を元に、百合のプロシージャルモデリングの手順を見てきました。Curve、Mirror、Polypatch、Sweep、Resample、Sphere、Circle、CopyToPoints、Foreach、Transform、Wrangle、Mergeといった基本的なノードを組み合わせることで、複雑な形状も手順立てて作れることが分かったかと思います。

日記からは、Curveの扱いや点の選択方法など、誰もが最初は戸惑うポイントに悩みつつも、ForeachやWrangleのようなHoudiniならではの機能の面白さ、そしてパーツが組み上がっていくプロシージャルモデリングの楽しさを見つけていく様子が伝わってきました。

この記事が、Houdiniを始めたばかりの方や、これから挑戦してみたいと思っている方にとって、プロシージャルな考え方やHoudiniの面白さを知るきっかけになれば嬉しいです。ぜひ、あなたも好きなものをHoudiniで作ってみてください!

nekoconekoco

Day14 GRAFFITI (COP)


日記

COPですね~、結局最後までCOPをどうやって組み合わせればいいのかよくわかんなかった…
フラクタルノイズとかパターンだけでどうやって形作っていくんだ…?って今でも分かんない

でも今日はなんだかんだよく出来た気がする
チュートリアルとかは無く、自分の知識で作り上げました!
なのですごい作品というより、愛着のある作品ですね

Graffitiということで、高架下とかシャッターによくあるスプレーアートを思いつきました
文字にしようか迷いましたが、ラバートイがかわいかったので、そうしました

SOPをテクスチャにする方法を探していたら、ラスタライズというものが存在するらしいです
リアル調の色合いにしたかったのですが、テストジオメトリからは色を取得できませんでしたね…(Cd Attributeが存在しないので?)
単調な青と、影用に位置をずらした黒を重ねてスプレーアートの完成!
ここで初めてRGBAのAlphaの使い方を知りました

続いては壁ですね
落書きされた壁と言えばレンガ!、なのでレンガを再現します
タイルパターンを調整するだけでレンガの模様になりますね、便利
あとはノイズで古びた感じを出したり、色を付けたり…

最後に2つの柄を合わせて完成!
壁の凸凹は壁を情報をハイトマップに入れました

AI解説記事

解説記事

Houdini COPで作る!スプレーペイント風アート制作記

こんにちは!Houdiniの世界へようこそ。
この記事では、Houdiniの強力な画像合成機能「COP (Compositing Operators)」を使って、スプレーペイント風のアート作品を制作した過程を、当時の日記とノード情報を元にご紹介します。

Houdiniを始めたばかりの方や、COPって何だろう?と興味を持っている方にも、楽しみながら読んでいただけるように解説していきます。今回はチュートリアルではなく、試行錯誤しながら自分の力で作り上げた作品なので、技術的に高度というよりは、手作り感と愛着が詰まったものになっています。

さあ、一緒にCOPの世界を覗いてみましょう!

STEP 1: ラバートイをスプレーアート風に

まずは主役となるラバートイの部分から作っていきます。
目標は、3Dモデル(SOPジオメトリ)をスプレーで描いたような2Dテクスチャにすることです。

  1. SOPジオメトリの読み込み (sopimport1)

    • まず、sopimportノードを使って、SOPで作られたラバートイのジオメトリデータをCOPネットワークに持ち込みます。今回はデフォルトのテストジオメトリを使用しました。
  2. ジオメトリを画像に変換 (rasterizegeo1)

    • 次に、rasterizegeoノードを使います。これが「ラスタライズ」と呼ばれる処理で、3Dジオメトリをカメラから見た2D画像に変換してくれます。
    • 日記にもあるように、最初はラバートイの色(Cdアトリビュート)も一緒に画像にしたかったのですが、テストジオメトリには元々色情報が設定されていなかったため、取得できませんでした。もしジオメトリに色が付いていれば、rasterizegeoAttributesタブでCdを指定することで、色付きの画像を生成できます。
    • 今回は形状だけを利用し、intrinsic:alphaを出力するように設定しました。これにより、ラバートイのシルエット部分が白、それ以外が黒(またはその逆)のような、アルファマスクとして使える画像が生成されます。
  3. 色付け (monotorgb1)

    • ラスタライズした画像は基本的に白黒なので、monotorgbノードで色を付けます。
    • パラメータのRampを使って、白の部分が鮮やかな青 (ramp2cr: 0.0, ramp2cg: 0.5, ramp2cb: 1.0) になるように設定しました。これで青いラバートイのベースができました。
  4. 影の作成

    • スプレーアートっぽさを出すために、少しずらした影を加えます。
    • まず、constant1ノードで単色の黒い画像を生成します。
    • 次に、transform2d1ノードを使って、この黒い画像を少しだけ右下(tx: -0.03, ty: -0.03)にずらし、ほんの少しだけ拡大(sx: 1.08, sy: 1.08)します。これが影になります。
  5. アルファチャンネルの活用と合成 (rgbtorgba1, rgbtorgba2, over1)

    • ここで重要なのがアルファチャンネルです。アルファは画像の「透明度」を扱う情報で、これを使うことで背景を透明にして画像を重ね合わせることができます。
    • rgbtorgbaノードを2つ使います。
      • rgbtorgba1: 青いラバートイ (monotorgb1) に、ラスタライズした形状 (rasterizegeo1intrinsic:alpha) をアルファとして設定します。これで、ラバートイの形の部分だけが不透明な青い画像になります。
      • rgbtorgba2: 黒い影 (constant1transform2d1でずらしたもの) にも、同様にラスタライズした形状 (rasterizegeo1intrinsic:alphatransform2d1でずらしたもの) をアルファとして設定します。これで影もラバートイの形になります。
    • 最後にblendノード (over1) を使います。modeOver (1) に設定し、alphaを有効 (1) にすることで、アルファチャンネルを考慮して画像を重ね合わせます。入力の順番が重要で、下のレイヤー(影:rgbtorgba2)の上に上のレイヤー(青いラバートイ:rgbtorgba1)を重ねます。
    • 日記の「ここで初めてRGBAのAlphaの使い方を知りました」とあるように、このアルファを使った合成が、狙った表現を実現する鍵となりました。

これで、青いスプレーで描かれたラバートイとその影、という表現ができました!

STEP 2: 背景のレンガ壁を作る

スプレーアートといえば、やっぱりレンガの壁が似合いますよね!

  1. レンガ模様の生成 (tilepattern1)

    • tilepatternノードは非常に便利で、様々なタイルパターンを簡単に生成できます。
    • patterntypeStretcher Bond (5) などに設定し、tilewidthtileheightrows, colsを調整するだけで、リアルなレンガの並び方が作れます。
    • さらにdoinset (1) を有効にし、insetパラメータ(今回は0.0222)を調整することで、レンガの間の目地(溝)も表現できます。
  2. 古びた質感の追加 (fractalnoise1, multiply1)

    • 新品のレンガではなく、少し古びた、汚れた感じを出したいので、ノイズを加えます。
    • fractalnoiseノードで、いい感じのムラがあるノイズパターンを生成します。amp (ノイズの強さ)、elementsize (ノイズの細かさ)、rough (粗さ) などを調整して、壁の汚れや質感に見えるようなノイズを探します。
    • blendノード (multiply1) を使い、modeMultiply (5) に設定します。これで、レンガパターン (tilepattern1) とノイズ (fractalnoise1) が掛け合わされ、ノイズの暗い部分がレンガの色を濃くし、まるで汚れが付着したような表現になります。
  3. 色付けとボカシ (blur1, monotorgb2)

    • multiply1で合成したレンガ+汚れの画像に、レンガらしい色を付けます。
    • まずblur1ノードで、画像を少しだけぼかします (size_pixel: 3.0)。これにより、ノイズのエッジが和らぎ、より自然な汚れに見えます。
    • そしてmonotorgb2ノードを使い、Rampパラメータで茶色系のグラデーション(暗い茶色から明るい茶色へ)を設定し、レンガ壁の色を表現しました。

STEP 3: 最後の仕上げ - 合成とプレビュー

さあ、いよいよラバートイとレンガ壁を合体させます!

  1. 最終合成 (over2)

    • 再びblendノード (over2) を使い、modeOver (1) に設定します。背景となるレンガ壁 (monotorgb2) の上に、先ほど作成したラバートイのスプレーアート (over1) を重ね合わせます。アルファチャンネルが効いているので、ラバートイの部分だけが壁の上に描かれたように見えます。
  2. 出力とプレビュー (rgbatorgb1, blur2, previewmaterial1)

    • rgbatorgb1: 最終的な画像は、多くの場合アルファチャンネルが不要になるため、このノードでRGB画像に変換します。unpremult (1) を有効にして、アルファブレンドによる色の影響を補正します。
    • blur2: これは壁の凹凸(ハイトマップ)用に使います。レンガ+汚れの画像 (multiply1) を弱めにぼかした (size: 0.00286) ものを用意します。
    • previewmaterial1: このノードは、作成したテクスチャを3Dオブジェクトに貼り付けてプレビューするためのものです。
      • Base Color (基本色) の入力に、合成した最終画像 (rgbatorgb1) を接続します。
      • Height (高さ) の入力に、壁の凹凸情報として用意したblur2を接続します。これにより、レンガの目地や汚れが実際に少し凹凸を持っているように見せることができます。(日記の「壁の凸凹は壁を情報をハイトマップに入れました」の部分です)

これで、レンガ壁にラバートイのスプレーアートが描かれた、目的のペイントアートが完成しました!

まとめ:試行錯誤が楽しいCOPの世界

最初は戸惑うことも多かったCOPですが、一つ一つのノードの役割を理解し、繋ぎ方やパラメータを試行錯誤していくうちに、だんだんとイメージしたものが作れるようになっていく過程は非常に楽しいものでした。

  • SOPジオメトリをラスタライズしてテクスチャに変換
  • アルファチャンネルを使った画像の切り抜きと合成
  • タイルパターンとノイズを組み合わせて質感を表現
  • 作成した画像をカラーだけでなくハイトマップとしても利用

など、この作品作りを通して多くのことを学ぶことができました。
HoudiniのCOPは、プロシージャル(手順的)にテクスチャや画像を生成・加工できる非常に強力なツールです。皆さんもぜひ、色々なノードを繋いで、自分だけのオリジナルアートを作成してみてはいかがでしょうか?

所感

1個目の記事とテンションというか解説の粒度が異なりますね。
何の設定もなくただ解説を書いてとお願いしているので、そのせいでしょう。
なので一定の品質を求めるなら、口調や特徴、rulesなどを設定する必要があるのでしょうね。

nekoconekoco

Day18 ROLL(KineFX)


日記

KineFXですね!KineFXも苦手でした…
あまりプロシージャルさを感じないのが、やってて微妙な気持ちでしたね
あと自分で勉強不足ですが、関節を1つずつ動かしていくのがめんどくさくて…

ボーン挿入だとかウェイト塗りは1回目で諦めました、これはやりたくない作業です!
なのでほとんどテストジオメトリのElectraを使用しました

お題はRoll、ロールと言えば転がる感じですね~
坂道を転がっている姿勢を考えていると、ローリンガールのことを思い出しました!
もうコンセプトはこれしかないですね!
https://www.youtube.com/watch?v=vnw8zURAxkU

ボーンの操作方法はRig poseで色々動かした後、Bone deformに繋げば反映されますね
なんやかんや、良い感じに坂道を転がるポーズを作成しました
(ここが本題なのに解説することがない…)

あとはコンセプトをみんなにわかってもらえるように、ローリンガールのMVの記号を再現しました
あの良い感じのぐちゃぐちゃ感、なんかプロシージャルで再現できそうな気がしたのでやりました!

Day4でやったポイントに回転情報を設定するやつ、Attribute randmizeで出来ましたね
pscaleで大きさ、orientで回転の情報を付与することが出来ます
そのポイントにcopy to pointするだけで、形が変わります、便利!

そんな感じでローリンガールの記号、完成!

最後にマージしてレンダリングしました

AI解説記事

解説記事

KineFXでキャラクターを転がしてみよう!~ローリンガール風~

Houdiniにはたくさんの機能がありますが、今回はキャラクターアニメーションに特化した「KineFX」という機能セットを使ってみましょう!

正直に言うと、筆者は最初KineFXに少し苦手意識がありました。Houdini得意の「プロシージャル(手続き的)な作り方」があまり感じられず、一つ一つの関節を地道に動かしていく作業が少し大変に感じたからです。ボーン(骨格)を入れたり、ウェイト(ボーンの影響範囲)を塗ったりする作業は、慣れないうちは特に難しく感じるかもしれません。

そこで今回は、そういった難しい準備作業をスキップ! Houdiniが用意してくれているテスト用モデル「Electra」を使って、KineFXの基本的な流れと、他のHoudini機能と組み合わせた表現を体験してみましょう。

今回のお題は「Roll(転がる)」。転がるといえば…あの曲が思い浮かびませんか? そう、wowakaさんの「ローリンガール」です! あの印象的なミュージックビデオ(MV)の雰囲気を、Houdiniで再現してみることにしました。

1. キャラクターの準備:Electraにお願い!

まずは、動かすキャラクターを用意します。今回は複雑な設定はせず、Houdiniに標準で用意されているテストジオメトリ「Electra」を使います。

ネットワークビューでTabキーを押し、testgeometry_electraと入力してノードを作成します。このノードは、すでにボーンやウェイト設定が完了している人型のモデルを出力してくれる便利なノードです。今回はこのElectraに転がるポーズをとってもらいましょう。

2. ポーズをつけよう:Rig Poseノード

キャラクターにポーズをつけるには、kinefx::rigpose(以下 rigpose)ノードを使います。

testgeometry_electra1 の3番目の出力(Skeleton)を rigpose1 の入力に接続します。

rigpose ノードを選択した状態で、ビューポート上でキャラクターの関節(ボーン)を選択し、移動(Tキー)、回転(Rキー)、スケール(Eキー)ツールを使って直接ポーズを編集できます。

パラメータビューを見てみましょう。
たくさんのパラメータがありますが、中心となるのは Transformations タブです。

  • Transformations: ここには、現在操作しているボーンのリストが表示されます。初期状態では空ですが、ビューポートでボーンを選択して動かすと自動的にリストに追加されます。
  • groupX: (X は数字) どのボーンを操作しているかを示します。例えば group0@name=thigh_l は、thigh_l (左太もも) という名前のボーンを指しています。
  • tX, rX, sX: それぞれのボーンの Translate (移動), Rotate (回転), Scale (スケール) の値です。ビューポートで操作した結果がここに反映され、数値で微調整することも可能です。

日記にも「関節を1つずつ動かしていくのがめんどくさくて…」とありましたが、まさにこのパラメータを一つ一つ調整していく作業になります。今回は、Electraが坂道を転がっているような、ちょっと苦しそうなポーズを目指して、各関節の回転 (rX) を中心に調整しました。例えば、以下のような値を設定しています。

  • pelvis (骨盤): r1x = -175.65 (X軸周りに大きく回転)
  • thigh_l (左太もも): r0y = 101.01 (Y軸周りに回転)
  • thigh_r (右太もも): r2y = 78.9 (Y軸周りに回転)
  • spine_01 (背骨): r5x = -38.8 (X軸周りに回転)
  • neck_01 (首): r10x = -39.5 (X軸周りに回転)

このように、各ボーンのパラメータを調整して、目標の「転がるポーズ」を作成しました。

3. ポーズをモデルに反映:Bone Deformノード

rigpose ノードで作ったのは、あくまで「ボーンのポーズ情報」です。これを実際のキャラクターモデル(ポリゴンメッシュ)に適用して変形させるのが bonedeform ノードの役割です。

bonedeform1 ノードには3つの入力が必要です。

  1. Rest Geometry: 変形させたい元のモデル形状。testgeometry_electra1 の1番目の出力(Geometry)を接続します。
  2. Rest Skeleton: ボーンの初期状態(Tポーズなど)。testgeometry_electra1 の3番目の出力(Skeleton)を接続します。
  3. Animated Pose: rigpose1 で作成したポーズ情報。rigpose1 の出力を接続します。

これで、rigpose1 で変更したボーンの動きに合わせて、Electraのモデルがぐにゃりと変形するようになります。

4. 背景作成:ローリンガールの「記号」をプロシージャルに

キャラクターのポーズができたら、次は背景です。「ローリンガール」のMVに出てくる、あの特徴的なモノクロの図形が散りばめられた「ぐちゃぐちゃ感」を、Houdiniのプロシージャルな機能を使って再現してみましょう。

4.1. 基本図形の作成

まず、背景に散りばめる基本となる図形を作ります。

  1. tube1: tube ノードで薄い円柱(チューブ)を作成します (height: 0.1, rad1: 0.5)。
  2. transform1: 作成したチューブを少し横にずらして(tx: 0.2)、少し小さく(sx: 0.8, sz: 0.8)したコピーを作成します。
  3. boolean1: boolean ノードを使って、元のチューブから、小さくしたチューブを引き算します (booleanop: 2 = Subtract)。これで、アルファベットの「C」のような、あるいは円の一部が欠けたような図形ができます。これが背景に散りばめる基本パーツです。

4.2. 図形を配置するポイントの生成とランダム化

次に、作成した図形をコピーするための「点(ポイント)」を、いい感じにばらまきます。

  1. grid2: まず、ポイントをばらまく元となる平面を grid ノードで作成します。
  2. split1, polyextrude1, split2, transform3, transform2: ここでは少し複雑なことをしています。grid の一部の面を選択し (split1)、押し出して (polyextrude1)、その一部の面をさらに選択し (split2)、変形 (transform3, transform2) させて、ポイントを生成したい領域(細長い帯状の領域)を作成しています。
  3. scatter1: scatter ノードを使って、作成した領域内にランダムな点 (ポイント) を生成します (forcetotal: 1, npts: 23 で合計23個)。
  4. attribrandomize1: 生成したポイントに、ランダムな大きさの情報 (pscale アトリビュート) を付与します。minx: 0.5, maxx: 1.5 なので、0.5倍から1.5倍の大きさになります。
  5. attribrandomize2: 同様に、ポイントにランダムな回転の情報 (orient アトリビュート) を付与します。orient はクォータニオンという形式で回転を表し、4つの数値で構成されます。minx/minz-1maxx/maxz1 に設定することで、主にY軸周りのランダムな回転を与えています。

これで、ランダムな位置、大きさ、回転を持つポイント群が生成されました。

4.3. ポイントに図形をコピー&配置

いよいよ、先ほど作った基本図形を、準備したランダムなポイント群にコピーします。

  1. copytopoints1: copytopoints ノードの1番目の入力に基本図形 (boolean1 から)、2番目の入力にランダム化されたポイント群 (attribrandomize2 から) を接続します。このノードは、2番目の入力にある各ポイントの位置に、1番目の入力ジオメトリをコピーします。さらに、ポイントが持つ pscale (大きさ) と orient (回転) アトリビュートを自動的に読み取り、コピーする図形のサイズと向きに反映してくれます。まさにプロシージャル!
  2. color1: コピーされた図形群全体に色をつけます。今回はMVの雰囲気に合わせて暗めのグレー (colorr/g/b: 0.221) に設定しました。
  3. transform4: 出来上がった図形の塊全体を、シーン内の適切な位置に移動・回転させて配置します (tx: 5.3, ty: 1.7, tz: -2.5, rz: 90, ry: -10.1)。

4.4. 地面の作成

最後に、キャラクターが転がるための地面と、背景の壁を作ります。

  1. grid1: grid ノードで平面を作成し、rx: 25.2 で傾けて坂道のような地面を作ります。
  2. grid3: もう一つ grid ノードを作成し、rz: 90 で回転させて壁のような平面を作ります。位置も tx: 5.3 で調整します。

5. 最終合成:Mergeですべてを合わせる

これで、ポーズを付けたキャラクターと、プロシージャルに生成した背景パーツが揃いました。最後に merge ノードを使って、これらすべてを一つにまとめます。

merge1 ノードに、bonedeform1 (キャラクター)、grid1 (坂道)、transform4 (背景図形)、grid3 (壁) をすべて接続します。

これで、KineFXでポーズを付けたキャラクターと、プロシージャルに生成したローリンガール風の背景が組み合わされたシーンが完成しました!

まとめ

今回はKineFXを使ってキャラクターのポージングを行い、さらにHoudiniの得意なプロシージャルモデリング技術(ScatterやAttribute Randomize、Copy to Pointsなど)を組み合わせて、コンセプトに基づいた背景を作成する流れを体験しました。

KineFXの rigposebonedeform を使うことで、キャラクターにポーズをとらせる基本的なワークフローがわかったかと思います。最初は難しく感じるかもしれませんが、テストジオメトリを使えばボーンやウェイト設定の手間なく、すぐにポージングを試すことができます。

そして、キャラクターだけでなく背景などもHoudini内でプロシージャルに生成することで、より統一感のあるシーンを効率的に作成できるのがHoudiniの魅力ですね!ぜひ皆さんも、KineFXと他の機能を組み合わせて、色々な表現に挑戦してみてください。

所感

また違った解説スタイルになりましたね
今度はMarmaid記法でノードのつながりを再現するという、面白い発想ですね
ノードのつながりについてはスクショの必要が無くなりそうですね!
(プレビュー画面のスクショはまだ必要かな~、そこを表示できるがHoudiniの強い点だと思いますし)

nekoconekoco

Day27 SNOW(DOP)


日記

今週はDOPですね!DOPは大好きです!
なおSOP階層にラップされたやつですが
DOPネットワークはなぜかうまくいかなくて苦手意識が…(すべてに苦手意識がある)

まあ、とりあえず雪のシミュレーションをしました
雪のシミュレーションってなんだ?って思いましたが、流体の粘度を上げたらいい感じになるみたいです
最近パーティクルのシミュレーションをしたらparticlefluidsurfaceをかければいい感じのメッシュになることを学びました
ただのシミュレーションだと面白みがないので、コライダーの勉強としてラバートイをシミュレーションのコライダーにしてみました

そのあと、雪の粒子が舞うシミュレーションもしてみました
POPは自動でDOP Netを構築してくれるみたいですね~

マテリアルもprincipledshaderを最近知って、いいよね~って思ってます。

当時の心境

今日は雪
 雪の結晶が生成されていく様をシミュレーションしたいな~って思ってたけど、よくよく考えたらそれDOPじゃなくてSolverなんだよな
 じゃあ普通に雪のシミュレーションでいいか

AIに聞いた

今日はChatGPTじゃなくてGemini 2.5に聞いてみた

HoudiniのDOP (Dynamics Operator) を使用して雪のシミュレーションを行う方法ですね。現在Houdiniで粒状の物質(砂、雪、土など)をシミュレートする場合、Vellum Solver の Grains を使用するのが最も一般的で強力な方法です。
以下にVellum Grainsを用いた雪シミュレーションの基本的なワークフローと考慮事項を説明します。

うーん、やっぱり嘘というか合ってない情報がいくつかあった
 HoudiniとAIの相性はあんまりよくないね…

マテリアルの作り方も聞いた

ここでは、Houdiniの標準レンダラーであるMantraや、新しいKarma(Solarisコンテキスト)で広く使われている Principled Shader をベースにした設定方法を解説します。基本的な考え方は他のレンダラー(Redshift, Arnoldなど)でも応用できます。

これもまた嘘とホントが混ざってた
 あんまり納得のいく表現ではなかったけど、まあ…

雪が降ってる感じにしたい

Houdiniで舞っている雪を表現したい場合、POP (Particle Operators) を使用するのが最も一般的で柔軟な方法です。POPは大量の軽量なパーティクルを効率的に扱い、風や乱気流による複雑な動きを制御するのに適しています。

POPに関して全然違った!
 なんかネットでいろいろと調べたら何とかなった(なったか?)

舞ってる雪にはモーションブラーが良いとのことで、それも聞いてみた
 う~ん、合ってるのかよく分かんないけど、とりあえずクラッシュした!

https://www.youtube.com/watch?v=dTtr_DWGAp4
モーションブラーはこの動画で解説されてた
 これならちゃんと本当の情報だから安心!
でもやっぱりクラッシュした!!!
 DOPとの相性悪いか?
 File Cache撮ったはずなのになぁ

とりあえず妥協で提出

AI解説記事

解説記事

Chapter X: DOPとSOPで作る!雪景色シミュレーション

こんにちは!今回はHoudiniの強力な機能、DOP (Dynamics Operators)SOP (Surface Operators) を使って、雪景色のシミュレーションに挑戦してみましょう。Houdiniを始めたばかりの方や、これから触ってみたいと思っている方にも、どんなことができるのか雰囲気が伝われば嬉しいです!

今回は、

  1. 降り積もる雪のシミュレーション
  2. 宙を舞う雪の表現

の2つのパートに分けて作成していきます。日記にもあるように、最初は「どうやって作るんだろう?」と手探り状態でしたが、色々なノードを試していくうちに形になっていきました。特に今回は、パーティクル(粒)のシミュレーションが中心になります。

1. 降り積もる雪のシミュレーション:Vellum Grainsを使ってみよう!

まずは、地面や障害物に降り積もっていく雪を作ってみましょう。日記には「流体の粘度を上げたらいい感じになるかも?」とありますが、Houdiniには粒状のものをシミュレートするのに適したVellum Solverという機能があります。その中でもVellum Grainsは、砂や雪のような粒々の集まりを表現するのにピッタリです。

SOPレベルでのノードの流れ

大まかには、以下の流れで作成します。

  1. 雪の発生源を作る (box1): どこから雪(の元となる粒)を降らせるか、その形を決めます。今回はシンプルな箱型にしました。
  2. 雪の粒を生成する (vellumconstraints_grain1): box1 の中に、シミュレーションで使う粒(Grains)を詰めます。ここで粒の大きさ (grainsize) などを設定できます。
  3. 粒の動き方を設定する (vellumconstraints1): 粒同士がどのようにくっついたり、離れたりするかを設定します。(今回は主にデフォルトの設定を使っています)
  4. 地面と障害物を用意する (grid1, testgeometry_rubbertoy1, merge1): 雪が積もる地面 (grid1) と、シミュレーションのアクセントになる障害物 (testgeometry_rubbertoy1 - Houdiniに用意されているテスト用のラバートイです!) を用意し、merge1 で一つにまとめます。これらが雪の粒と衝突する「コライダー」になります。
  5. シミュレーションを実行する (vellumsolver1): Vellumの心臓部です。ここで重力 (gravityy) や粒同士の相互作用(日記にあった「粘度」のような効果は viscosityattractionweight で調整できます)を計算し、時間経過と共に粒がどう動くかをシミュレーションします。
    • vellumsolver1 には、(1)粒の情報 (vellumconstraints1 から)、(2)コライダーの情報 (merge1 から) を接続します。
  6. 粒を滑らかなメッシュにする (particlefluidsurface1): シミュレーション結果はたくさんの粒の集まりなので、これを滑らかな一つの塊(メッシュ)に変換します。日記にもあるように、particlefluidsurface ノードを使うと、いい感じの雪が積もったような表面を作ってくれます。パラメータ (particlesep, voxelsize など) を調整することで、雪のディテールや滑らかさが変わります。

これで、ラバートイの上に雪が降り積もっていくようなシミュレーションが作成できました!

2. 宙を舞う雪の表現:POPでパーティクルを飛ばそう!

次に、シーン全体に雪が舞っているような表現を追加してみましょう。日記にもあるように、こういう時はPOP (Particle Operators) を使うのが一般的です。POPは大量の軽いパーティクルを効率よく扱うことができ、風などの影響を受けて複雑に舞う動きを作るのに適しています。

Houdiniでパーティクルシミュレーションを始める簡単な方法の一つは、SOPレベルで popnet ノードを作成することです。これを使うと、パーティクルシミュレーションに必要な基本的なDOPネットワークが自動で内部に構築されます。

SOPレベルでのノードの流れ

  1. 舞う雪の発生範囲を決める (box1, transform1): どの範囲で雪を舞わせるか決めます。先ほどの積もる雪の発生源 (box1) を transform1 で少し大きくして、より広い範囲から雪が発生するようにしました。
  2. パーティクルシミュレーションを実行する (popnet): このノードの中に、パーティクルの発生源や動きを制御する設定が入っています。入力には発生範囲 (transform1) を接続します。
  3. 舞う雪の形を作る (box2, subdivide1): 舞っている一つ一つの雪の形を作ります。今回は非常に小さな箱 (box2) を作り、subdivide1 で少し角を丸めています。
  4. パーティクルの位置に雪の形をコピーする (copytopoints1): popnet で計算されたパーティクル(点)の位置情報を使って、subdivide1 で作った雪の形を大量にコピーします。これで、たくさんの雪が舞っているように見えます。

popnet内部 (DOPレベル) の簡単な解説

popnet ノードをダブルクリックすると、DOPネットワークの中に入ることができます。ここでは、パーティクルの動きを制御する様々な力が設定されています。

  • source_first_input (popsource): SOPレベルから接続された transform1 (拡大された箱) を元に、パーティクルを発生させます (Constant Birth Rate などで発生量を調整)。
  • gravity1: パーティクルに下向きの重力を加えます。
  • popwind1: 全体的な風の力を加えます。これで雪が一方向に流されるような動きが作れます。
  • popaxisforce1: 軸周りの力を加えます。渦を巻くような動きなどを追加できます。(今回は少し複雑な動きを加えるために使われているようです)
  • popdrag1: 空気抵抗を加えます。これがないとパーティクルは永遠に加速してしまいますが、抵抗があることで、ふわりと舞うような、より自然な動きになります。
  • popsolver: これらの力を元に、各フレームでのパーティクルの位置を計算します。
  • output: 計算結果を popnet ノードの外 (SOPレベル) に出力します。

これで、シーン全体に雪がちらちらと舞う表現ができました!

3. マテリアル設定:Principled Shaderで雪の質感を

最後に、作成した雪に質感を設定しましょう。日記にもあるように、Houdini標準のPrincipled Shaderは非常に高機能で、様々な質感をリアルに表現できます。

マテリアルの設定手順

  1. マテリアルネットワーク (matnet1) を作成: この中にシェーダーノードを置きます。
  2. Principled Shader (principledshader1) を作成: matnet1 の中に Principled Shader を配置します。
  3. シェーダーパラメータを設定:
    • Base Color: 雪の色なので、白に近い色 (0.95, 0.95, 0.98) に設定。
    • Roughness (粗さ): 0.5 程度に設定。少し粗くすることで、完全な鏡面反射ではなく、雪らしい少しマットな質感になります。
    • IOR (屈折率): 1.31 に設定。これは水の屈折率に近い値で、氷や雪の表現によく使われます。
    • Subsurface Scattering (SSS): これを有効 (sss = 1.0) にすると、光がオブジェクトの表面だけでなく、少し内部を透過・散乱するようになります。これにより、雪や肌のような半透明な質感が出しやすくなります。sss Color (散乱光の色) や sss Distance (散乱する距離) で見た目を調整できます。今回は白っぽい散乱にしています。
    • Bump Map (バンプマップ): ノード情報を見ると、baseBumpAndNormal_enable が有効で baseBump_bumpTexture にテクスチャ (/obj/geo1/copnet1/HEIGHT/) が指定されています。これは、おそらくノイズテクスチャなどを使って、雪の表面に細かな凹凸を追加し、よりリアルな質感を出そうとしている設定です。(今回はCOPnetの情報がないため詳細は割愛します)
  4. ジオメトリにマテリアルを割り当て (material1): SOPレベルに戻り、material1 ノードを使って、作成したジオメトリ (積もった雪や地面、ラバートイ) に matnet1 内の principledshader1 を割り当てます。shop_materialpath1 パラメータで /obj/geo1/matnet1/principledshader1 (または /obj/geo1/matnet1 でも可) を指定します。
  5. 最終的な結合 (merge2, merge3):
    • merge2 で、マテリアルを適用したいオブジェクト (積もった雪、地面、ラバートイ) をまとめます。
    • material1merge2 の後につなぎ、まとめたオブジェクト群にマテリアルを割り当てます。
    • 最後に merge3 で、マテリアル設定済みの積もった雪たちと、copytopoints1 で作成した舞っている雪を一つにまとめます。

これで、レンダリングした際に雪らしい質感で表示されるようになりました!


いかがでしたでしょうか?今回はVellum Grainsを使った積もる雪と、POPを使った舞う雪のシミュレーション、そしてPrincipled Shaderを使ったマテリアル設定の流れを、日記とノード情報を元にご紹介しました。Houdiniでは、このように様々なノードを組み合わせて複雑な表現を作り上げていきます。最初は難しく感じるかもしれませんが、一つ一つのノードの役割を理解していくと、だんだん面白くなってくるはずです。ぜひ皆さんも、色々な表現にチャレンジしてみてください!

所感

今まではジオメトリノードの中身だけを見ていましたが、今回はSOP、DOP、MATの情報を取得して読みこませました
それらの情報がごちゃまぜになったノードリストになりましたが、良い感じに理解してくれましたね
やはりGeminiは大規模コンテキストに強いのでしょうね

nekoconekoco

Day31 UNDERWATER(LOP)


日記

LOP!LOPですね!
実はSolarisはさつき先生のチュートリアルで学習したので、初日から活用していました
でもいざLOPを活用しろと言われると、どんなノードで、何が出来るのか知らないので、なにも出来ないんですよね…

今回はまず海のシミュレーショをしてもらいました
水の中と言ったら、下から覗いて水面が歪んでいて、コースティクスがかかっているイメージですね!
そのために、波を起こすために海のシミュレーションをしました
あとは最近出番が多かったparticlefluidsurfaceですね

続いて海のマテリアルとしてprincipledshaderですね
透明感があるのを作るときは、すごくお世話になっています
これでメッシュの中から覗いてみたらいい感じでした

続いて、空気の泡が浮いている演出もいいなぁ~っと思ったのでシミュレーションしました
パーティクルを放つのはPOPネットワークと学びました、Mardiniで勉強したおかげですね!
こちらは影があまりついてほしくないので、Surface Unlitにしました

あとはシミュレーションが重かったので、file cacheを取っておきました

最後に今月いっぱいお世話になったラバートイを漂わせて、モデリング完了です

LOPでは、fogが存在したので、それを使ってみました
後は水面から強い光(太陽のような)が入ってきてほしかったので、めちゃつよライトを設置しました
本当はGod Rayを入れたかったんですが、Fogを入れても見えなかったんですよね~、なんでだろ

そんなこんなでレンダリングしたらいい感じになりました
個人的に青系統の色が好きで自分のパーソナルカラーと感じているので、最後の締めが偶然そんな感じの作品になってとても満足して気に入っています

当時の心境

ついでに最終日もやっちゃうよーん
 UnderWater
 う~ん、これは全く思いつかない
  そもそもHoudini(のLOP)にどんな機能が備わっているのかを全然把握していないので、何ができるのかもわからない
 なのでまたAIちゃんに聞いてみよ~

適当に海のメッシュを作って、FogかけてGodRay飛ばしてコースティクス掛けたらいいんじゃね?って言われた
 あと編集で色収差とかブラーかけたら良いんじゃね?
 浮遊物もあったらうれしいね
  POPとか

とりあえずWave Tankで波打つ海つくるよ~
 initialとDOP以外はいらないんだよなぁ~
 Initialもocean sourceまでで、後は消す
  particle fluid surfaceはいつも通りお世話になります
  シェーダーはprincipled shader

POPの作り方は、範囲用のBoxを作成→POP Networkに接続!以上!
 シェーダーはUnlitが存在するらしい!助かるラスカル
 さすがにそのままだと目立ちすぎるので、Opacityをめccccっちゃ下げる
もうこれで海の中から覗けば、UnderWaterでしょ

コースティクスについて調べてたらめっちゃいいチュートリアル見つけた!
https://www.youtube.com/watch?v=tT36Csznoxg
 もうこれでいいんじゃないか?
 いや、バージョンが古すぎて(そうでもないけど)何言ってるかわからん
  ノードが完全に違う、まったくわからん

とりあえずFogを入れた
 https://qiita.com/jyouryuusui/items/87f0b3dcac84fb551dfe
 GodRayが入れれるらしいけどよく分かんない?
  めccccっちゃ強いDiskライトを置いといた
  なんだかんだ良い感じになったわ

最後だしお世話になったラバートイ浮かせとくか
  ありがとう、まるでぃーに…

AI解説記事

解説記事

水中シーンを作ってみよう!SOPとLOPで作る幻想的な水の世界

Houdiniを始めたばかりの皆さん、こんにちは!あるいは、Houdiniって何ができるんだろう?と興味を持ってこの記事を読んでいる方もいるかもしれませんね。

今回は、Houdiniの強力な機能を使って、幻想的な「水中シーン」を作成するプロセスを追いかけてみましょう。実際にHoudiniを触りながら制作した方の日記と、その時に使われたノード(Houdiniの機能ブロックのようなもの)の情報をもとに解説していきます。

今回の目標は、「水の中から見上げたような、水面が歪んでいて、コースティクス(光が水底で揺らめく模様)がかかっている」イメージのシーンを作ることです。

Houdiniには、モデリングやシミュレーションを行うSOP (Surface Operators) というコンテキスト(作業場所)と、ライティングやレンダリング(最終的な画像出力)の設定を行うLOP (Lighting Operators) / Solaris というコンテキストがあります。今回はこの両方を使ってシーンを構築していきます。

それでは、制作過程を見ていきましょう!

1. 波打つ海を作る (SOP: Wave Tank & Particle Fluid Surface)

まずは、水中のシーンの主役である「海」を作ります。水面がゆらゆらと波打っている様子を表現したいですよね。

Houdiniには Wave Tank という、比較的手軽に波のシミュレーションを始められる機能があります。(日記でも「とりあえずWave Tankで波打つ海つくるよ~」とありますね!)

  • 波の生成: oceansource ノード (/obj/wavetank_initial/wavetank) と oceanspectrum ノード (/obj/wavetank_initial/oceanspectrum1) を使って、波の形状や動きの元となるデータを作成します。

    • oceansource では、海の広さ (sizex: 15, sizez: 15) などを設定します。
    • oceanspectrum では、風の強さ (windspeed: 5) や波の高さ (ampscale: 5) を調整して、好みの波を作り出します。
  • メッシュ化: 作成した波のデータは、この時点ではまだパーティクル(点の集まり)やボリューム(密度情報)の状態です。これをレンダリング可能な滑らかな面のデータ(メッシュ)に変換するために particlefluidsurface ノード (/obj/wavetank_initial/particlefluidsurface1) を使います。(日記でも「最近出番が多かったparticlefluidsurfaceですね」と、よく使われている様子がうかがえます)

    • voxelsize パラメータ (0.75) で、メッシュの細かさを調整します。値が小さいほど、より詳細なメッシュになります。

これで、波打つ海のメッシュができました!

2. 海のマテリアルを設定する (SOP: Principled Shader)

メッシュができたら、次は「質感」を設定します。今回は水なので、透明感のある青いマテリアル(材質)を作りたいですね。

Houdiniで非常によく使われる principledshader を使います。(日記にも「透明感があるのを作るときは、すごくお世話になっています」とあります)

  • マテリアルネットワーク: matnet (/obj/wavetank_initial/matnet1) というノードの中に、マテリアルを作成します。
  • Principled Shaderの設定: principledshader ノード (ocean) を作成し、以下のパラメータを中心に調整して水の質感を作ります。
    • basecolor: 水の基本的な色。今回は少し青みがかった色 (0.08, 0.24, 0.58) に設定されています。
    • ior (Index of Refraction): 光の屈折率。水の屈折率に近い 1.386 を設定することで、水を通して見たものが歪んで見える効果を出します。
    • rough (Roughness): 表面の粗さ。0.3 に設定されており、波の表面で反射する光(ハイライト)が少しぼやけた感じになります。完全にツルツルだと 0 です。
    • transparency: 透明度。0.7573 と高めに設定し、水が透き通るようにします。
    • transdist (Transmission Distance): 光が水中を進む距離に応じてどれだけ色が濃くなるか。0.1 と小さめに設定することで、少し深さが増すと色が濃く見えるようになります。

作成したマテリアルは、material ノード (/obj/wavetank_initial/material1) を使って、先ほど作成した海のメッシュに割り当てます。

これで、見た目にも「水らしい」海になりました。

3. 空気の泡を作る (SOP: POP Network)

水中に浮かぶ細かい空気の泡があると、より雰囲気が出ますね。泡のような細かい粒子の動きを作るには、パーティクルシミュレーションが適しています。Houdiniでは POP (Particle Operators) Network を使います。(日記にも「パーティクルを放つのはPOPネットワークと学びました、Mardiniで勉強したおかげですね!」と学習の成果が出ているようです)

  • 発生源: まず、泡がどこから発生するかを決めます。今回は box ノード (/obj/wavetank_initial/box1) で作成した箱(サイズ 10x10x10)を発生エリアとします。
  • シミュレーション: dopnet (/obj/wavetank_initial/popnet) という、シミュレーション専用のネットワークの中で設定します。
    • popsource ノード (source_first_input): Boxの表面 (emittype: surface) から、一定の割合 (constantrate: 5000) でパーティクル(泡)を発生させます。

    • gravity ノード (gravity1): 通常、重力は下向きにかかりますが、泡は上に浮いていくので、上向きの力 (forcey: 0.1) を設定します。

    • popsolver ノード: これらの設定に基づいて、パーティクルの動きを計算(シミュレーション)します。

    • 泡の形状: シミュレーション結果は点の集まりなので、この点一つ一つに泡の形をコピーします。copytopoints ノード (/obj/wavetank_initial/copytopoints1) を使い、小さな sphere (球体) (/obj/wavetank_initial/sphere1, scale: 0.04) を各パーティクルの位置にコピーします。

これで、水中を上昇していくたくさんの泡ができました。

4. 泡のマテリアルを設定する (SOP: Surface Unlit)

泡のマテリアルはどうしましょうか? 日記によると「こちらは影があまりついてほしくないので、Surface Unlitにしました」とのこと。リアルな泡というよりは、少し光っているような、影の影響を受けにくい表現を目指しているようです。

  • Unlit Shader: matnet (/obj/wavetank_initial/matnet1) 内に mtlxsurface_unlit ノード (white) を作成します。これは文字通り「Unlit(光が当たっていない)」、つまりライティング計算の影響を受けずに設定した色で光るシェーダーです。
  • パラメータ設定:
    • emission: 自己発光の強さ。1 に設定して白く光るようにします。
    • emission_color: 発光色。白 (1, 1, 1) に設定。
    • opacity: 不透明度。0.1569 とかなり低めに設定されています。(日記にも「さすがにそのままだと目立ちすぎるので、Opacityをめccccっちゃ下げる」とありますね!)これにより、泡が主張しすぎず、 subtly(さりげなく)シーンに溶け込むようになります。

このマテリアルも material ノード (/obj/wavetank_initial/material2) を使って、泡のジオメトリに割り当てます。

5. 計算結果を保存する (SOP: File Cache)

海のシミュレーションや泡の生成は、フレームごとに計算が必要で、特に複雑になると時間がかかることがあります。(日記にも「シミュレーションが重かった」とありますね)

そこで活躍するのが filecache ノード (/obj/wavetank_initial/filecache1) です。

  • 役割: このノードは、それまでのノードネットワークの計算結果(ジオメトリデータ)を指定したファイル形式 (.bgeo.sc) でディスクに保存します。
  • メリット: 一度キャッシュを保存すれば、次回からは重い計算を再度行う必要がなく、キャッシュファイルから素早くデータを読み込めます (loadfromdisk: on)。これにより、作業全体の効率が大幅に向上します。特に、レンダリング前の最終確認などで何度も同じジオメトリを使う場合に非常に有効です。

今回は、海と泡を merge ノードで結合した結果をキャッシュしています。

6. オブジェクトを水中に配置する (SOP: Rubber Toy & Transform)

仕上げに、何かオブジェクトを水中に浮かべてみましょう。日記によると「今月いっぱいお世話になったラバートイを漂わせて、モデリング完了です」とのこと。Houdiniに標準で用意されているテストジオメトリのラバートイを使ってみます。

  • ラバートイの読み込み: testgeometry_rubbertoy ノード (/obj/wavetank_initial/testgeometry_rubbertoy1) でラバートイをシーンに追加します。
  • 配置: transform ノード (/obj/wavetank_initial/transform1) を使って、ラバートイの位置 (tx, ty, tz)、回転 (rx, ry, rz)、大きさ (scale: 0.55) を調整し、水中にぷかぷかと浮かんでいるように配置します。

これでSOPでのモデリング、シミュレーション作業は完了です!

7. LOP (Solaris) でシーンを仕上げてレンダリング

さて、ここからはLOP (Solaris) の出番です。SOPで作った海のメッシュ、泡、ラバートイを配置し、ライトやカメラ、そして水中の雰囲気を出すためのフォグを設定して、最終的な画像をレンダリングします。

  • シーンのインポート: まず、SOPで作ったジオメトリ(File Cacheから読み込んだものとラバートイ)をLOPのステージに持ち込みます。sceneimport ノード (/stage/sceneimport1) がその役割を担います。/obj/wavetank_initial 内の最終的な結果を読み込んでいます。

  • カメラの設定: camera ノード (/stage/camera1) を作成し、水の中から水面を見上げるようなアングルに設定します。

  • ライティング: 光はシーンの印象を大きく左右します。今回は2種類のライトを使っています。

    • 環境光: karmaphysicalsky ノード (/stage/karmaphysicalsky1) で、空全体からの光(環境光)と太陽光 (enablesun: on) を設定します。空の明るさ (intensity: 2.573) や太陽の高さ (solar_altitude: 45) を調整します。
    • 強い指向性ライト: 日記にある「水面から強い光(太陽のような)が入ってきてほしかったので、めちゃつよライトを設置しました」を再現するため、light ノード (/stage/light1) で円盤状のライト (UsdLuxDiskLight) を追加します。水面の少し上あたりから水中を照らすように配置し、強度 (inputs:intensity: 1000) を非常に高く設定しています。これが水中に差し込む光の筋(God Ray)や、水面のきらめきを生み出す元となります。
  • フォグ(霧): 水中の濁りや深さを表現するために、karmafogbox ノード (/stage/karmafogbox1) を使います。(日記でも「fogが存在したので、それを使ってみました」とあります)

    • シーン全体を覆うようにサイズ (sx, sy, sz: 100) を設定します。
    • density (0.124) でフォグの濃さを調整します。値が大きいほど濃くなります。
    • color を水の色に合わせて少し青緑っぽい色 (0.207, 0.487, 0.767) に設定し、水中感を高めます。
  • God Rayとコースティクスについて: 日記には「本当はGod Rayを入れたかったんですが、Fogを入れても見えなかった」「コースティクスについて調べてたらめっちゃいいチュートリアル見つけた!…いや、バージョンが古すぎて…」といった試行錯誤の跡が見られます。

    • God Ray: 強いライトとフォグがあっても、はっきりとした光の筋が見えるようにするには、レンダリング設定(特にボリュームサンプリング関連)やライトの特性(指向性など)をさらに調整する必要がある場合があります。今回は明確には見えなかったようですが、強いライトが良い雰囲気を出しています。
    • コースティクス: 水面を通った光が屈折して水底で揺らめく模様のことです。これも表現するには専用の設定やテクニックが必要になることがあります。今回は実装には至らなかったようですが、水中シーンの表現としては非常に魅力的な要素ですね。
  • レンダリング設定: karmarenderproperties ノード (/stage/karmarendersettings) で、最終的な画像出力の設定を行います。

    • engine: xpu : KarmaレンダラーのXPUエンジン(CPUとGPUを使うハイブリッド)を選択。
    • resolution: 画像サイズ (1920x1080)。
    • samplesperpixel: 画質(ノイズの少なさ)に関わる設定 (9)。値が大きいほど綺麗になりますが、レンダリング時間も増えます。
  • レンダリング実行: 最後に usdrender_rop ノード (/stage/usdrender_rop1) でレンダリングを実行し、指定した場所 (picture: C:/Users/neko/.../render.png) に画像ファイルを出力します。

8. 完成!

こうして、SOPでのモデリング・シミュレーションと、LOPでのシーン構築・レンダリングを経て、幻想的な水中シーンが完成しました!

制作者の日記には、「個人的に青系統の色が好きで自分のパーソナルカラーと感じているので、最後の締めが偶然そんな感じの作品になってとても満足して気に入っています」とありました。試行錯誤はあったものの、最終的に納得のいく作品ができたようです。


いかがでしたか? Houdiniを使えば、このように波のシミュレーションからマテリアル設定、ライティング、レンダリングまで、一連のプロセスを通じて複雑なシーンを作り上げることができます。
今回は水中シーンを例にとりましたが、Houdiniの可能性は無限大です。ぜひ皆さんも、興味を持ったテーマでHoudiniに挑戦してみてくださいね!

所感

今回のノード情報もDay27同様に様々なネットワークが入り混じっていました(SOP、DOP、MAT、LOP)
その結果、今までは2000行(5万文字)ほどだったのが、3500行(13万文字)を超えていました

そんな大規模コンテキストでちゃんと分析できるのか心配でしたが、杞憂でしたね

gravity ノード (gravity1): 通常、重力は下向きにかかりますが、泡は上に浮いていくので、上向きの力 (forcey: 0.1) を設定します。

このようにジオメトリノードのDOPの中の細かな設定だというのに、認識できているようです

nekoconekoco

感想

とりあえず5日分ほど記事を書いてもらいました
この作業をしていて感じたことなどを書いていきます

自動化とタスクは異なる

プログラムの保存

今回は同じような作業を繰り返し行ってもらったのですが、毎回出来が異なるんですよね
また異なるだけならいいのですが、まともに実行できない時もありました

ノード情報を書き出す作業なんてGemini 2.0 flashでも出来るようなタスクなのですが、運が悪いとGemini 2.5 Proであっても沼にハマってまともにこなせません

なのでこのように同じような作業をする場合、最初にうまくいったプログラムを保存して、それを繰り返しやって貰うのがいいでしょう

{
"code": "import hou\nimport json\n\nnode = hou.node('/obj/wavetank_initial')\nif node:\n    children = node.children()\n    node_data = []\n    for child in children:\n        child_data = {\n            'name': child.name(),\n            'type': child.type().name(),\n            'path': child.path(),\n            'connections': [],\n            'parameters': {}\n        }\n        # Connections\n        for input_index in range(len(child.inputs())):\n            input_connection = child.inputConnections()[input_index]\n            if input_connection:\n                child_data['connections'].append({\n                    'input': input_index,\n                    'node': input_connection.inputNode().name(),\n                    'output': input_connection.outputIndex()\n                })\n            else:\n                child_data['connections'].append({\n                    'input': input_index,\n                    'node': None,\n                    'output': None\n                })\n        # Parameters\n        for parm in child.parms():\n            try:\n                child_data['parameters'][parm.name()] = parm.evalAsString()\n            except Exception as e:\n                child_data['parameters'][parm.name()] = str(e) # エラーを文字列として保存\n        node_data.append(child_data)\n    # Save to JSON file\n    filepath = 'g:/マイドライブ/Vault2/wavetank_initial_info.json'\n    with open(filepath, 'w') as f:\n        json.dump(node_data, f, indent=4, ensure_ascii=False)\n    print(f'Node data saved to {filepath}')\nelse:\n    print('Node not found')"
}

実はこれは、私の怠慢です

高速にタスクが実行されていく中、それぞれの成功・失敗、詳細内容を確認していくことがめんどくさくなりました。
「このような自動タスクにおいては、人間の判断がボトルネックになる」という洞察は本当で、作業を早めるためには人間の判断を極力無くすことになってしまいました

そうすると成功したプログラムに対しても興味が失せてしまい、確認することが無かったですね

あと、タスクが小分けにして実行されていくので、個々の成功に興味が向かないというのもありました
タスクをいっぺんに行いそれが成功したなら、そのプログラムを保存するのですが…
小分けにされているので、「どれが重要なんだ?」と、いちいち覚え解く必要ないかなぁって

最後に、「今回のプロンプトをまとめて」とか「今回の成功したプログラムをまとめて」と言うような習慣を付ければ変わるのでしょうか?

タスクはプログラムではない

自分は、プログラムは手続き的に一連の処理をこなすものだと考えているのですが、ClineなどのAIエージェントはそれとは異なると考えています

なんと言えばいいんでしょう…
失敗したときにそこを修正して、最初からもう一度上手くいくか試してみるのが(私の得意な)プログラミングだと思っています

ですがエージェントは、今の状態からどうするか考えるといった感じなので、扱いづらいと感じます
状況が毎回特殊というのでしょうか、毎回異なる現状を把握している必要がありますよね
なのでその時に行ったタスクは、その時に合った特殊な行動なんじゃないかって
だからわざわざ確認する気になれない、みたいな…


以上、ポエムでした

このスクラップは5ヶ月前にクローズされました