カテゴリー別アーカイブ: houdini

Houdini FLIP その1

Houdini FLIPのテスト。
岩に凹みをつけて、岩が浮き上がった際に水が凹みに溜まるようにしてみた。

レンダリングはRenderMan。
最新のRenderMan23.5では途中でレンダリングが止まってしまうため
Houdini 18.0.532上でRenderMan23.4を使用した。

Houdini FLIP test from Shuichi Sakuma on Vimeo.

Houdini KineFX Spider リグ

Houdini 18.5のKineFXを使って蜘蛛のアニメーションを作ってみた。

今回、蜘蛛の脚の動きにはサイクロイド曲線を使用し
Rig Attribute Wrangleノード内のVEXで制御した。
(サイクロイドとは円が回転するときの円上の点が描く軌跡のこと)
蜘蛛のジョイント階層のルートジョイントの毎フレームの移動量から
サイクロイド曲線上の各脚先の動きを割り出している。

【テスト1】
蜘蛛を動かしながら衝突判定を行った。
蜘蛛の脚先からintersect関数を使って特定方向にレイを打ち、衝突検知を行っている。
衝突した際の姿勢の制御もVEXで行った。

【テスト2】
壁を上るテスト。
平地からのスムーズなトランジションを実現。

以下、サイクロイド曲線を可視化したもの

今回感じたKineFXの強み
・ローカル座標系<–>ワールド座標系の使い分けが簡単にできる
・フルボディIKをプロシージャルに使用できる
・モーションのブレンドをプロシージャルに行える
・どこでどのようなモーション編集を行っているかが一目でわかる
・必要なタイミングでFK・IKを組み込める
・CHOPを簡単に組み込める(蜘蛛の頭の振動を抑えるためにFilter CHOPを使用)

 

Houdini KineFX

Houdini18.5 のKineFXを使って、以前Houdiniでモデリングしたロボットを
動かしてみた。

モーションはmixamo.comからダウンロードしたもの。
ロボットの体型に合わせてモーションの調整を行い、
Vellumで腕のインナーチューブのシミュレーションを行った。

足の接地にはStabilizeJointノード、関節の曲がり角度制限にはFullBodyIKConfFgureJointsノード、重心制御にはIKChainノード、腕のモーション修正にはRigPoseノードを使用した。
今回mixamoのジョイント階層とロボットの階層構造がかなり異なるため、
モーションを移し替えた際にロボットの膝の振動が発生してしまった。
そのためにRigAttributeWrangleでIKのTwist位置を調整するVEXを書いた。
さらにAttachControlGeometryノードを使用し、Vellumシミュレーションのベースとなる
チューブの初期位置を確定した。

KineFXを触ってみた所感だが、SOP内で階層構造を扱うための行列計算が格段にやり易くなった。
数年前に書籍「Houdini SOP&VEX編」を書いているときは、SOP内で階層構造を実現するための
行列計算が大変だった記憶がある。
また、KineFXとVellumの親和性はかなり高そうだ。

そういえば、SideFXのHouidni18.5のデモ動画にも
このタイプのロボットが出ていたな~。流行ってるのかな?

RenderMan for Houdini その3

今回RenderManのボリュームシェーダと屈折系シェーダのテストを行うために
以下のような海中を泳ぐクラゲのシーンを作成した。

海の中を表現するために大きなコンテナに対してボリュームシェーダを設定。
その上部にエリアライトを置き、ライトとコンテナの間にライトをブロックするための
複数のグリッドを配置した。それをVEXで小刻みに動かして水中に差し込む光を表現した。

Houdini Jellyfish test from Shuichi Sakuma on Vimeo.

クラゲの頭の動きはH18から新しくなったBendノードとsin関数を組み合わせて制御。
クラゲの触手はVellumを使って動かした。

