LoginSignup
31
15

More than 3 years have passed since last update.

お茶を飲もう

Last updated at Posted at 2020-12-15

自己紹介

簡単に自己紹介を
新卒1年目の人です。Houdiniは趣味で毎日やっていたら就職できました。
Houdiniを使った作品制作より、Houdiniで何が出来るか、この現象はこうやったら作れるか等の研究が好きです。
割と独学や研究等で得た知識が多いので非効率な事や突拍子もない事をしますが、動くので大丈夫です。

自分のツイッタです。質問等はDMでhttps://twitter.com/TF_siri

今回の制作物

さて、本題に入ります。今回作るのは「茶」です。
なんで茶かって?寒いからさ。そして自分は茶が好きなので。
夜になんとなく寝れなくて作りました。シミュマテリアル設定等全部含めて3時間半ぐらい?

tea01.jpg
映像もあります。
https://www.youtube.com/watch?v=s44xC90F9Ls&feature=youtu.be&ab_channel=Siri

今回はcompress等の軽量化は一切しておりません。ややこしくなるからね。
シーン、シミュレーションキャッシュも添付しますが32GBあります。
あまり長くなりすぎてもアレなのでDOP編からは詳細は省いてあります。
使う箇所とか全部書いたらキリが無いですし。質問があったら自分にどんな手段でもいいので連絡取ってくださればお答えします。

今回はRedShiftを使ってレンダリングしました。自分はコンポ周りの知識がからっきしなので未コンポ、一発書き出しです。
可能な限り初心者にも分かりやすい用に書きましたが、ソフトの都合上「誰でも簡単!」では無いのでご容赦を。

環境
Houdini indie 18.5.351

CPU : intel i9-7980XE
RAM : 128GB
GPU : GTX 1080ti

最初に観察してから

漠然と制作するだけでも良いですが、まず何が要素としてあるのかをよく見ましょう。想像でも良いですが実物見た方が良いですね。

・お茶を注ぐ為のカップ
・お茶自体の液体
・お茶から立ち上る湯気
・湯気がガラスに付いた時の曇り

ですかね。
今回はこの4つ+レンダリングをします。

カップのモデリング(初心者向け)

初心者向けに長く書いてるので、まず中級者以上の方用にやってる事書きます。
「断面作ってRevolveして、取っ手付けときます。後々使うので内側にはinsideのアトリビュートをfloat 1で与えといてください」
以上です。では初心者用の記事に移ります。

まず茶を入れる為のカップが無い事には始まりません。机にぶちまける訳にはいきませんからね。
おもむろにHoudiniを立ち上げます。作業を始める前に、上のタブからPoly Modelingモードに変更しましょう。こうするとモデリングがやりやすいモードになります。
スクリーンショット 2020-12-12 202730.png
geoを作って中にcurveノードを作ります。
curveを引いて、断面図を作るのですが、断面図を作るという都合上完全に2次元的に配置しないとなりません。
後でscaleを0にして合わせても良いですが、一発でやりたいのでビューポート上でSpace+3を押し、xy平面を見ます。
この状態でEnterを押してCurveを引いていきます
image.png
ここであまり細かくなめらかにする必要はありません。めんどくさいですしね。
しかし、始点と終点は0にしてください。面を貼った時に穴が出来てしまいます。
この後、カップ底面や飲み口など、角がしっかりしててほしいポイントを選択し、cキーを押してPoly modelingメニューからBevelします。
image.png
ここで、後程使うのでinsideアトリビュートを作成します。
カップの内側に相当するポイントを指定して、Wrangle等で@insideを作っておきましょう。
image.png
edit等で形を整え、Convertノードを接続します。これは入力した物を色々な形式に変換してくれます。
今回は都合が良い「NURBS curve」にします。
image.png
そうすると丸みを帯びた曲線になりました。詳しく知りたい場合は「NURBS 何」で調べてください。式でカーブ書くのです。
このままではポリゴンに出来ないので、resampleノードでポリゴンにします。

