テレワーク中のエル

エルは北欧ノルウェー原産の猫なので
寒さには強いはずだが、エアコンの涼しい風は嫌いらしい。

日中はいつもエアコンの風が当たらない場所を見つけて寝ている。

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;// アルファ

Houdini 風船アニメーション2

空気を抜いた状態から徐々に膨らんでいく風船のアニメーションを作ってみた。
ミッキー型の風船が正面を向くように紐の重さや風の強さを調整。

全ての風船の膨らむタイミングを変えるために
DOP内のVellum Constraint PropertyノードにVEXを書いた。

平日の昼間

テレワーク中の昼間のエル。
午前から昼にかけては大体ハンモックの上から外を眺めている。
たまに外を飛んでる鳥に凄く反応している。

「ん?なによ」

Houdini Fur 3

Furのウェットシミュレーションを行ってみた。
熊の頭上から水を落下させ、水と接触したFurの形状や質感を濡れた状態に変化させる。
さらに首を振った際にファーから飛沫を出すようにしてみた。

Houdini Fur splash test from Shuichi Sakuma on Vimeo.

今回のシミュレーションには以下のソルバを使用した。
ファー:Vellum Solver
液体 :Flip Solver
飛沫 :POP Solver

濡れた質感を作るためにマントラ標準のHair Shader(VOP)をカスタマイズした。
シミュレーションと同期させ、ファーのカラー・透明度・スペキュラーを変化させた。

ウェット状態のファーの形状は、SOP内のVEXによって
アトリビュートを操作することで実現している。
この際、水に接触したファーを濡れた形状に瞬時に切り替えるのではなく、
数フレームかけてアニメーションしながら徐々に切り替わるようにした。

通常状態とウェット状態の比較。

一昔前の8コアのマシン(Core i7-5960X)で作業しているが
さすがにこのレベルのシミュレーションになると処理的にキツイ…。

 

Houdini Fur 2

Houdiniで動物のFurを作成し、アニメーションに対応させてみた。

リギング、キーフレームアニメーション、ブレンドシェイプ、マッスル(ジグル)の作業は
全てHoudiniで行った。ファーのダイナミクスを確認するため、立ち上がり後に着地する
アニメーションを作成した。

顔の表情をつけるためのブレンドシェイプはCHOPを中継してリグから駆動できるようにした。
顔のリグを動かせばそれに対応する表情が駆動するようになっている。

今回、ブレンドシェイプのターゲットはEditノードで複数モデリングした。
ターゲットをBlendShapeノードにつなげてCHOPを中継することで
リグからウェイト値を制御する仕組みになっている。

キャプチャー変形、ブレンドシェイプ変形、マッスル変形を併用する場合の
設定の順番は以下の通り。(他にもいろいろな組み方があると思う)

  1. キャプチャーによるウェイト設定(Mayaのスキニング操作に相当)
  2. ブレンドシェイプによる変形
  3. ボーンによる変形(1で設定したウェイト値を参照)
  4. マッスル設定
  5. マッスルによる変形