LoginSignup
7
2

More than 3 years have passed since last update.

TouchDesignerでGLSL Shaderを使ってLaunchpadをマトリックスディスプレイにする

Last updated at Posted at 2020-12-06

この記事はTouchDesigner Advent Calendar 2020の7日目の記事です。

前日(6日目)の記事は@satoruhigaさんの「感覚的に作るには」です。


TouchDesignerを休日にたしなんでいます @miyukki です。

はじめに

Novation Launchpadとは、Novation社が出しているUSBインターフェースを備えたMIDIインターフェースで、ドラムラックの演奏やサンプラーなど音楽制作で使われることが多いデバイスです。
image.png
最近では楽曲制作以外にも、システムの制御やステータスの表示にNovation Launchpadが使われることも増えてきました。おそらく、TouchDesignerユーザーの方であれば1台持っていたりするのではないでしょうか。

ちなみに、私が知っている事例ではInterop Tokyoでネットワーク機器のステータス表示に使っていたりする事例もありました。

余談はさておき、このLaunchpadを現場でまじまじと見ていると、マトリックスディスプレイとして使えないかと思い、空いている時間を見つけてTouchDesignerを使って実現しました。toxやコードを貼るだけでも良いのですが、せっかくなので思考プロセスや工程を含めて解説していこうと思います。

Launchpadの基本動作

まず、Launchpadの基本動作についておさらいしておきます。ここでは、TouchDesignerにおけるMIDIデバイスの設定方法などは割愛します。
Launchpadは、64個の何も書かれていないボタンと16個のコントロール用のボタン、計80個のボタンが備わっていますが、このうちコントロール用のボタンに関してはここでは取り扱わないものとします。

MIDI In CHOP を設置してLaunchpadのボタンを押してみると、画像のようになります。
image.png
Launchpadでは、ボタン下から1行目が ch1n12ch1n19 2行目が ch1n22ch1n29... といったチャンネルになるようです。ボタンとチャンネルの対応を分かりやすくすると、以下の画像のようになります。
image.png

また、試しに ch1n12ch1n19 に対して 適当な値を入れた Constant CHOPMIDI Out CHOP に接続してみます。MIDIの値は 0-127 のレンジで表現され、MIDI Out CHOPに送られた 0-1 の値は自動的に 0-127 変換されます。
image.png
するとデバイスでは以下の画像のように表示されます。
image.png
ボタンが押されたチャンネルに対して、値を入れることでボタンを表示させたり、またその色を変えたりできるといったことが分かりました。

Launchpadのボタン色

ここで、勘の良い人であれば、どの値がどの色になっているのかの対応が気になるかと思います。
しかし、私が調べた情報では、0-127の値の中である程度の規則性がある部分とそうでない部分があるそうです。

0-127 の値と色の対応を一覧にまとめた画像がありましたが、確かにこれをコード上でRGBから変換するのは難しいような気がしてきました...
image.png

どうにか、RGB->MIDI値の変換ができないか...ということで私の中で出た方法が、表示したい色とLaunchpadのボタン色パターンを比較して一番近いパターンの色を採用するというものです。

楽に考えるのであればPythonを用いるのが良いのですが、8x8のピクセルに対して127通りのループを作るのはパフォーマンスの面であまり気がすすみません。

GLSL Shaderを用いた近似色探索

そこで、GLSL Shader を用いた解決方法を思いつきました。

下図のように 表示したい色Launchpadで定義された色をRGBの三次元座標に置いて、それぞれの距離を算出し、一番近いパターンの物を採用するというイメージです。

image.png

LaunchpadのRGBカラーについては、運よくGitHubで公開している人がいたので、これを使用することにします。
https://github.com/mohayonao/launch-pad-color

マトリックスディスプレイにする

Launchpadをマトリックスディスプレイとして表示するためには、以下のような流れになると思います。
image.png

実際には、以下のようなノード構成になりました。
TouchDesigner_2020_26630___Users_a14802_Desktop_LEDDisp_toe.png
8x8のためのクロップなどの処理を経て8x8のTOPは、まずGLSLに接続されます。
GLSL Shaderの中身は以下のようになっています。

out vec4 fragColor;

// Launchpadの色パターン
vec4[128] colorMap = vec4[](
    vec4(  0,   0,   0,   0), vec4( 80,  80,  80,   1), vec4(160, 160, 160,   2), vec4(240, 240, 240,   3), vec4(255, 145, 133,   4), vec4(255,  35,  10,   5), vec4(230,  31,   9,   6), vec4(204,  28,   8,   7)
    // ...略...
);

void main()
{
    // 表示したいピクセルの色
    vec4 color = texture(sTD2DInputs[0], vUV.st);

    vec4 cl;
    float d;
    float min = distance(0, 1);
    int idx = 0;
    for (int i = 0; i < colorMap.length(); i++)
    {
        // 2点間の距離を計算して、一番近いもののインデックス(=MIDI値)を保持する
        cl = colorMap[i];
        d = distance(color.rgb, cl.rgb/255.0);
        if (d < min) {
            min = d;
            idx = i;
        }
    }

    // GLSLが出力するピクセルのαにMIDI値を代入する
    color = vec4(0.0, 0.0, 0.0, colorMap[idx].w/255.0);
    fragColor = TDOutputSwizzle(color);
}

GLSLのあとは、αの値(MIDI値)を取り出すための処理と、データをLaunchpadのチャンネルに変換するための処理が続いています。
TouchDesigner_2020_26630___Users_a14802_Desktop_LEDDisp_toe.png
TouchDesigner_2020_26630___Users_a14802_Desktop_LEDDisp_toe.png

ちなみに、Rename CHOPch1n[1-8][2-9] とすることにより ch1n12, ch1n13, ..., ch1n19, ch1n22, ...となることを知りました。べんり〜

マトリックスディスプレイで遊ぶ

作りたいものが作れた後は、思いっきり遊ぶだけです!

何かしら画像を出してみたり

image.png

長い文字をスクロールしてみたり

Video Device In TOPとつないでカメラの画像を表示してみたり

あとがき

今回はGLSLを映像処理ではなく、GPUを生かした並列処理を行うオペレーターとして扱ってみました。特にパフォーマンスにシビアなプロジェクトではいかにCPUなど時間のかかる処理をオフロードできるかが重要になってくるかと思います。

また、今回作った8x8のTOPをLaunchpadに表示するやつはtoxとしてGitHub上に公開してますので、是非ご利用ください。興味がある方は、toxの中も覗いてみてください。
https://github.com/miyukki/touchdesigner-launchpad-disp

7
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
2