A Practical Microcylinder Appearance Model for Cloth Rendering の実装(2)

前回からの続きです。

ushiostarfish.hatenablog.com

If you like english version, Please check this

ushiostarfish.hatenablog.com

シェーディングモデル

本論文では、以下の図のように2本のたて糸とよこ糸が図のように直行している様子をモデル化します。

f:id:ushiostarfish:20181229174211p:plain

※Fig. 2 IMAN SADEGHI, OLEG BISKER, JOACHIM DE DEKEN, HENRIK WANN JENSEN, UC San Diego, "Practical Microcylinder Appearance Model for Cloth Rendering"

図を見て分かる通り、明らかに たて(経)糸とよこ(緯)糸で見えている面積が異なります。これをシンプルに反映し、以下の式で出射放射輝度を定義します。

 
\displaystyle {
L_{ r }\left( \omega _{ r } \right) =a_{ 1 }L_{ r,1 }\left( \omega _{ r } \right) +a_{ 2 }L_{ r,2 }\left( \omega _{ r } \right) 
}

ここで、 a_1, a_2 は単純にパラメーターです。線形補間なら、aは一つでいいのではないか?とも思われるのですが、Fig. 2の一番左のように隙間が存在しているケースでは、 a_1 + a_2 は必ずしも 1になりません。そのためこのパラメーターは2つ存在しています。逆に密に糸が織られているケースでは、 a_1 + a_2=1 になります。

では個別の  L_{ r,j }\left( \omega _{ r } \right) ですが、こちらは以下のように定義します。

 
\displaystyle {
L_{ r,j }\left( \omega _{ r } \right) =\frac { 1 }{ N_{ j } } \sum _{ t }^{  }{ \int _{ \Omega  }^{  }{ L_{ i } } f_{ s }\left( t,\omega _{ i },\omega _{ r } \right) \cos { \theta _{ i }d\omega _{ i } }  } 
}

※ もうBRDFを考えており、ここで  \Omega は半球です。

ここで  N_{ j }は何かというと、接線のサンプル数になります。というのも、織布の糸を考えたとき、少なくともどちらか1本は波打っていると考えられるため、その糸の傾き具合をそれぞれ別に評価して平均する、ということになります。

f:id:ushiostarfish:20181229180255p:plain

※ Fig. 12, Polyester Satin Charmeuse fabric IMAN SADEGHI, OLEG BISKER, JOACHIM DE DEKEN, HENRIK WANN JENSEN, UC San Diego, "Practical Microcylinder Appearance Model for Cloth Rendering"

 f_{ s }\left( t,\omega _{ i },\omega _{ r } \right) については、前回の糸モデルそのままです。 サンプルを具体的にどうするのかは、論文には言及がありませんでした。今回は横着して、論文にある Table II の制御点をそのままサンプルポイントとすることにしました。これでも論文の画像と良好な一致を確認しました。しかし厳密には確率的に解いたりすると良いのかもしれませんが、最終結果により良い結果につながるかは疑問です。

以上で全体の流れは網羅できましたが、本論文ではより測定結果に近づけるため、さらに2つの調整を提示しています。それは "Shadowing and Masking"と"Reweighting" です。これについて見ていきます。

Shadowing and Masking

たて糸とよこ糸が直行している今回のようなシェーディングにマッチするShadowing, Maskingとして、 本論文では、それぞれ以下のように定義されています。

 
\displaystyle {
M\left( t,\omega _{ r } \right) =max\left( \cos { \phi _{ r } } ,0 \right) \\ M\left( t,\omega _{ i } \right) =max\left( \cos { \phi _{ i } } ,0 \right) 
}

これを見てすぐに分かることとして、それぞれ \phi _{ i }, \phi _{ r } にのみ依存する点があります。これの理由は、論文のFig 13がわかりやすいです。

f:id:ushiostarfish:20181229221524p:plain

※ Fig. 13, 中, 右の図 Polyester Satin Charmeuse fabric IMAN SADEGHI, OLEG BISKER, JOACHIM DE DEKEN, HENRIK WANN JENSEN, UC San Diego, "Practical Microcylinder Appearance Model for Cloth Rendering"

