第17回: シェーダー基礎

Advent Calendarの季節です!過去分も含めてチェック!


今回のプロジェクトファイル

今回の授業では、TouchDesignerで映像表現をする上で必須というわけではありませんが、使えるようになると表現力が大幅にアップする シェーダー言語 の説明をしようと思います。

シェーダー言語にもいくつか種類があるのですが、TouchDesignerで扱えるのは GLSL と呼ばれるものになります。

シェーダー言語はGPU上で高速に動作するように作られているので、使いこなせると非常に高度な表現ができますが、逆に言うとシェーダー言語を使う側がGPUの事に十分に気を使って書かないといけない、ということでもあります。地獄へようこそ!

TouchDesignerでは GLSL TOPGLSL MAT というオペレーターを通してGLSLを操作できます。今回は主に GLSL TOP のほうをやっていきます。

GLSL TOP

/project1/GLSL_TOP を参照

まずは、一番単純な使い方から見ていきたいと思います。

GLSL TOP を作ると、下図のようにTOPオペレーターとDATオペレーターが自動的に2つ作られます。

Image

この例だと、 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 といった数字が出ているのがわかると思いますが、これがシェーダー言語から生成された色の数値です。(端数がちょっと変ですが)

Image

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 TOPVector 1-3 のタブの Uniform Name にUniform変数名を定義して、同じ名前をシェーダーコードの中で uniform float uUniform などとして使うといった具合です。

1つのUniform変数あたりパラメーターは最大4つまで指定できますが、パラメーター数を変更した場合シェーダーコードの宣言の方も float, vec2, vec3, vec4 といった具合に修正する必要があります。

Image

サンプル紹介

GLSLGLSL TOP の使い方の基本的な機能を紹介してきました。ここからはサンプルをいくつか作ってきたので、順次口頭で解説していこうとおもっています。

とはいえいざ学習するとなるとGLSL自体が難解な所があるので、リファレンスのリンクをいくつか貼っておきます