シーンに大量の屈折体やボリュームシェーダが割り当てられたスケールの大きいオブジェクトが
ある場合でも、RenderManは極端にレンダリングスピードが落ちることがない。
このあたりが標準レンダラーのmantraとは違う点。

今回少しだけRenderManカスタムシェーダを書いたが、SeExprは必要な関数が
一通り揃ってるため使いやすかった。
(以前ブログにも書いたがSeExprはWalt Disney Animation Studiosが策定した
エクスプレッション言語)
http://wdas.github.io/SeExpr/doxygen/userdoc.html

シェーダ内でSeExpr関数を使う際には以下の本が役に立った。
REYESが終わってもこの本はまだまだ活躍できる。

 

RenderMan for Houdini

RenderMan for Houdini その2

Houdini18 RBD その1

H18のRBD(RigidBody)ワークフローに慣れるために
高架橋の破壊エフェクトを作ってみた。

H18から、RBDはSOP内でセッティングを行うことができ
ノードネットワークもかなりわかりやすくなっている。
今まで散在していたRBD関連のノードを
うまくアセットにまとめている感じだ。

シミュレーションはキャッシュを取りながらRBD->Pyro->パーティクルの順番で行った。
RBDのシミュレーション結果の速度ベクトルを
パーティクル、Ryroシミュレーションで再利用している。

動きの細かい部分に関してはVEXで制御した。

H18 RBD test v.01 from Shuichi Sakuma on Vimeo.

H18 RBD test v.01 flipbook from Shuichi Sakuma on Vimeo.

RenderMan for Houdini その2

Houdini内でRenderManのヘアーシェーダとスキンシェーダのテストを行った。

RenderManのヘアーシェーダのパラメーター設定は
「フィジカルモード」と「アーティストモード」で切り替えて使用ができるが
今回はフィジカルモードを使用。

フィジカルモードではメラニン色素をベースにして髪の色が決定される。
今回はブロンドの設定のため、メラニンは低めに設定し
ディフューズ反射を上げた設定にしてみた。

スペキュラー計算はマルシュナーモデル(Marshener)というものがベースとなっており、
以下の三種類のスペキュラーが設定できるようになっている。

  1. 光が髪の表面に当たって反射する一次スペキュラ
  2. 光が髪の表面を透過した後、毛髪繊維のボリュームを通過して髪の背面で反射し、再び毛髪繊維のボリュームを追加した後髪の前面から反射する二次スペキュラ
  3. 光が髪の表面を透過した後、毛髪繊維のボリュームを通過してそのまま髪の背面へ反射する三次スペキュラ

スペキュラー強度はコーン角度で設定できるようになっているためわかりやすい。
また毛髪の断面形状までもシェーダで設定できるようになっている。

さらに、フィジカルモードで髪を染める染料を設定すると、単に色素を入れ替えるのではなく、ベースのメラニンに対して染料の色素がコーティングされたような自然な見え方になるようレンダリングしてくれる。以下のレンダリング画像はブロンドヘアーに青の染料を追加したもの。

また、アーティストモードで使用すれば非現実的なアニメ調のキャラクターの毛髪にも対応可能になり、あらゆる毛髪タイプに対応可能なシェーダになっている。

以下シェーダの接続。pxrHairColorをpxrMarshenerHairに接続。
pxrHairColorで毛髪一本ごとのディフューズとスペキュラー決定し、
pxrMarshenerHair(マルシュナーヘアー)でシェーディング計算を行う。

スキンシェーダは、サブスタンスペインターで肌のテクスチャーを作成し、
Pixar Shaderの表面下散乱(SSS)モデルを使用した。
表面下散乱の計算アルゴリズムは6種類から選ぶことが可能で
今回は表面下散乱の計算にはレイトレースは使用せず、
ディフュージョン(diffusion)方程式をシンプルな関数で近似する
Jensenのダイポールモデルを使用した。