さて、これで断面が出来たのでカップの形状にしていきましょう。
これをポリゴンにするのに使うのは、Revolveです。
image.png
Mayaでもあったかな?壺とか作れるのですね。
これをそのまま使うと何故か面が反転してるので「reverse mesh」のチェックをオンにして面を正常な向きにします。
後々湯気の時に必要なので細かくしておきます。自分は150。
image.png
さてこれでカップは出来ました。でも何か足りないな.....
そう!持ち手ですね!これじゃ熱くて持てない。
じゃあ最初の手順でCurve出して持ち手の形状にし、Resampleまでやります。
image.png
今回はRevolveは使えません。なのでSkinを使います。
Copy and transformを出し、Z方向に任意の値だけ移動します。
この移動値が持ち手の幅になります。
image.png
でもこのままSkinしてもダメなので、transformノードで移動値の半分だけ元に戻します。
ですが、もし後々幅を変えたくなったら数値をいちいち入力するのがめんどくさいので自動化します。
Copy and transformのtranslate zの上でマウス右クリックをし、Copy parameterを押します。
image.png
特に何も変化無いように見えますがCtrl+Cと同じようなものです。
このままTransformノードのtranslate zの上で右クリックをし、Paste relative referenceを押します。
こうすると、リンクされます。Copy and transformで入力した値と同じ値が出てくるので、最初に-を付け、
最後に/2を入れましょう。
こうすると移動方向に対してマイナスの向きに半分だけ移動するので、鏡合わせのようになります。
image.png
じゃあこれらで作ったカーブに面を貼りましょう。skinノードを接続します。
今回はcopyしたのでポイント数等々なので普通に出来ます。
image.png
まぁこっからは面が出来てるので楽なもんです。
extrudeしてsubdivideして出来上がり!!
image.png
ではこれでカップは出来上がりです。
ですが、サイズが間違ってる場合があるのでtransformのuniform scale等で調整しましょう。
スケールはデフォルトだと1メモリ1mです。後々響きます。
スクリーンショット 2020-12-12 204148.png
後でコリジョン等の時に選びやすい用にmergeノードの下にNullノードを出し、「CAP」とでも名前を変更しておきましょう。
Houdiniは大文字を優先して上位に出すので、大文字にすると他ノードより見つけやすくなります。

茶の制作(中級者向け)

中級者向けに書いています。なので、上級者向けにやってる事書きます。
「小規模液体シミュレーション用の設定して書き出します。collision offsetで湯気出す面の色を変えてください」
以上です。では中級者向け記事に移ります

本題とも言える茶の制作ですね。
では別のgeoを作成します。teaとでも名前を変えておきましょうか。

液体シミュレーションをするためには液体の発生源、つまりソースを出さなければなりません。
今回はsphereでやります。
sphereを先程作ったカップに対し、不自然でないサイズにスケールします。

このSphereにアニメーションを設定していきます。
今回は発生源が円運動するように調整していきましょう。

addを出し、point0のチェックをオンにしてポイントを1つ作成します。
そのポイントを移動させる為にpoint Wrangleを使います。
ではVEXのお時間です。と言っても凄い簡単。

float source=@Time*ch("speed");
@P.x=sin(source);
@P.z=cos(source);
@P*=ch("radius");

です。
sinとcosに同じ値が入るので円運動になりますね。
speedとradiusで速度と半径を変更可能です。
speedを調整して適度なスピードにしましょう。
ティーポットから注ぐときに回すスピードです。

ではポイントの位置に最初に作ったsphereを持ってくるのでcopy to pointします。
でもまだ地面を這いまわってるので、適度な高さまで上げましょう。
VEX内で高さ調整用のパラメータを設定しても良いかもしれませんね。

今回はティーポットを使わないので出来ればカメラから発生点見えない方が良いですね。
かと言って高すぎるとびちゃびちゃ散ってしまいます。
カメラからの絵とシミュレーション結果を見ながら適度に調整することになります
スクリーンショット 2020-12-11 155424.png
では、flipsourceを出します。これは読んで字のごとくflip用のソースにしてくれるのです。
デフォルトだと津波等の大規模シーン用になってるのでvoxelsizeとparticle separationで適度な密度にします。
スクリーンショット 2020-12-11 155005.png

このままだと流れ続けてしまうので、switchとnullで流れを止めときましょう。$T>"止めたい時間"で指定すればnullに移行して発生源が無くなるので水流を止められる。
ここまでのネットワークです
スクリーンショット 2020-12-11 155343.png

ではお待ちかね!DOPnetworkです!!
初心者が最初にやりたがって挫折するノード代表!皆SOPからやろうな!!

DOP!!

ではDOP内で、「volumesource」「flipsolver」「flipobject」「gravity」「merge」「staticobject」「staticsolver」を作成し、以下のように繋げます。

スクリーンショット 2020-12-11 154310.png

static geometryにCAPを入れ、ボリュームを見ながら全体像が見えるようにします。

スクリーンショット 2020-12-11 154804.png

こっから細かくなるので、ノード別に変更箇所を書きます。
もし分からなければ配布シーンを参照してください。
flip object
・partticle separationにflipsourceのparticle separationをリンク
・guides/particleからvisualizationをparticlesに変更
flip solver
・particle Motion/Reseedingを以下の設定に
 ・Surface Orversamplingを10へ
 ・Orversampling Bandwidthを2へ
 ・Birth Thresholdを1へ