左の図を見ると、グレージング角でも糸が糸に隠れているところは存在しません。これは糸の方向と同一方向に傾いているからですね。 ところが右の図では糸の方向に対して横方向に傾いています。この場合は隣の糸に邪魔されて糸が隠れています。すなわちこの方向にのみShadowing, Maskingを考慮すれば良いだろう、ということになります。

では次になぜShadowing, Maskingは  \cos { \phi _{ r } } なのでしょうか。 これはシリンダーが横に並んだときの遮蔽を考えています。以下のようにシリンダーが横に並ぶと、手前の白のシリンダーが奥のグレーのシリンダーの一部を遮蔽します。

f:id:ushiostarfish:20181229223416p:plain

ではその見えている量はどのくらいかを、図に書き込んでみます。円筒の半径は0.5だとします。

f:id:ushiostarfish:20181229225827p:plain

そう、見えている量はまさに  \cos { \phi } であったのです。

Shadowing, Masking の相関

もし入射と出射のShadowing, Maskingに全く相関が無い(=無相関)と仮定すると、Shadowing & Masking関数は以下のような個別の関数の単純な積の定義が用いられます。

 
\displaystyle {
M_{ no-correlation }\left( t,\omega _{ i },\omega _{ r } \right) =M\left( t,\omega _{ i } \right) M\left( t,\omega _{ r } \right) 
}

しかしこの仮定にはよく知られた問題があって、例えば  \omega _{ i } = \omega _{ o } のようなケースを考えてみます。Shadowing, Maskingはどちらも表面の遮蔽具合を表現するものであるため、入射と出射が等しいのであれば、その見えている領域は完全に同一であるはずです。つまり、遮蔽に関して言えば実際には片方だけ作用させれば良いはずなのにもかかわらず、上記の定義ではそれの積、つまり二乗分の遮蔽が計上されてしまうのです。これは相関の仮定がうまく動作しないわかりやすい例です。 本論文ではこれの対策として、Michael Ashikhmin, Simon Premoze, Peter Shirley, "A Microfacet-based BRDF Generator" で提案されている方法を使っています。

このアイディアはシンプルで、入射と出射が等しいような強い相関のあるShadowing & Masking関数を、無相関とは対照的に、

 
\displaystyle {
M_{ correlation }\left( t,\omega _{ i },\omega _{ r } \right) =max\left( M\left( t,\omega _{ i } \right) ,M\left( t,\omega _{ r } \right)  \right) 
}

と定義します。これは直観的にはShadowingの領域がMaskingの領域を包含している、もしくはMaskingの領域がShadowingの領域を包含していたので、遮蔽は大きい方に合わせれば良い、というイメージだと思います。

最後に無相関の関数と、強い相関のある関数を、"入射と出射の類似度" で線形補間します。

 
\displaystyle {
M\left( t,\omega _{ i },\omega _{ r } \right) =\left( 1-u\left( \phi _{ d } \right)  \right) M\left( t,\omega _{ i } \right) M\left( t,\omega _{ r } \right) +u\left( \phi _{ d } \right) max\left( M\left( t,\omega _{ i } \right) ,M\left( t,\omega _{ r } \right)  \right) 
}

ここで、"入射と出射の類似度" は、 \phi _{ i } \phi _{ r } の差である、 \phi _{ d } を引数に取るガウス関数を用いて、

 
\displaystyle {
u\left( \phi _{ d } \right) =\left( -\frac { \phi _{ d }^{ 2 } }{ 2\sigma ^{ 2 } }  \right) 
}

を使います。 \sigma については、15度から 25度となっていたため、ここではひとまず 20度で実装しました。ただ、15度や25度になったところでそれほど大きくは変わらないでしょう。