表面下散乱の計算をフルレイトレースで行うアルゴリズムも用意されており、
MPCは「ブレードランナー2049」ではレイチェルの皮膚の表面下散乱計算に
フルレイトレースのアルゴリズムを使ったらしい。

毛髪のスタイリングにはVellumを使用。計算が安定しているため大量の毛髪でも
問題なくハンドリングできた。前方から一定時間だけ強風を吹かせて形を整えた。

RenderMan for Houdini

「RenderMan for Houdini」に関する備忘録

RenderMan(レンダーマン)とはPixar社のレンダラー。
https://renderman.pixar.com/product

RenderMan Showreel 2020 from Pixar’s RenderMan on Vimeo.

Pixarのアニメーション作品は全てRenderManでレンダリングされており
MPCを筆頭とする海外の大手VFXプロダクションにおいても様々な映画で使用実績がある。
Houdini上でRenderManを使用するためにはHoudini Indieの購入が必要だが
RenderMan自体は非商用に限り無料で使用できる。

今回は先日Houdiniで作成したロボットのシーンをRenderManでレンダリングしてみた。

RenderManには様々な質感表現に対応しているモノリシックシェーダの
Pixar Shaderがあるが、今回はサブスタンスペインターで作成したPBRテクスチャ
(basecolor-metal-roughnessワークフロー)を使用するためDisney Shaderを使用した。
これはHoudiniのPrincipled Shaderに相当するシェーダになる。
(というか、HoudiniのPrincipled ShaderはDisney Shaderがベースになっている)

HoudiniのPrincipled Shaderのアイコンはシンデレラ城だが、
本家のDisney Shaderのアイコンはミッキー。

ちなみにPixar ShaderはLuxoボール。

今回作成したシェーディングネットワークは以下の通り。
Disney Shaderにサブスタンスペインターで作成したテクスチャー(basecolor,metal,roughness,normal)を接続している。(SeExprノードについては後述)

basecolorテクスチャーのみリニア空間へ変換しておく。

先日やったような腐食箇所以外のロボットのペイントカラーを変更するために
SeExprノードを使用した。
SeExprはウォルトディズニー・アニメーションスタジオが開発したエクスプレッション言語。
https://wdas.github.io/SeExpr/overview.html

SeExprノードはRenderManシェーダ内でInline Codeノードの代わりに使用できる。
(あたりまえだがRenderManコンテキスト内ではVEXは使用できない)

そしてSeExprノードには以下のコードを記述。
このプログラムによって腐食箇所以外のロボットのペイントカラーを変更している。
SeExpr自体は少々クセがある言語で、最後の行にはセミコロンを付けずに
return値だけを書いておくなど様々な決まりごとがある。

col = colorInput1;# ベーステクスチャ
col = rgbtohsl(col);# HSV空間へ変換
a = floatInput1;# 錆のalphaテクスチャ
a = a < 0.1 ? 1 : 0;
b = hash(floatInput2+100);# 乱数を発生(floatInput2はロボットID)
b *= a;# 錆がない箇所は0に設定
h = col[0]+b;# 色相を変調
s = col[1];# 彩度
v = col[2];# 明度
h = h < 0 ? 1+h : (h > 1 ? h-1 : h);# 0から1に制限
s = s < 0 ? 1+s : (s > 1 ? s-1 : s);
v = v < 0 ? 1+v : (v > 1 ? v-1 : v);
col = hsltorgb([h,s,v]);# RGB空間へ戻す
col

RenderManのPrimVarノードを使用するとHoudiniのジオメトリアトリビュートを
読み込むことができるが、Primitiveアトリビュートを読み込むとRenderManがクラッシュするためRenderMan側で使用するアトリビュートはPointに対して持たせておいた。
(今回はロボットごとのid)

RenderManのレンダリング結果(4Kサイズ)

albedoを見るとシェーダ(SeExpr)によってロボットの腐食部分の色は変えずに
ペイント部分の色だけが変化していることが確認できる。