・Volume Motion
 ・Velocity TransfarをAPIC(Swirly)へ
 ・/Volume LimitsのBox Size、Box Centerを発生点からシミュレーションする物まですべて含めた最小体積より少し大きく
 ・/AirのEnforce Air Incompressibilityをオンに
 ・/Surface TensionのEnable Surface Tensionをオンに、数値を低くする。
volume source
 ・InitializeをSource FLIPにへ変更
 ・InputをFirst Context Geometryに変更
merge
 ・Affector RelationshipをMutualに変更
スクリーンショット 2020-12-11 153929.png
アートボード 1.png
スクリーンショット 2020-12-11 154136.png
スクリーンショット 2020-12-12 153031.png

さてシミュレーションしてみましょう。
多分失敗します。スクリーンショット 2020-12-12 155036.png
これはSubstepが原因なので、flipsolver/Substeps/Max Substepをブチ上げましょう。
もっと効率良い方法もあるかもですが、これが手っ取り早いです。
スクリーンショット 2020-12-12 154952.png
恐らくSurface tension辺りが悪さしてるのか、Reseedingがダメなのか....原因は分からないですがとりあえずSubstepを上げれば解決します。
ここは色々な設定が複雑に絡み合ってるので全部の解決法を書くのは時間的にも枠的にも難しいです。
DMでもリプでも、連絡を貰えれば可能な限り対処します。(Twitter=https://twitter.com/TF_siri)
トゲトゲになるならsurface tensionを下げると解決するとか、衝突が発生しない時はどうするとか。

さて、シミュレーション自体を作るのはこれで終わりですが、まだです。
これをSOP内で使い、かつ毎回シミュレーションしないようにキャッシュを取ります。

SOPに帰り、DOP network/Object merge/Objectにflipobject1と入力します。
これで水のみを取ってくることが出来ました。
file cacheを作って名前を変更します。お茶の液体のシミュなのでteaとでも変えておきましょう。
キャッシュ作る時は名前変えてからキャッシュしないと後々痛い目見るので気を付けて。
スクリーンショット 2020-12-12 160739.png
さてキャッシュしましょう。
自分は192フレームで56分でした。(i9-7980XE&128GB)
書き出したら、一応確認しましょう。
こんな感じにパーティクルのみあればOK
スクリーンショット 2020-12-12 160636.png
では面にしていきましょう。これにはparticlefluidsurfaceというノードを使用します。
 ・/surface/Particle SeparationにDOP内で使ったようにflipsourceのparticle separationをリンク
 ・/regions/Collisions/Subtract Collision Volumesをオンに。
particlefluidsurface.png
さて、このSubtract Collision Volumesという設定ですが、これは今回のように器に入った液体等を計算する時に、器に液体をピッタリと這わせてくれる物になります。
都合が良いので使いましょう。Object mergeを作成し、CAPのモデルを持って来て2番目の接続に加えます。
スクリーンショット 2020-12-12 164358.png
ここで、後々使う設定もやっておきましょう。
 ・Filtering/Collision Offsetをオンに
 ・Visualize Maskをオンに
 ・色を調整し、注がれてる液体、表面のみ白くなるように調整
スクリーンショット 2020-12-12 164823.png
上手く行っていたらこれも後々使うのでキャッシュしましょう。
以前の手順でtea_surfaceにしておきましょうか。
最後にNullを繋ぎ、TEAとでも名前を変えましょう。
さて、一旦これでお茶の液体シミュレーションは終わりました!
一息つきましょう。ドーナツとか食べてください。
僕はポンデリングとかのモチモチしたのが好きですね。

湯気のシミュレーション(中級者向け)

上級者向けのを書いときます。
「tea_surfaceで作った湯気出るとこを発生源にして湯気作ります。質感はお好みで」
では記事に移ります

熱い茶を煎れるんだから湯気は無いとなぁ!
と言う事で湯気を作ります。
まず、ObjectMergeで先程の液体シミュレーションの最終結果のTEAを持ってきましょう。
scatterのDensity AttributeにCdを入力します。
これは先程の液体の最後にやったCollision Offsetのマスクですね。液体から湯気が出るところを白にしてあるのでこのまま使えます。
スクリーンショット 2020-12-12 174348.png
その後、Pyrosourceを作成し、densityとtemperatureを与えます。
このポイントをボリュームにするのにvolumerasterizeattributesを使用します。
volumerasterizeattributes/general/Attributesは、「density v temperature」の3つを使用します。それぞれ濃度、温度、速度です。
次にvolumerasterizeattributes/Voxel sizeにpyrosourceのparticle separationをリンクし、良い密度までpyrosourceの方で値を弄り、程よくボリュームが見えるようにします。
スクリーンショット 2020-12-12 180748.png
さてお待ちかね!DOPです!!
DOPを作成し、中に入って「staticobject」を2つ、「merge」を2つ、「smokeobject」「volumesource」「pyrosolver」を作成し、以下のように繋ぎます。
スクリーンショット 2020-12-12 173849.png
staticobjectは液体の時のようにCAPと、液体のモデルを持ってきましょう。
mergeは両方ともMutualです。
ここで注意ですが、液体のモデルは固定されている物ではなく常に形が変動します。デフォルトの設定だとこのままだと1フレーム目の形状しか読み込まれないので、StaticObject/Use Deforming Geometryをオンにします。スクリーンショット 2020-12-12 181131.png
こうするとデフォーム(=変形)したモデルを読み込んでくれます。

ではSolver関係の設定に行きます。
SmokeObject
 ・SizeとCenterを適切な値にし、計算する領域よりほんの少し大きいサイズにする。
 ・Division sizeにpyrosourceのparticle separationをリンクします。
Volume Source
 ・InputをFirst Context Geometryに変更
 ・/Volumes/Operationsの+を押して3つに増やし、Source Volume , Target Field ,それぞれにdensity temperatureを入力する。
 ・vの場合のみ少々異なり、Source Volumeにv、Target Fieldにvelを入力し、Field RankをVectorにする。
Pyro Solver
質感の設定なので後々話します。
スクリーンショット 2020-12-12 183316.png
volumesourcePyro.png
さてシミュレーションが出来るようになりました!
結構重いですが一旦回します。ここからはPyro solverで質感の設定になります。
かなり有名ですが、この動画が凄い参考になります。https://vimeo.com/90803730

自分はDissipationを低めに、Shreddingを半分、Buoyancy Liftを10にしました。
Buoyancy Liftはその名の通り浮力です。上に行く力ですね。
これが働いていない場合、temperature関係の設定が間違っている可能性があるので見直しましょう。
煙が出ていない場合はdensity関係。それぞれの値に倍率かける時はVolume Sourceのそれぞれの下にあるScaleから指定できます。

さて、SOPに戻って液体の時のようにシミュレーション物だけ取り出します。
爆発等複数のアトリビュートが必要な物ならともかく、今回はdensityだけ欲しいのでDOP networkの物をそのまま使います。
DOPnetwork/Objectにsmokeobject1、Dataにdensityを入力します。
スクリーンショット 2020-12-12 184426.png
ではこれで湯気の終わりです。以下がネットワークになります。
スクリーンショット 2020-12-12 184936.png

カップの曇り(オリジナルテク)

出来れば上級者の方にも読んでいただきたいですが、内容書くとこうです。
「湯気をポリゴン化して湯気までの距離、液体までの距離で色を変えて曇りのアトリビュートをCdで作ります」
さて記事に行きましょう。

ここまでのをレンダリングしてみます。(レンダリングの設定等は後で書きます)
teaNoclowd.jpg
お茶と湯気は良いですが、なんか湯気が上るほど熱くは見えないな.....と言う事で、現物を観察しました。観察だから....これ休憩じゃないから.....
ふむ、湯気に当たったカップは曇りますね。温度差があるので表面に水滴が触れて云々。
なので、曇らせていきます。

さて曇らせる、まぁカップ自体のラフネスを弄れば良いですね。とりあえず湯気の情報が欲しいので湯気をポリゴン化します。
スクリーンショット 2020-12-12 191735.png
こんな感じ。レンダリングに関係ある物じゃないので荒くて良いのです。
さて、やり方を書きます。
Convert VDBでfogをVDBに変換し、そのVDBをポリゴンに変換しています。
VDBpoly.png
これでポリゴン化した物は使うのでいつも通りNullで出しやすい用にしましょう。
Steam_polyとかで。

capに行き、colorを使用して色を黒(Cd=0)にします。
その下にpoint Wrangleを作成し1入力にObject Mergeで先程のSteam_polyを持ってきた物を入力します。
そしてVEXに

@Cd=fit(distance(@P,minpos(1,@P)),ch("min"),ch("max"),1,0);

と入力します。
少し複雑ですが簡単に説明します。
fitはfit(対象にする値,最大,最小,更新後の最小,更新後の最大);となっています。
minposは、入力したサーフェス上の一番近いポイントの位置になります。
distanceはその名の通り、2点間の距離を測ります。
なので、このVEXを翻訳すると

色は、今の位置と入力1の最も近い位置の間の距離からminとmaxの間で0~1になる。

となります。
翻訳は難しいけど、多分こんな感じで合ってる。
説明するまでも無いと思いますが、この白いとこが曇りになります。

このVEXを入力し、minmaxを弄ると以下のようになると思います。
スクリーンショット 2020-12-12 193855.png
一応今やっているのは、湯気からの距離に応じて色を変更しています。
でもおかしくないか?湯気は純粋な距離だけでなく、障害物に阻まれるカップの外側には付かない。
なので、そこを修正します。
モデリングの時に作った@insideを使用します。
先程入力したVEXの上に

if(@inside>0)

と入力しましょう。
if文に関しては言わずもがな。一応翻訳すると、「もし@insideが0以上の場合、実行する」みたいな感じかな?
スクリーンショット 2020-12-12 194250.png
これでよくなった?
否!まだ変なところがある!
曇りは水に触れたりするとそちらに取られるので消えるはずだ!!なので液体が入ってるところには出来ない!!
なのでそこも修正しましょう。

先程のWrangleの下に新しくpoint Wrangleを作成し液体が欲しいのでTEAモデルをObject Mergeで持って来てWrangleの1入力に接続し、

@Cd*=fit(distance(@P,minpos(1,@P)),ch("min"),ch("max"),0,1);

と入力します。
え?さっきと同じだろって?ちょっと違う。
@Cdの後に*が入っている。なので、この文で出た結果を掛け合わせます。
スクリーンショット 2020-12-12 194917.png
値を設定するとこんな感じに、液面から下は黒になった。
色を直接ポイントに付けてるのでちょっとギザギザしてますね。Attributeblur等でぼかしましょう。

これでOK!曇りの設定は出来た!!
おめでとうございます。こっからはレンダリングになります。

レンダリング

こっからはRedShiftのお時間だ。
今回はRedShiftで作ってますが、一応使っている物と似てるのはMantraにもあるので出来ると思うよ。
皆indie買ってRedShift買おうね。レンダリング速度速いとやる気も出るよ。
と言っても持ってる人はもうレンダリング出来るだろうから、曇りの部分だけやるね。

その前にHDRIを使うので、毎度おなじみHDRIhavenさんでballroomのHDRIをダウンロードしてきましょう。
https://hdrihaven.com/hdri/?c=indoor&h=ballroom
これにしたのは雰囲気が良かったから。添付すると二次配布になっちゃうのでリンクからお願いします。

さて、今回曇りを作る上で重要になるのが、ParticleAttributeLookupというノードです。
スクリーンショット 2020-12-12 200215.png
これは文字の通り、パーティクル=ポイントのアトリビュートを持ってきます。
勘の良い方はお気づきだと思いますが、これでカップのCdアトリビュートをラフネスに入れます!
あ、マテリアルはGlassプリセットをそのまま使用しています。
image.png
ネットワークはこう。
RSMathRangeはVEXのfitみたいな物。0~1で色を作ってて、ラフネス1だとちょっと高すぎたので調整用に入れてます。

で、レンダリングしてみました。
良いですね!ラフネスがアトリビュートで変更されて良い感じに曇りっぽくなっています!!
Desktop Screenshot 2020.12.12 - 20.08.38.32.png

この底面だけの反射については以前Twitterで上げましたが、RedShiftのライトは当てる対象を選択できます。
なので底面のgridを作成し、そのgridのみ光を当てないようにすればオブジェクトからの反射光や屈折光のみ反射するので不思議な感じに出来ます。(というよりテクスチャ使いたくなかった。遅いし。)

さて、これで終わりですね。
teaNoclowd2.jpg

おわりに

凄い長くなりましたが、やっと纏め終わりました.....制作+レンダリング時間より執筆の方が時間かかりましたね。
自分自身、結構クオリティの高い物が作れて驚いています。
作り終わってから書いているのでところどころ抜けている所、説明不十分な所があると思いますがシーンを見て、それで分からなければDMかリプをください。

あ、最後にシーンです。キャッシュファイルは重すぎるので別添付します。
シーン https://1drv.ms/u/s!Al-gq6RIAjNrulauKSQsfCFnB9Bu?e=VOiaSD
geo(32GBあります) https://11.gigafile.nu/1219-nc4d460d3f9415807c1fb7a7dc21999bc

添削、相談に乗ってくださったbechicaさん、(https://twitter.com/bechica)
ありがとうございます!

うーん、最後に書く事ってあんまり無いですね。質問等はいつでも受け付けてます....ぐらい?
まぁ、あれです。

良いお年を!

31
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
15