これにより、個別のシェーディングモデルは以下のように書き直されます。

 
\displaystyle {
L_{ r,j }\left( \omega _{ r } \right) =\frac { 1 }{ N_{ j } } \sum _{ t }^{  }{ \int _{ \Omega  }^{  }{ L_{ i } } f_{ s }\left( t,\omega _{ i },\omega _{ r } \right) M\left( t,\omega _{ i },\omega _{ r } \right) \cos { \theta _{ i }d\omega _{ i } }  } 
}

Reweighting

Reweightingは、まず論文 Fig 13 を見てみましょう。

f:id:ushiostarfish:20181230124255p:plain

※ Fig 13 左 IMAN SADEGHI, OLEG BISKER, JOACHIM DE DEKEN, HENRIK WANN JENSEN, UC San Diego, "Practical Microcylinder Appearance Model for Cloth Rendering"

まず青色の糸に着目してみると、どうにも真ん中は青色が強く、端に行く(=グレージングアングルに近づく)ほどに相対的に青が弱くなっているのがわかります。 これは何故かと考えてみると、糸が傾くことで見かけの長さ(=視点方向へ投影した長さ)が小さくなっているからではないでしょうか。(=視点方向へ投影した長さ)が小さくなっているからではないでしょうか。 さらにオレンジの糸に着目してみると、全範囲で変化はなく均一です。これは端でもオレンジの糸の見かけ上の長さが変わっていないからでしょう。 このことから見かけ上の長さの変化は、 \psi にのみ依存するということもわかります。

※ところで別な見方をすると、青色が弱く見えるのはオレンジの糸の密度が上がったからではないか?という考えも浮かびます。しかしオレンジの糸の密度が上がったのは見かけ上の青の糸が短くなったことに起因するわけで、結局同じことを違う視点で見ただけのようです。

イメージとしては以下のようなかんじでしょうか。

f:id:ushiostarfish:20181230134818p:plain

さながら、マイクロファセット理論でよく出てくる可視法線分布のようです。

 \psi は最初の座標系の説明には登場しませんでした。これも合わせて確認します。論文のFig. 14を確認しましょう。

f:id:ushiostarfish:20181230125716p:plain

※ Fig 14 IMAN SADEGHI, OLEG BISKER, JOACHIM DE DEKEN, HENRIK WANN JENSEN, UC San Diego, "Practical Microcylinder Appearance Model for Cloth Rendering"

わかりにくいところはなく、単に糸と同一方向と、布法線が作り出す面上の角度です。

では見かけ上の長さといえば、当然  \cos \psi です。論文ではこれを使って、以下の重みを定義しています。

 
\displaystyle {
P\left( t,\omega _{ r } \right) =max\left( \cos { \psi _{ r } } ,0 \right) \\ P\left( t,\omega _{ i } \right) =max\left( \cos { \psi _{ i } } ,0 \right) 
}

偶然にも Shadowing, Masking と同一の式になっています。ちなみに入射と出射両方向考えているのは、見る方向だけでなく、光を受ける方も同様の現象がおこり、見かけ上の長さ長いほうが受光量が大きくなり、結果寄与がおおきくなるだろう、という考えがあるからです。しかしながら、入射のほうについては、LTE放射輝度の密度変化を考慮した  \cos \theta_i 項があるわけなので、両方向考えるのはいささか過剰な気もしますが、 \psi にのみ依存する P 項とは少し立ち位置が違うのかもしれません。

論文ではShadowing, Maskingとアイディアも似通っているからか、入射と出射の組み合わせについても、同様の以下の定義を用いています。

 
\displaystyle {
P\left( t,\omega _{ i },\omega _{ r } \right) =\left( 1-u\left( \psi _{ d } \right)  \right) P\left( t,\omega _{ i } \right) P\left( t,\omega _{ r } \right) +u\left( \psi _{ d } \right) max\left( P\left( t,\omega _{ i } \right) ,P\left( t,\omega _{ r } \right)  \right) 
}

ここで、 \psi_d は、 \psi_r - \psi_i となります。  \phi _d と同様の考え方ですね。

