2018.04.25
- 人×技術
TouchしないDesigner
Motivation
TouchDesigner に Touch しないで Emacs で使いたい。
Python インターフェース
td Module - TouchDesigner 099 Wiki
TouchDesigner には Python 向けのモジュール td
が用意されているので、これを利用して Emacs で作業を完結させる仕組みを検討します。td
は TouchDesigner の起動時に実行される TouchInit.py
で自動的に読み込まれるため import
は不要で、sys
, re
, math
, inspect
, warnings
, collections
などの基本的なモジュールも同様です。
まずは、下図のような入力映像を加工し出力する構成を Python から生成します。
Texture の作成
入力映像と GLSL の TOP を作成して接続。
$ emacs = op('/emacs')
$ vdi = emacs.create(videodeviceinTOP)
$ gls = emacs.create(glslTOP)
$ gls.inputConnectors[0].connect(vdi)
Uniform の定義
入力テクスチャの解像度を GLSL に渡すための uniform 変数。
$ gls.par.uniname0 = 'resolution'
$ gls.par.value0x.expr = "op('%s').width" % vdi.name
$ gls.par.value0y.expr = "op('%s').height" % vdi.name
GLSL の同期
glslTOP
生成時の Pixel Shader が textDAT
のため fileinDAT
に変更してシェーダのファイルパスを登録。
$ fii = op(gls.par.pixeldat).changeType(fileinDAT)
$ fii.par.file = 'emacs.glsl'
$ fii.par.refresh = True
emacs.glsl
シェーダファイルは入力をそのまま出力する処理で一旦作成。
out vec4 fragColor;
void main()
{
fragColor = texture(sTD2DInputs[0], vUV.st);
}
Perform Mode の切替
Perform mode - TouchDesigner 099 Wiki
Perform Mode 用のウインドウを作成して登録。
$ emacs.create(windowCOMP).par.winop = gls
$ ui.performMode = True
Python の実行
ここまでのスクリプトを Emacs で記述し TouchDesigner で実行します。この結果 TouchDesigner は出力結果のウインドウのみになるため、以降は Touch しないで Emacs から GLSL を変更し Design を確認する環境になります。
emacs = op('/emacs')
vdi = emacs.create(videodeviceinTOP)
gls = emacs.create(glslTOP)
gls.inputConnectors[0].connect(vdi)
gls.par.uniname0 = 'resolution'
gls.par.value0x.expr = "op('%s').width" % vdi.name
gls.par.value0y.expr = "op('%s').height" % vdi.name
fii = op(gls.par.pixeldat).changeType(fileinDAT)
fii.par.file = 'emacs.glsl'
fii.par.refresh = True
emacs.create(windowCOMP).par.winop = gls
ui.performMode = True
ポストエフェクトの反映
動作確認のためにシェーダを変更した結果が以下になります。uniform 変数 resolution
からは事前に定義しておいた videodeviceinTOP
の解像度が参照可能になっており、また fileinDAT
による GLSL の同期が確認できます。
uniform vec2 resolution;
out vec4 fragColor;
void main()
{
mat4x3 m, s;
const int r = 4 + 1;
const mat4x2 d = mat4x2(-r, -r, 0, -r, -r, 0, 0, 0);
for (int u=0; u<r; u++) {
for (int v=0; v<r; v++) {
for (int i=0; i<4; i++) {
vec3 c = texture(sTD2DInputs[0], vUV.st + (vec2(u, v) + d[i]) / resolution.xy).rgb;
m[i] += c;
s[i] += c*c;
}
}
}
m /= r*r;
s /= r*r;
vec3 rgb;
float minL = 1.0;
for (int i=0; i<4; i++) {
float l = dot((s[i] - m[i]*m[i]).rgb, vec3(0.30, 0.59, 0.11));
if (l < minL) {
rgb = m[i];
minL = l;
}
}
fragColor = TDOutputSwizzle(vec4(rgb, 1.0));
}