第17回: シェーダー基礎
Advent Calendarの季節です!過去分も含めてチェック!
- TouchDesigner Advent Calendar 2019 - Qiita
- TouchDesigner Advent Calendar 2018 - Qiita
- TouchDesigner Advent Calendar 2017 - Qiita
- Touchdesigner Advent Calendar 2016 - Adventar
今回の授業では、TouchDesignerで映像表現をする上で必須というわけではありませんが、使えるようになると表現力が大幅にアップする シェーダー言語
の説明をしようと思います。
シェーダー言語にもいくつか種類があるのですが、TouchDesignerで扱えるのは GLSL
と呼ばれるものになります。
シェーダー言語はGPU上で高速に動作するように作られているので、使いこなせると非常に高度な表現ができますが、逆に言うとシェーダー言語を使う側がGPUの事に十分に気を使って書かないといけない、ということでもあります。地獄へようこそ!
TouchDesignerでは GLSL TOP
と GLSL MAT
というオペレーターを通してGLSLを操作できます。今回は主に GLSL TOP
のほうをやっていきます。
GLSL TOP
/project1/GLSL_TOP
を参照
まずは、一番単純な使い方から見ていきたいと思います。
GLSL TOP
を作ると、下図のようにTOPオペレーターとDATオペレーターが自動的に2つ作られます。
この例だと、 glsl1_pixel
の部分がシェーダー言語を記述するDAT、glsl1_info
がシェーダー言語のコンパイル結果やエラーなどを表示するためのDATです。
続いて、これが赤を出力せよ、という内容のシェーダーコードです。
out vec4 fragColor;
void main()
{
vec4 color = vec4(1, 0, 0, 1);
fragColor = TDOutputSwizzle(color);
}
おまじないが多少ありますが、要は void main()
の括弧の中で、あらかじめ out vec4 fragColor
と定義した変数へ RGBA
に対応する vec4
の数字を代入すればその色が出る、という感じになります。
ピクセルの座標を出力してみる
続いて、glsl2
ではピクセルの座標を色として出力してみる、といったことをやっています。シェーダーコードは以前と大体同じですが、 gl_FragCoord.xy
というGLSLのシステムの中でデフォルトで定義されている変数を使ってピクセルの色を塗っています。
out vec4 fragColor;
void main()
{
vec4 color = vec4(gl_FragCoord.xy, 0, 1.0);
fragColor = TDOutputSwizzle(color);
}
glsl2
のビューワーの中にマウスをのせてみると R: 118.500 G: 50.500
といった数字が出ているのがわかると思いますが、これがシェーダー言語から生成された色の数値です。(端数がちょっと変ですが)
GLSLを書くときは、print文などが使えないのでこういった色の情報を試しに出力してみてきちんと動作しているかを確かめながら進めていきます。
X: 100, Y: 100 の座標に点を打つ
このページの最初に、シェーダー言語を書く時はGPUの内部の処理のことを気にしながら進めていかなければいけないと書きましたが、それはGPUの処理の仕組みが並列実行であるから、という点が大いに関係しています。
この講座の最初の授業で紹介したこのムービー覚えてますでしょうか?
たとえば ↑ の機械を使って、横が100番目、タテが100番目だけ白のボール、あとは黒のボールを打つプログラムを書きたい時はどうしたらいいでしょう?
GLSLを使った場合だと、たとえばこういう形になります。
out vec4 fragColor;
void main()
{
vec4 color;
if (floor(gl_FragCoord.xy) == vec2(100, 100))
color = vec4(1, 1, 1, 1);
else
color = vec4(0, 0, 0, 1);
fragColor = TDOutputSwizzle(color);
}
Processing などの言語だと point(100, 100)
のようなもので書けるものもだいぶ複雑な見た目になります。。これがGLSLが難しいと言われている原因の一つではないかと思います。
が、実際にシェーダー言語を使ったほうが高速に動く事が多いので、こういった事は速度のためには諦めて慣れるしかありません!地獄へようこそ!
UV座標
/project1/UV
を参照
さきほどの例だと gl_FragCoord.xy
を使ってピクセルの位置を取得していましたが、普通はもうちょっと使いやすい UV座標
というものを使います。
UV座標は GLSL TOP
の機能によって vUV.st
というキーワードでアクセスできるようになっており、左下が (0, 0)、右上が (1, 1) の値になるように調整されています。
これは、GLSLの機能である texture関数
と一緒に使いやすいようにこういうふうになっていて、一番目のインプットにつながっているTOPの内容を示す sTD2DInputs[0]
と組み合わせることで入力されたTOPの色を取得することができます。
out vec4 fragColor;
void main()
{
vec4 color = texture(sTD2DInputs[0], vUV.st);
fragColor = TDOutputSwizzle(color);
}
Uniform変数
/project1/UNIFORM
を参照
Uniform変数を使うとTouchDesignerのパラメーターをシェーダー言語に渡して内容を動的に変化させることができます。
GLSL TOP
の Vector 1-3
のタブの Uniform Name
にUniform変数名を定義して、同じ名前をシェーダーコードの中で uniform float uUniform
などとして使うといった具合です。
1つのUniform変数あたりパラメーターは最大4つまで指定できますが、パラメーター数を変更した場合シェーダーコードの宣言の方も float
, vec2
, vec3
, vec4
といった具合に修正する必要があります。
サンプル紹介
GLSL
、 GLSL TOP
の使い方の基本的な機能を紹介してきました。ここからはサンプルをいくつか作ってきたので、順次口頭で解説していこうとおもっています。
とはいえいざ学習するとなるとGLSL自体が難解な所があるので、リファレンスのリンクをいくつか貼っておきます
- 公式ドキュメント https://docs.derivative.ca/Write_a_GLSL_TOP
- 非常にわかりやすい&ためになるチュートリアル https://thebookofshaders.com/?lan=jp
- 関数の使い方がわからない時など http://docs.gl/
- ネタ探しに https://neort.io/tag/bmj9c1c3p9fdr6916krg
- 目の保養に https://www.shadertoy.com/