TouchDesigner 頂点テクスチャフェッチを使って波のシミュレーションをする


こんにちは。
人生初のアドベントカレンダー執筆なので、ものすごく緊張しています。
改善点・間違っている点などあったらバシバシご指摘ください。


#デモ
今回はこれをつくります。
![wave-_1_.gif](https://qiita-image-store.s3.amazonaws.com/0/195560/2f715ea4-6a34-7f79-3c8b-65a5e4566a7c.gif)

[ソースはこちら👈](https://www.dropbox.com/s/iufcxnjs81zerqf/Wave.toe?dl=0)


#頂点テクスチャフェッチ(VTF)とは
[参考 ： 頂点テクスチャフェッチ(VTF)](https://wgld.org/d/webgl/w071.html)
上のページに記載されているように、頂点テクスチャフェッチとは**テクスチャの各ピクセルのRGBAにデータを格納して、それを頂点シェーダ内で参照すること**です。

#波動方程式を計算する
ではまず、波動方程式を計算しその結果を格納するテクスチャをつくっていきます。
このテクスチャに格納するデータは
R = 波の高さ
G = 速度
とします。


ノードは以下のように組みます。
feedback1のTarget TOPはnull1 とします。
constant1は黒にし、Common>Pixel Formatを16-bit float(RGBA)に、Common>Resolutionを500, 500に設定します。
<img width="1421" alt="スクリーンショット 2017-12-20 18.19.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/195560/b78ba724-1918-92a3-953d-429e50693277.png">
ここで、constant1は初期値を表しています。
R = 0, G = 0なので、波の高さの初期値 = 0, 速度の初期値 = 0 ということになります。
また、Feedback TOPを使うことで、GLSL内で１フレーム前の計算結果を参照することができるようになります。


では、glsl1のPixel Shaderを記述していきましょう。
[参考 ： [WebGL] 波動方程式を勉強してみる](https://qiita.com/edo_m18/items/e8efac43a93641c37ad2)

```
precision mediump float;

uniform vec2 resolution;
uniform vec2 mouse;
uniform int isActive;

float k = 0.5;
float attenuation = 0.99;
float range = 0.01;
float force = 0.00003;

out vec4 fragColor;

void main()
{
	vec4 pre_data = texture(sTD2DInputs[0], vUV.st); 
  	vec2 pixel = 1.0/resolution;
  	float accel = texture(sTD2DInputs[0], vUV.xy + pixel*vec2(0,-1)).x
				+ texture(sTD2DInputs[0], vUV.xy + pixel*vec2(0,1)).x
				+ texture(sTD2DInputs[0], vUV.xy + pixel*vec2(-1,0)).x
				+ texture(sTD2DInputs[0], vUV.xy + pixel*vec2(1,0)).x
				- texture(sTD2DInputs[0], vUV.xy).x * 4.0;
				
	accel *= k;
	float vel = (pre_data.y + accel) * attenuation;
	float u = pre_data.x + vel;
	
	if(isActive == 1){
		float len = distance(vUV.xy, mouse);
		if(len < range) u += 1.0/len*force;
	}
	
    fragColor = TDOutputSwizzle(vec4(u, vel, 0, 1.0));
}
```
fragColorのRには波の高さ(u)、Gには速度(vel)を格納します。

uniform変数は以下のように設定します。
resolutionはconstant1の解像度に合わせます。
<img width="586" alt="スクリーンショット 2017-12-21 2.28.41.png" src="https://qiita-image-store.s3.amazonaws.com/0/195560/df803609-acb1-56bd-f245-7c9c85798591.png">

mouse, isActiveについては、Panel CHOPのinsideu, insidev, selectチャンネルをエクスポートします。
<img width="330" alt="スクリーンショット 2017-12-20 20.51.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/195560/5b853d53-5858-59a7-d485-556b171901c4.png">

これで、マウスをドラッグしたポイントから波紋がでるようになりました。


#Particleを動かしてみる
Particleを動かして計算結果を確認してみたいと思います。

以下のようにノードを組みます。
grid1のRows, Columnsを、先ほどのconstant1の解像度と同じ500に設定します。
また、convert1のConvert toをParticlesにし、geo1のRender>Materialにはglsl2を設定します。
<img width="1121" alt="スクリーンショット 2017-12-20 21.07.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/195560/7094c666-6441-5236-1be2-a1058d3c12ff.png">


次に、先ほど実装した波動方程式の結果をglsl2の頂点シェーダで参照しましょう。
glsl2のuniform変数に、計算結果を格納したnull1を入れます。
<img width="621" alt="スクリーンショット 2017-12-20 21.16.18.png" src="https://qiita-image-store.s3.amazonaws.com/0/195560/a6dc5c2f-4cf1-526f-0afb-39944d1de3c8.png">


Vertex Shaderは以下のように記述します。
テクスチャのRに格納した波の高さを、Particleのzに割り当てます。

```
uniform sampler2D result;
void main() 
{
	float height = texture(result, uv[0].xy).x;
	gl_Position = TDWorldToProj(TDDeform(vec3(P.xy, height)));
}

```

Pixel Shaderでは適当な色を指定します。

```
out vec4 fragColor;
void main()
{
	TDCheckDiscard();
    vec4 color =  vec4(0.0, 0.25, 1.0, 1.0);
    TDAlphaTest(color.a);
    fragColor = TDOutputSwizzle(color);
}
```

最後にカメラの位置を調整し、Open Viewerで波の動きを確認してみてください。

#参考
https://wgld.org/d/webgl/w071.html
https://qiita.com/edo_m18/items/e8efac43a93641c37ad2
https://qiita.com/ToyoshiMorioka/items/91c4e1427c2b4296c2a4

#最後に
私を含む大学生4人でメディアアートクリエイティブチーム [Reflect Initial (リフレクト イニシャル)] (http://reflectinitial.tokyo/about/) を立ち上げ、制作活動を行なっています。

<img src="https://qiita-image-store.s3.amazonaws.com/0/195560/767e91c4-fa44-4804-ade0-7dd7cf0e47eb.png" width=400>


私たちはみな大学でメディアアートを専攻しているわけではなく、ただひたすらメディアアートが大好きだという思いから独学で学び制作をしています。もっともっとReflect Initialを知ってもらいたくここで紹介させていただきました。どうか応援よろしくお願いします。

Reflect InitialのTwitterぜひフォローしてください！
Check it out 👉 [@refect_toe](https://twitter.com/reflect_toe)

<blockquote class="twitter-tweet" lang="ja"><a href="https://twitter.com/reflect_toe/status/942529757794721792"></a></blockquote>