intersect関数で色々しようの話。

# 自己紹介
軽い自己紹介からする流れがあるので軽い自己紹介を。
業界3年目のHoudinistを名乗る何かです。普段はゲームエンジンを使って色々しています。最近CGworldに記事書きました。
ここ半年ぐらいは絵を描くのを趣味にしていますが、Houdiniが好きです。結婚しようSideFX。

# 本題
さて、本題に入りましょう。本日はintersectの話です。
公式の超詳しい解説はこちら https://www.sidefx.com/ja/docs/houdini/vex/functions/intersect.html

この関数で何出来るかザッと概要を話すと、
「指定した位置から指定した方向を見た時に最初に当たる位置等を出す」
って感じです。

いや意味分からんぞってなるので、実際にやってみましょう。

PointWrangle出して、0入力に参照するポイントの位置、1入力に対象となるポイントを入れて
```
vector dir=set(0,10,0);
vector pos,uvw;

intersect(1,@P,dir,pos,uvw);

@P=pos;
```

と入れると、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545265/1055b371-986b-7424-863a-a1dc6ca295a9.png)
こんな感じになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545265/51da4ee3-35a5-af46-653f-da75b45e0181.png)
わかりやすく移動したのを繋げるとこう。

指定した方向に移動しているのがわかる。
minpos、xyzdistでやるとこうは行かないので便利だ。

ちなみに、変数作ってintersectの関数を入れると当たらなかったポイントには-1が入るので参考になる。
最大距離はDirで決めた値(この場合は10)なので、無限遠まで見たいとかは無理。99999999とかにすれば実質無限遠になるけど、重かったりそもそも必要なかったりなので、程々に。

ここまでは皆さんよく紹介しており、intersect関数を使って面白い事出来ないかなーと思ったので、レンダラ的な何かを作ってみる。

ここからは「え？それ何に使えるの？」は禁句です。電波だって最初は無用の長物だったんだ。

# 今回作る物の紹介
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545265/b7b1164b-088a-55df-1a52-29abdc9cea98.png)
こんな感じの屈折が出来る物を作ります。
出力に関しては知りません。多分ベイク使えばイケるんじゃないかな。

### 注意
・論文とか参考にしてる訳じゃないので色々間違ってます。「っぽい物」です。
・主題は「完璧なレンダリングをするじゃなく、intersect関数を使って面白い事をする」です。
・もう一度言いますが、何に使えるかは貴方の発想次第です。関数の可能性に気づけたら幸いです。
・最後に、コレが出来たからって就職が有利になるとか全然無いので、勉強に「効率が悪い」とか言ってる人は他の記事見ましょう。無駄を気にするタイプの人には無駄な時間です。

## ネットワーク
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545265/9aa25a01-be74-05ba-1a55-710c0b62a25a.png)

### 簡単な概要
1・カメラとなるGridのポイントから撮影方向に光を飛ばす
2・オブジェクトに当たったら、そのオブジェクトの色と法線を取得する
3・その法線方向から屈折率を計算、結果を元に次の方向を決める
4・繰り返す

です。
透明かどうかは今回判別していません。どうやって屈折させてるかというと、透明の場合得た色が黒で、非透明の物に当たったら色を取得するので、透過してるように見えます。
また、オブジェクトに当たらない部分は色を持たないので、透過後の光が新しく色を取得する事も無く、色が維持されます。

## 被写体の準備
被写体の準備が思った以上に大きいですが、以下の要素を足してるだけです。

・オブジェクトの法線を計算で使うので、Subdivide等を使用して細かくしておく。
・透過するオブジェクトの色は黒(0,0,0)にしておく。
・透過しないオブジェクトはAttribute From map等を使用してPointにCdを渡しておく。
・PolyFrameを使用し、PointにNを与えておく。

## カメラとなるGrid
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545265/f3d88268-c805-0176-409b-03caa858ca9a.png)
こんな感じで配置します。
一番右がカメラのGrid、ワイヤーフレーム(すごい細かい)が被写体です。
Gridは撮影時のカメラの解像度です。
レンズの曲率等は計算していないので、レンズ的な感じではなく、距離が離れても大丈夫なスキャナーのイメージです。

このGridに与えるアトリビュートは
・v@rayangle (撮影する方向と距離)
・i@id (撮影後に色を与える為の番号)
の2つです。使用目的は書いてある通り。

# オブジェクトへの衝突の確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545265/421bef3e-b92b-8b1c-8b84-5e603e141764.png)
このCaptureノードでやってる事は、intersect関数を使用してオブジェクトに当たったかどうかを確認している。

当たった場合
・当たった場所に計算箇所を移動。
・色を取得。

当たらなかった場合は次の位置に移動している。

## 法線
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545265/ab7f388a-0820-1368-1c36-4d94e94d513c.png)
法線をAttribute Transferを使用して元のオブジェクトから持ってくる。

## 屈折の計算
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545265/dd9c7071-2b28-46ac-f891-b06515ecc858.png)
屈折を計算する。
ここで使っているのはfresnel関数です。
公式による超詳しい解説はこちら=https://www.sidefx.com/ja/docs/houdini/vex/functions/fresnel.html

簡単に言うと、屈折とか色々計算できる関数です。
可能性を無限に感じてる。

もしオブジェクトに光が当たった場合(i@hit=1)、移動方向を更新する。
屈折した結果が正規化されている為、最初に決めた移動量になるよう増幅します。

ここでは関数を使ってるだけなので、そんなに説明する事は無いです。

ここまでで1回の計算が出来た。
最後のfresnelで次の移動方向を更新している為、for-eachで繰り返せば、その分の屈折を計算出来る。
現在は12回計算している。豚が綺麗に見えるのがそのぐらいだった。
レンダリングした事ある人なら、Refract Limitで通じるかと思う。

## 計算結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545265/21c084aa-4e47-4a8b-d974-a9aeaa2e1a54.png)
実際にポイントを移動させているので、こんな感じに広がる。これだけでもかなり面白いので、何か作品にできるかもね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545265/4c74bfb9-6849-cd72-5d22-52f61e8d5ce9.png)
このポイントから最初に設定したIDを使って色を転送する。
Gridは最初に設定したGridと解像度を同じにしている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545265/8ccb9791-daa0-0c33-51fc-4e2c247e4feb.png)
これで画像として見れるようになった。

# おわりに
今回はレンダリングらしき何かを作ってみた。
intersectは移動だけに使えるんじゃないよって事とか、VEXおもしれぇ～～って思ってくれたら幸いです。

あと、今回のでは屈折らしき事が出来てるけど、屈折対象とかが雑だったり、テクスチャの読み込みがゴリ押しだったりなので、テクスチャの読み込みや透明対象を選べるようにしたい。
その辺はこれをベースに改造していく事になるだろう。ゆくゆくね。

最後に、シーンを添付します。
いつもの事ですが、悪用や自作発言は厳禁です。
https://1drv.ms/u/s!Al-gq6RIZjNr2FJOpzbUUBB0sAl1?e=WohJ2d

という事で記事終わります。閲覧ありがとうございました。