すあまの備忘録

誰得内容の自分のための非営利目的備忘録ブログ(筆者がわかっても内緒にしてください)

Houdiniでえくすぷろーじょん

f:id:godofsuama:20201002213206p:plain

はじめに


explosion

こんな記事を書いている間にH18.5が発表されてPyroがめちゃアップデートされてた。

Houdini 18.5 Sneak Peek on Vimeo

備忘録なので過去の作り方としてそのまま記事に。

この記事の後半を読む前に、参考にしたMatt PuchalaさんのSample Hipを開くこと。

vimeo.com

Axiom Solver — Matthew Puchala

全体

f:id:godofsuama:20201002174239p:plain

POP Emitter

f:id:godofsuama:20201002174448p:plain

左側

LineからSweepで半球を作成。この際に真上に穴を開けておいて真上にエミットするパーティクルができないようにする。

f:id:godofsuama:20201002174554p:plain

Normalを作成し、Scatter(このScatterの数がPOPのエミット数)

f:id:godofsuama:20201002174627p:plain

右側

Point Generateで1つだけPointを作成し、Attribute Createでエミットするフレーム番号のアトリビュートを作る。

f:id:godofsuama:20201002174759p:plain

Wrangleでエミットするフレーム番号+Durationの範囲以外の場合はPointを削除させる。

@multを作成し、あとでtemperature,burnをフレームによって調整する。pscaleも同様

if(@Frame < @stFrame || @Frame > @stFrame + chf("dur")) {
    removepoint(0,@ptnum);
}

f@mult = fit(@Frame, @stFrame, @stFrame + chf("dur"), 1,0);

f@pscale = 2 - @mult;

1個だと物足りないのでPoint Replicateで3つに増やす。Attributeを引き継ぐのを忘れないように。

f:id:godofsuama:20201002175035p:plain

その後Copy to Pointsをする。

f:id:godofsuama:20201002175120p:plain

POP

f:id:godofsuama:20201002180415p:plain

POP Source

EnumerateでPointに@idを作成。

Point VOPでVelocityとmassをランダムに作成

Velocityは早いやつが何個かあり、それ以外はそんなに早くないとなるように調整。

f:id:godofsuama:20201002175315p:plain

f:id:godofsuama:20201002175409p:plain

POP Sim

POPシムはほぼデフォルトの状態。

f:id:godofsuama:20201002175526p:plain

POP SourceのAdd Inherited Velocityを使用してvにランダムを追加

f:id:godofsuama:20201002175620p:plain

POP Dragを少々かける。

f:id:godofsuama:20201002175650p:plain

POPの後でRetimeをかける。おまじない。

f:id:godofsuama:20201002175804p:plain

f:id:godofsuama:20201002175824p:plain

Pyro Source

f:id:godofsuama:20201002180334p:plain

Point Replicate

Point ReplicateでPointを増やす。

Point Replicateは、Nかvがあるとその方向を向いた状態で複製することができる。ライン形に複製するときに便利

ShapeをLineにし、OrientationをZX Plane

CenterのZを-0.5にすると最初のポイントから後ろに並ぶ。

Uniform Scaleで並ぶ長さを決め、Quasi-Stratified Sampligのチェックを外すと均等に並ばなくなる。

f:id:godofsuama:20201002180026p:plain

f:id:godofsuama:20201002180048p:plain

さらにPoint Replicateを使用し、今度はSphere上にPointをかさ増しする。

1,2回めどちらも、Copy Source Attributesのチェックを忘れないように。

f:id:godofsuama:20201002180458p:plain

ageで消す

数が多すぎるのでageで消す。 f:id:godofsuama:20201002180617p:plain

Pyro Attributes

Pyro Sourceでアトリビュートの初期値を設定。

f:id:godofsuama:20201002180709p:plain

Point Vopでageを元にMultiply

f:id:godofsuama:20201002180818p:plain

Attribute Noiseでノイズを追加 f:id:godofsuama:20201002181029p:plain

f:id:godofsuama:20201002180855p:plain

どちらもAddにはしない。Addにすると局所的に非常に高い値などが生成されてPyroのシムがぶっ飛んだりする。

Point VelocityでCurl Noiseを追加

f:id:godofsuama:20201002181012p:plain

Volume Rasterize