以下、RenderMan for Houdiniを使用して感じたメリット。

・Houdiniとの密なインテグレート
・It(Pixar製のビューワ)の使いやすさ
・2種類のサーフェイスシェーダ(シンプルな”Disney”と多機能な”Pixar”)
・マテリアルプリセットの豊富さ
・GI計算の収束スピードの速さ
・チェックポイント機能(GI計算の途中結果を繰り返し回数や時間間隔を基準にして保存)
・学習リソースの豊富さ(https://renderman.pixar.com/learn
・シーンに応じたGIアルゴリズムを選択可能

RenderMan for Houdiniのマテリアルプリセット画面

Houdini シェーダによるテクスチャーの変調

以前、ラピュタに出てくるロボットをHoudiniでモデリングし
サブスタンスペインターでPBRテクスチャーを作成した。

Houdiniでポリゴンモデリング

その際、テクスチャーは金属層・ペイント層・腐食層の3つのレイヤーに分けて作成したが
今回はレンダリング時にシェーダでペイント層のテクスチャーをロボットごとに変化させ、
ロボットにカラーバリエーションを与えてみた。

以下はサブスタンスペインターで作成した金属層・ペイント層・腐食層のテクスチャー。

まず、サブスタンスペインターからテクスチャーをPSDファイルにエクスポートし
Photoshop内で腐食レイヤーのテクスチャーマスクを別ファイルとして保存。
これはシェーダ内から参照するためのサーフェイス上の錆(さび)の有無を示す情報になる。
今回はTGAファイルのアルファチャンネルに保存した。

次にHoudiniのSOP内でロボットごとにプリミティブに対してidアトリビュートを設定しておく。
これはCopyToPointsなどでポイントに対してロボットをコピーする際に
ターゲットポイントのidをもらってくるやり方で設定できる。(PointWrangleで@id = @ptnum;)
このidはロボットごとの識別番号となる。

idアトリビュートはプリミティブアトリビュートにプロモートしておく。
(後でシェーダ内のParameter VOPからこのidを参照するため)

そしてロボットに設定したPrincipledShaderのロックを外して中に入り、
さらに以下の図のノード(Surface Texturesカテゴリーのbasecolor)の中に入る。

上記の図の拡大(Surface Texturesカテゴリーのbasecolor)

中へ入ったら、元々接続されていたオレンジで示すラインを削除し、オレンジ枠内のVOPを新しく作成し接続。オレンジ枠内にはInline Code VOPとそれに対する入力となるParameter VOP、
テクスチャー読み込みのためのTexture VOPが作成されている。

Inline Code VOPはシェーダノードの中で唯一VEXを書けるノード。
Pameter VOPからの入力(各種テクスチャー、idアトリビュート)を取得し
最終的な色を計算する。VEX内の入力・出力には$記号を付けることに注意する。
ここで、腐食レイヤーのテクスチャーマスクを読み取り、
腐食している箇所の色はそのままにしておき、それ以外の箇所の色を変化させた。
乱数シード値をid(SOPで設定したロボットの識別番号)で固定させるのがポイント。

$color = $clr;// ベーステクスチャ
if($clr_2.w < 0.1) // 腐食テクスチャーのマスクをチェックし錆の有無を判定(閾値は適当)
{
    vector c = vector($color);// vector型へキャスト
    c = rgbtohsv(c);// HSV空間へ変換
    c.x += fit01(rand($id+100),-0.5,0.5);// 色相調整
    c.y += fit01(rand($id+200),-0.2,0.2);// 彩度調整
    c.z += fit01(rand($id+300),-0.2,0.2);// 明度調整
    c.x = clamp(c.x,0,1);// 0から1に制限
    c.y = clamp(c.y,0,1);
    c.z = clamp(c.z,0,1);
    $color = hsvtorgb(c);// RGB空間へ戻す
}
$color.w = 1;// アルファ