[#TouchDesigner] バックバッファを用いたGLSLの書き方

![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3132373430322f62633039666136362d363937342d636632642d383230342d3138373832653034323666632e706e67.png](https://qiita-image-store.s3.amazonaws.com/0/127402/0dd4ac2c-5c01-ae9b-8a5b-e4a084f48ae5.png)

この記事は、[TouchDesigner Advent Calendar 2017](https://qiita.com/advent-calendar/2017/touchdesigner) 23日目の記事です。

# はじめに
何の打ち合わせもなしに、前日の記事と内容が丸被りしました。(そんなことあるんですね...)
書き直すの面倒なので、そのまま掲載します。
ごめんなさい！！！

TouchDesignerでは、GLSLフラグメントシェーダを用いた画像の生成が可能です。
![2017-12-10_160250.png](https://qiita-image-store.s3.amazonaws.com/0/127402/cc16237b-e303-8d10-468b-8302e1594f1d.png)
上記画像のように、単一のGLSLフラグメントシェーダであれば、GLSL TOPノード1発で済むのですが、
人間とは欲深いもので、前フレームの計算結果を利用して次のフレームの描画をしたくなる時があります...

つまるところ、この[Lorenz Attractor](https://www.shadertoy.com/view/XddGWj)のように、
バッファを用いた描画をどうやってTouchDesigner上で実現するのか気になって夜も眠れませんでした。(昼寝てたけど)

本記事では、これを実現する方法を**雑に**解説します。

# 実装する内容
今回は、Shadertoyに掲載されている[2次元波動シミュレーション](https://www.shadertoy.com/view/Xsd3DB)をTouchDesigner上に移植します。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="en" dir="ltr">Wave Simulation <a href="https://twitter.com/hashtag/touchdesigner?src=hash&amp;ref_src=twsrc%5Etfw">#touchdesigner</a> <a href="https://twitter.com/hashtag/glsl?src=hash&amp;ref_src=twsrc%5Etfw">#glsl</a> <a href="https://t.co/MudSzoOI4l">pic.twitter.com/MudSzoOI4l</a></p>&mdash; Kodai Takao 🌊 (@m1ke_wazowsk1) <a href="https://twitter.com/m1ke_wazowsk1/status/939809339216240640?ref_src=twsrc%5Etfw">2017年12月10日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet" data-lang="ja"><p lang="und" dir="ltr"><a href="https://t.co/CtIonNNfab">pic.twitter.com/CtIonNNfab</a></p>&mdash; Kodai Takao 🌊 (@m1ke_wazowsk1) <a href="https://twitter.com/m1ke_wazowsk1/status/944256261100519425?ref_src=twsrc%5Etfw">2017年12月22日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<br>
リリースはこちらです。(CC License)
[WaveSimulationForTouchDesigner - GitHub](https://github.com/kodai100/TD_WaveSimulation/releases/tag/TD_WaveSimulationSample)
(TouchDesigner099 2017.15400)

# 波動シミュレーションの仕組み
波動シミュレーションの解説は、うしお先生の記事が非常にわかりやすいため、
こちらを参照していただきたいと思います。

- [波動方程式の立式から数値シミュレーションまで(1)](https://qiita.com/Ushio/items/e6a636cab156f440b70b)
- [波動方程式の導出(弦の運動)](https://qiita.com/Ushio/items/51158ce9cd8155f119d0)
- [波動方程式の数値解法](https://qiita.com/Ushio/items/0249fd7a5363ccd914dd)

過去にUnityで実装した例も掲載しておきます。
[Wave Simulation for Unity](http://creativeuniverse.tokyo/portfolio/?portfolio=wave-simulation)

ただし、今回の内容は波動シミュレーションを理解しなくても問題ありませんので、読み飛ばしていただいても結構です。

# TouchDesignerでのバッファの作り方
一度[Shadertoyプロジェクト](https://www.shadertoy.com/view/Xsd3DB)を見てみましょう。
BufAのGLSLコードは、BufAとBufBの計算結果を参照しており、
![2017-12-10_174955.png](https://qiita-image-store.s3.amazonaws.com/0/127402/2b12e53b-cacb-246b-1972-33150cc385e8.png)

BufBのGLSLコードは、BufBとBufAの計算結果を参照、
![2017-12-10_175014.png](https://qiita-image-store.s3.amazonaws.com/0/127402/a796ed95-13a4-662b-4612-7eeb26d33330.png)

最終的な描画処理ではBufAの計算結果を参照しています。
![2017-12-10_175027.png](https://qiita-image-store.s3.amazonaws.com/0/127402/39db8d3d-4275-c421-cc59-3fd9a939d13f.png)

TouchDesignerで同じバッファ機能を実現するためのキモは以下2つのノードを利用することです。

- GLSL Multi TOP (GLSL TOP)
- Feedback TOP

## GLSL Multi
GLSLコードを書くためのノードです。
複数の画像を入力に受けることができます。
今回の例はGLSL TOPでも同じ効果が得られますが、僕は宗教的にこちらを使います。

## Feedback
「指定されたノードの現在のフレームバッファを消去せず次のフレームに受け渡す」機能を持ったノードです。
つまり、これをうまく利用することで**次フレームに現在の計算結果を引き継ぐことができます**。

## つなぎ方
[Shadertoyプロジェクト](https://www.shadertoy.com/view/Xsd3DB)のBufAを実装する例を示します。

はじめに、Feedback TOPにConstant TOPを接続します。
このときのConstant TOPは、解像度を指定するためだけの機能を持っています。(Feedbackは接続元がないとエラーを吐くため渋々...)

次に、Feedback TOPのTarget TOPに、BufAのコードを実装したGLSL Multi TOPを指定します。

最後に、Feedback TOPの出力と、
画像には映っていませんがBuf BのFeedback TOPの出力を
GLSL Multi TOPの入力に接続します。
![2017-12-10_180054.png](https://qiita-image-store.s3.amazonaws.com/0/127402/f972b592-ff78-ee70-569b-19e6893b6e6d.png)

BufBや最終的な描画についても同様に接続すればOKです。

# 最終的なノード
I/Oなどの雑多な処理を除けば、以下のように単純な構造になります。
![2017-12-10_180716.png](https://qiita-image-store.s3.amazonaws.com/0/127402/dbaa35b3-ee45-a339-28f5-8304980bc64e.png)

詳しい内容は配布した.toeプロジェクトを参照していただけると助かります。

# 結果
ジャスティス
<img src="https://qiita-image-store.s3.amazonaws.com/0/127402/3ec47d91-41c2-35d6-9c54-384e4188b248.gif" width=50%><img src="https://qiita-image-store.s3.amazonaws.com/0/127402/003b6a3d-8620-f9e6-26a3-6e3fff7e7f92.gif" width=50%>



# 終わりに
この手法の応用例としては、[森岡さんの記事](https://qiita.com/ToyoshiMorioka/items/91c4e1427c2b4296c2a4)と組み合わせて、
バッファだけGLSLで書き出し、
その結果をパーティクルシステムで取り出して利用するといった使い方ができるかと思います。
(俗にいうVTFですね。)

時間が確保できず適当な解説になってしまいましたが、質問等あればお気軽にTwitter経由でご連絡ください。

明日は一番楽しみにしていた比嘉先生によるOpenCL講座です。
よろしくお願いします！

# 参考文献
- [Compiling multiple buffers in the glsl-top - Derivative Forum](https://www.derivative.ca/forum/viewtopic.php?f=27&t=9195)
- [TouchDesigner - GLSL Image Displacement](https://qiita.com/brvoigt/items/2937df3fb6aed3e816bf)