f:id:godofsuama:20201002181132p:plain

Pyro Sim

f:id:godofsuama:20201002181223p:plain

BBOX

今回はSparse Solverを使用しているが、

爆発はちょっとの調整でかなり範囲が広がってしまうことがあるためBBOXを作成して範囲を制限している。

DOP

f:id:godofsuama:20201002181431p:plain

Smoke Object

f:id:godofsuama:20201002181506p:plain

Boundry ConditionsのYをClose Belowにしてもいいが、Ground Planeを敷いているので設定していない。

Volume Source

f:id:godofsuama:20201002181918p:plain

  • burnをflameに変更し、OperationをMaximumに。
  • temperatureのOperationをPullにし、Acceleration StrengthとDeceleration Strengthを設定。
  • vをvelに設定、Scaleを弱めにしてAdd
  • burnをdivergenceにし、Scaleを調整。Use Timestepをオフに。
Operation : Maximum

毎フレームの追加時にすでにより高い値がBoxel内に合った場合は追加しなくなる。どんどんSourceが追加されるのを防ぐ。

Operation : Pull

Target Fieldを毎フレーム押し出す。Acceleration StrengthとDeceleration Strengthで強さが決まる。

今回の設定では、temperatureが押し出されることで外へ広がっていくような感じになる。細いパーティクルからエミットするとよくわかる。

Use Timestep

DOPの計算が24fps基準らしいので、オンだと24fpsの際に実際のScaleが等倍になる。内部的に勝手にMultiplyされる感じ。

今回は24fpsなのでほぼ関係ない。

Divergence

ざっくり言うと、+の値で膨張し、-の値で縮小する。

Pyro Solver
Resize

動きが早い場合は、ある程度上げる。

f:id:godofsuama:20201002190807p:plain

f:id:godofsuama:20201002190911p:plain
Paddingが十分確保されている場合

f:id:godofsuama:20201002191000p:plain
Paddingが足りない場合

足りないとコンテナに引っかかって段差ができてしまう。

Simulation Tab

f:id:godofsuama:20201002191356p:plain

Sparse Solverは従来のGravity Forceの計算ではなく、Ambient TempとReference Tempで浮力が決まる。

この部分はK(ケルビン)表記なので、℃表記になおす場合は以下の計算で直す。

K=℃ + 273.15
℃=K - 273.15

Advection-Reflectionを使用すると計算速度の低下と引き換えによりディテールが残るようになる。

Flame Tab

flame field(burn)から生成されるFieldと生成の仕方の制御

f:id:godofsuama:20201002191811p:plain

Shape Tab

Dissipationで煙を消しつつ、小さなTurbulenceをかけている。

TurbulenceはControl Fieldと併用しないとずっとぼこぼこしたタービュレント感が残ってしまうので注意。

f:id:godofsuama:20201002192133p:plain

Micro Solvers

f:id:godofsuama:20201002183526p:plain

Speed Fieldを作成し、Disturbance等のMaskに使用。

Speed Field

f:id:godofsuama:20201002184016p:plain

Gas Match Fieldでvelと同じ設定のSpeed Fieldを作成

f:id:godofsuama:20201002184057p:plain

Gas Analysisでvelのlengthを計算し、Speed Fieldに格納 f:id:godofsuama:20201002184139p:plain

Speed Field(別手法)

Fieldが増えるとメモリ使用量も増加するため、Fieldを増やしたくない場合

デフォルトのControl Fieldはスカラーしか指定できないため

以下のようにMicro Solver内の該当箇所のBindのTypeをvectorにし、lengthノードを間に挟めばControl Fieldにvelを指定することができ、Fieldを増やさなくてよくなる。

f:id:godofsuama:20201002212815p:plain
Gas Disturbの場合

f:id:godofsuama:20201002212738p:plain
Gas Turbulenceの場合

Gas Disturb (Rotate)

いつついたのかわからないが、Rotational Forceにチェックを入れる。

チェックを入れるとDisturbance Fieldがvelの強さを変えるのではなく、velの向きを変えるように作用する。

velの強さを維持しつつランダムな向きへvelを変更できる。

この設定の際にStrengthを上げすぎると上昇する力などの本来のvelの効果が消えてその場でぐちゃぐちゃしてるようになってしまうため上げ過ぎには注意する。