以上を重みを式に付け加えて以下のようにシェーディングモデルを書き直します。

 
\displaystyle {
L_{ r,j }\left( \omega _{ r } \right) =\frac { 1 }{ Q } \frac { 1 }{ N_{ j } } \sum _{ t }^{  }{ \int _{ \Omega  }^{  }{ L_{ i } } f_{ s }\left( t,\omega _{ i },\omega _{ r } \right) M\left( t,\omega _{ i },\omega _{ r } \right) P\left( t,\omega _{ i },\omega _{ r } \right) \cos { \theta _{ i }d\omega _{ i } }  } 
}

正規化項として  Q が増えています。今回追加した P 項は重みを調整するための恣意的なスケールを行うわけですので、それ単体では重みの和が1にならず、エネルギー全体にスケールを掛けてしまう恐れがあるためです。ここはShadowing, Maskingと違うところですね。  Q は以下のように求めます。

 
\displaystyle {
Q=\frac { a_{ 1 } }{ N_{ 1 } } \sum _{ t }^{  }{ P\left( t \right)  } +\frac { a_{ 2 } }{ N_{ 2 } } \sum _{ t }^{  }{ P\left( t \right)  } +\left( 1-a_{ 1 }-a_{ 2 } \right) a_{ 2 }\cdot n
}

ちょっとややこしいことになっています。 ここでReweightingを加える前では、全体から見ると個別のサンプルはどういう重みになっていたか?を図にしてみます。

f:id:ushiostarfish:20181230142635p:plain

この図では外側の箱がちょうど単位面積になっており、まずパラメーター  a_1, a_2 によって二分されます。その後、それぞれの糸ごとに一つ以上のサンプルが存在し、それぞれ均一な重みが割り振られます。こう考えると個別のサンプルの重みは割り当てられた面積ということになります。

ということは結局のところ今回追加する  P は、この個別の面積をそれぞれスケールした と考えられます。スケール後の面積の和は1になりませんので、結局スケール後の面積の和で除算して正規化すれば良いことがわかります。 ちなみに最後の項  \left( 1-a_{ 1 }-a_{ 2 } \right) a_{ 2 }\cdot n a_{ 1 } + a_{ 1 } \lt 1 のケースを考慮しており、糸が存在していない部分はとりあえず法線に合わせた投影領域に重みを割り振ったと考え、残りを埋めています。

実装

実装は素直にストレートフォアードにやったつもりです。結構長いので埋め込まずリンクにしています。

microcylindercloth · GitHub

material · GitHub

モデル

シェーディングモデルは用意できましたが、絵を出すにはやはりモデルが必要で、また論文の絵をなるべく再現したかったので、それに近い3Dモデルがほしいです。ちょうどHoudini 17には新しいシミュレーションモジュール、Vellum が入ったそうなので、それを試してみることにしました。

※自分のMSI ノートでは、NahimicのせいでHoudini17がクラッシュしたり、Houdini 17 crashing constantly - General Houdini Questions - od|forumOpenCL の初期化でエラーでて設定を調整したりなどちょっと問題もありましたが・・・[Solved] OpenCL setup for 17? | Forums | SideFX 環境依存っぽかったのでこれについてはあまりここでは深入りしないことにします。

VellumはMatthias Müller, Bruno Heidelberger, Marcus Hennix, John Ratcliff, "Position Based Dynamics" をベースとしたソルバーのようで、拘束ベースで設定を行います。またSopで完結できるようになっていたりとかなり楽に使えてとても良かったので、ついでに紹介してみます。

Vellum

まずは地面を作ります。TubeとGridをただ並べるだけにします。

f:id:ushiostarfish:20181230150113p:plain

次に上に重ねる布を適当な分解能で準備します。ただ後に接ベクトルを計算のため、uvflattenを使ってpointにuvを追加しておきます。

f:id:ushiostarfish:20181230150315p:plain

次にConstraintを設定します。Clothはプリセットがあるのでそれを選ぶと楽です。

f:id:ushiostarfish:20181230150557p:plain

BendのStiffnessを調整すると、布の曲がりにくさを調整可能です。パラメーターはそれほど多くはないので狙った見た目にならない場合はちょっといじってみると良いでしょう。ただ、シミュレーションに詳しい人に聞いてみると、可能な場合は、実際手元で布をいじってみてどういう形になるのか?を試してみたほうが良い というのを聞きました。シミュレーションだけしかやっていないと、シミュレーションは正しいが、アプローチが間違っている場合に気づかないこともあるそうです。

真ん中をnullにつなぐと、拘束を確認することもできます。

f:id:ushiostarfish:20181230151232p:plain

心臓部、Vellum Solverにつなぎます。

f:id:ushiostarfish:20181230151406p:plain

Forces/Friction/Static Threshold などを調整して摩擦の具合を調整できます。 また、拘束が伸びすぎて収束していないようなケースでは、Solver/Substeps などを上げると良いでしょう。

あとはタイムラインをスタートすれば、

f:id:ushiostarfish:20181230151738g:plain

ね?簡単でしょう?

あとは適当なフレームで、Smoothと、Subdivideをかけてちょっと綺麗にしつつ File Cacheを使ってobj書き出しを行います。

f:id:ushiostarfish:20181230152009p:plain

接ベクトルは実行時に計算しても良いのかもしれませんが、今回はHoudiniのpolyframeパッチを使って事前計算しました。

f:id:ushiostarfish:20181230152645p:plain

※ただ頂点単位の計算になるので、実際には最後にプリミティブで接ベクトルがそれぞれ直交するように調整しています。

以上でモデルは準備完了です。

結果

シーンは以下のようにしました。(いや、正確には論文の絵に近づくように配置してみたところこうなりました、というのが実情です)

f:id:ushiostarfish:20181230153241p:plain

ここでは論文のTable Ⅱにあるパラメーターを使って再現してみます。

Linen Plain

f:id:ushiostarfish:20181230154032p:plain

 \eta Thread A  k_d  \gamma_s (deg)  \gamma_v (deg)  a Tangent Offsets (deg)
1.46 Both (0.2, 0.8, 1.0) * 0.3 0.3 12 24 0.33 -25, 25

Silk Crepe de Chine

f:id:ushiostarfish:20181230154233p:plain

 \eta Thread A  k_d  \gamma_s (deg)  \gamma_v (deg)  a Tangent Offsets (deg)
1.345 Flat (1.0, 0.95, 0.05) * 0.12 0.2 5 10 0.75 -35, -35, 35, 35
1.345 Twist (1.0, 0.95, 0.05) * 0.16 0.3 18 32 0.25 0, 0

Polyester Satin Charmeuse

f:id:ushiostarfish:20181230154800p:plain

 \eta Thread A  k_d  \gamma_s (deg)  \gamma_v (deg)  a Tangent Offsets (deg)
1.539 Flat (1.0, 0.37, 0.3) * 0.035 0.1 2.5 5 0.9 -32, -32, -18, 0, 0 , 18, 32, 32
1.539 Twist (1.0, 0.37, 0.3) * 0.02 0.7 30 60 0.1 0, 0

Polyester Satin Charmeuse (Back-side)

f:id:ushiostarfish:20181230155451p:plain

 \eta Thread A  k_d  \gamma_s (deg)  \gamma_v (deg)  a Tangent Offsets (deg)
1.539 Flat (1.0, 0.37, 0.3) * 0.035 0.1 2.5 5 0.67 -30, -30, 30, 30, -5, -5, 5, 5
1.539 Twist (1.0, 0.37, 0.3) * 0.02 0.7 30 60 0.33 0, 0

Silk Shot

f:id:ushiostarfish:20181230155850p:plain

 \eta Thread A  k_d  \gamma_s (deg)  \gamma_v (deg)  a Tangent Offsets (deg)
1.345 Dir 1 (0.1, 1.0, 0.4) * 0.2 0.1 4 8 0.86 -25, -25, 25, 25
1.345 Dir2 (1.0, 0.0, 0.1) * 0.6 0.1 5 10 0.14 0, 0

Velvet