Block-Basedの設定時は、ワールド空間でノイズを生成する。Base Block Sizeはその際の一番大きいブロックの大きさ。Voxel Size以下のノイズは作れない。

f:id:godofsuama:20201002184432p:plain

f:id:godofsuama:20201002184633p:plain

f:id:godofsuama:20201002184647p:plain

Gas Disturb

Rotational Forceをオフにし、ModeをContinuousに設定。

Continuousの場合は、Voxelごとにノイズが変わるので一番小さいノイズを追加することができる。やりすぎるとわしゃわしゃする。

作例はちょっとわしゃわしゃしすぎた気がする…

VoxelごとのノイズのためVoxel Sizeの影響を受けやすく、高解像度にした場合にはStrengthを下げないとめちゃめちゃ細かいつぶつぶが発生する。

f:id:godofsuama:20201002185338p:plain

f:id:godofsuama:20201002185357p:plain

Gas Vortex Confinment

発生した渦を維持する力を追加する。いつも最後に下げがちで効果の程がなんとも言えない。

Gas Turbulence

全体にかかるTurbulence。大きいのと小さいのを作ることが多い。

強すぎるととてもTurbulenceが出るので、Control Settingsで適応範囲を決めること。

Post

はじめに、でもあるようにこれ以降はMatt Puchalaさんのサンプルの簡略実装になってます。

f:id:godofsuama:20201002195445p:plain

Cache

DOP Import Fieldで必要なFieldをSOPへ読み込み、

f:id:godofsuama:20201002192715p:plain

Pyro Post ProcessノードでVDBをにしてキャッシュする。

Apply LookをオフにすることでVDB変換と圧縮処理だけ使用する。

velをレンダリングで使用するのでResampleし、各Fieldは16bit Floatの状態のFieldを保存する。

f:id:godofsuama:20201002192742p:plain

f:id:godofsuama:20201002192802p:plain

Scatter Field

temperatureからレンダリングで使用するScatter Fieldを作成する。

f:id:godofsuama:20201002193117p:plain

temperatureを分離し、VDB ActivateでBounding Boxを拡張する。

f:id:godofsuama:20201002193221p:plain

VDB SmoothでTemperatureをぼかしたものを3つくらい用意。画像合成のグローの作り方と同じ。

f:id:godofsuama:20201002193259p:plain

VDB CombineのMaximumで3つを合体

f:id:godofsuama:20201002193407p:plain

f:id:godofsuama:20201002193420p:plain

temperatureからscatterに名前を変更。

Mergeで全部のFieldを1つにまとめる。

f:id:godofsuama:20201002193608p:plain

Sharpen Density Field

Densityとそれ以外を分離

f:id:godofsuama:20201002195551p:plain

DensityにVolume Convolveをかける

f:id:godofsuama:20201002195702p:plain

このページの処理をVolumeに対して行っている。

Volume WrangleでSharpにしたものとしていないものをScatter FieldのRangeで混ぜる。

f:id:godofsuama:20201002195941p:plain

//import field
float scatter = volumesample(2, "scatter", @P);
float orgDensity = volumeindex(1, "density", set(i@ix, i@iy, i@iz));
float sharpDensity = lerp(orgDensity, @density, ch("shMult"));

//scatter fit range
float range = fit(scatter, ch("scatOldx"), ch("scatOldy"), ch("scatNewx"), ch("scatNewy"));

//Mix density
@density = lerp(orgDensity, sharpDensity, range);

Shader

f:id:godofsuama:20201002200518p:plain

Density

Scatter FieldをRemapしたものをDensity FieldにMultiplyし、Pyro ShaderのDensityへつなぐ。

f:id:godofsuama:20201002201505p:plain

Emit Color

Rangeを調整してRampで色付けし、Pyro ShaderのEmit Colorへ。

Scatter Flame

Scatterにpowで1.4くらいをかけて値をしぼりつつ、それぞれをMultiplyしたのち加算する。

その後、調整したDensityをMultiplyしてPyro ShaderのEmitへつなぐ。

f:id:godofsuama:20201002201316p:plain

Ce

Densityを再度RemapしたものとCeをMultiplyして再度Ceへつなぐ

f:id:godofsuama:20201002201642p:plain

f:id:godofsuama:20201002201658p:plain