なぜかVelvetに関しては結果が論文の写真とあまり合いませんでした もしかすると論文のはSiggraph ロゴを出すためにライティングや法線マップを調整しているのかもしれません。

f:id:ushiostarfish:20181230160224p:plain

 \eta Thread A  k_d  \gamma_s (deg)  \gamma_v (deg)  a Tangent Offsets (deg)
1.46 Dir 1 (0.05, 0.02, 0.0) * 0.3 0.1 6 12 0.5 -90, -50
1.46 Dir2 (0.05, 0.02, 0.0) * 0.3 0.1 6 12 0.5 -90, -55, 55, 90

論文 Fig. 24

f:id:ushiostarfish:20181230160515p:plain

Velvet以外については、無事再現することができました。

まとめ

レイトレ合宿6 ではベルベットのシェーディングをまがいなりにも導入していましたが、布のシェーディングについては正直ほとんど調べられておらず、やや不完全燃焼な印象があったので、一度ちゃんと調べてみたかったのもあり、ざっと調べた範囲で手の届きそうなところの A Practical Microcylinder Appearance Model for Cloth Renderingにチャレンジしてみました。ところがソースコードが入手できなかったのもあり、なかなか時間がかかってしまいました。

本手法は、決して洗練された方法でもないかもしれませんし、Mathematically well defined とも言いにくいかもしれません。しかし測定データに対して最小限の定式化を使い、Far Fieldだけとはいえ、かなり真実の味を感じる絵を実現しています。 何を重要とみなすか?というフォーカスの設定がここで肝だったのではないでしょうか。

一方で、エネルギー保存の問題や、シェーダの重さはまだ課題が多いですし、特にTangent Offsetsのパラメーターは直観的に設定するのは難しいと言わざるを得ません。また、布ではカメラが布にある程度近づくだけで詳細が見えてしまう実情もあり、さらなるクオリティアップのためには、Near Fieldの見た目をうまいことハンドリングするのは避けて通れない気もします。

布特性上、かなり毛髪などのレンダリングと理論が共通しているため、わりと幅広く知識がつながっている感触も得られました。ぜひこの分野に興味が湧いた方は調べてみると面白いのではないでしょうか。

謝辞

実装にあたって、Henrik W. Jensen 氏には、メールでいくつか質問に答えていただき、大きく理解を助けていただきました。本当にありがとうございました。

In implementing, Mr. Henrik W. Jensen have answered some questions by e-mail and helped me to understand well. Thank you so much.

参考文献

IMAN SADEGHI, OLEG BISKER, JOACHIM DE DEKEN, HENRIK WANN JENSEN, UC San Diego, "Practical Microcylinder Appearance Model for Cloth Rendering"

※ちなみに ACM Digital Library で課金すると、彼らのプレゼン映像が見れます。

Iman Sadeghi, "Controlling the Appearance of Specular Microstructures"

信州大学繊維学部, はじめて学ぶ繊維

Michael Ashikhmin, Simon Premoze, Peter Shirley, "A microfacet-based brdf generator"

Piti Irawan, "Appearance of Woven Cloth"

Wenzel Jakob, Adam Arbree, Jonathan T. Moon, Kavita Bala, Steve Marschner, "radiative transfer framework for rendering, materials with anisotropic structure"

Stephen R. Marschner, Henrik Wann Jensen, Mike Cammarano, "Light Scattering from Human Hair Fibers"

Eugene d’Eon, Guillaume Francois, Martin Hill, Joe Letteri, Jean-Marie Aubry, "An Energy-Conserving Hair Reflectance Model"

Bruce Walter, Stephen R. Marschner, Hongsong Li, Kenneth E. Torrance, "Microfacet Models for Refraction through Rough Surfaces"

Subrahmanyan Chandrasekhar, "Radiative Transfer"

Michael Ashikhmin, Simon Premoze, Peter Shirley, "A Microfacet-based BRDF Generator"

Matthias Müller, Bruno Heidelberger, Marcus Hennix, John Ratcliff, "Position Based Dynamics"