TouchDesignerでGLSL sandboxやShaderToyのコードを流用したりするためにも知らなきゃいけないコト
ナカジ(@cp_nakajun)です。
今回は【TouchDesignerでGLSLを使うために「最低限」知らなきゃいけない「超基礎」】
の続きです。
「超基礎」を覚えたらどんどんGLSLを使っていきたくなるのが向上心。
GLSLの習熟度が高い人は今回のTouchDesignerのGLSL Topの感じがつかめればかなり使っていけるように思います。
また、僕のようにガリガリGLSLを書けるわけじゃない人はGLSL sandboxやShaderToyのコードを流用することから始めると思いますが
それをする為にもいくつか「知らなきゃいけないこと」があります。
今回はそれ
今回のポイント
ポイントは次の3つです。
- 時間と解像度
- 処理中ピクセル座標と出力宣言
- シェーダー内座標の正規化
時間(time)と解像度(Resolution)
GLSL sandboxのコードを見ると最初の「変数宣言」に以下のような記述があると思います。
uniform float time; uniform vec2 mouse; uniform vec2 resolution;
とりあえず「mouse」は置いておいて
「time」と「resolution」はGLSL sandboxのデフォルト変数です。
それぞれ
- 現在の時間 : time
- 出力画像のピクセル解像度 : resolution
です。
時間的変化や動きのあるものを作る際には重要で必要になります。
ShaderToyをみるとコード内でわざわざ宣言しなくても良いみたいですが
- 現在の時間 : iGlobalTime
- 出力画像のピクセル解像度 : iResolution
がデフォルト変数として使えます。
TouchDesignerの「時間」と「解像度」を取得し変数に格納することで使います。
方法は「GLSL TOP」のパラメータ、「Vector1」の「uniform name」に設定する変数名とコードの「uniform」で宣言する名前を一致させればオッケーです。
「value」に設定する値は
- 時間(time,iGlobalTime):absTime.seconds
- 解像度(resolution,iResolution):me.par.resolutionw
を下の画像のように入力することで
absTime.seconds=秒
解像度のX軸に「me.par.resolutionw」Y軸に「me.par.resolutionh」とすることで
GLSL Topのcommonタブで設定した解像度を取得することができます。
処理中ピクセル座標と出力宣言
これはなにも考えずに記述しましょう。
vec2 fragCoord = vec2(vUV.s*resolution.x, vUV.t*resolution.y); out vec4 fragColor;
これで最終的にfragColorの情報が出力されます。
シェーダー内座標の正規化
main関数の中に
vec2 p = (fragCoord.xy * 2.0 - resolution) / min(resolution.x, resolution.y);
と書くコトで座標の指定を「0.0〜1.0」の範囲に統一することができます。
こうしておかないと「解像度」を変更した際に「描画座標」に関わる全てのコードを変更しなければならなくなるからです。
GLSL sandboxのコードをTouchDesignerに移植
試しにGLSL sandboxのコードをTouchDesignerに移植してみました。
今回試したコードは
http://glslsandbox.com/e#41905.0
このコードは上記に書いたことをすることで動かすことができました。
TouchDesigner用に変更したコードは以下です。
precision mediump float; uniform float time; uniform vec2 resolution; vec2 fragCoord = vec2(vUV.s*resolution.x, vUV.t*resolution.y); out vec4 fragColor; float starFunc(vec3 p) { float a = 2.0; float fp = .7550; const int n =15; float pa = 0.; for(int i = 0; i < n; ++i) { p=abs(p)/dot(p,p)-fp; a+=abs(length(p)-pa); pa=length(p); } a /= float(n); return pow(a,6.)*.225; } vec3 galaxy(vec3 start, vec3 dir) { vec3 p = start+dir*40.0; vec3 c = vec3(starFunc(p)) * vec3(1.7,1.4,2.0); p = start+dir*1.0; c += vec3(starFunc(p)) * vec3(1.2,0.8,3.0); p = start+dir*.1; c += vec3(starFunc(p)) * vec3(1.7,1.2,1.4); return c*0.462; } void main() { vec2 p = (fragCoord.xy * 2.0 - resolution) / min(resolution.x, resolution.y);// -1.0~1.0 float an = 1.5+0.03*time; float a2 = 3333.9; float a3 = -2.9; mat2 rot_a2 = mat2(cos(a2),sin(a2),-sin(a2),cos(a2)); mat2 rot_a3 = mat2(cos(a3),sin(a3),-sin(a3),cos(a3)); vec3 ro = vec3( 1.0*cos(an), 2.0*cos(an) ,5.); ro.xz *= rot_a2; ro.yz *= rot_a3; vec3 rd = vec3(p.x*cos(an) + p.y*sin(an),p.x *(-tan(sin(an))) + p.y*cos(an), 0.1 - sin(time*0.003)); rd.xz *= rot_a2; rd.yz *= rot_a3; vec3 bckg = galaxy(ro,rd); vec3 col = bckg; col = pow(col,vec3(0.5)); vec4 outcolor = vec4(col,1.0); fragColor = TDOutputSwizzle(outcolor); }
まとめ
とりあえず、また小さな一歩を踏み出せたかなぁ、と
まだまだ細部を語れるほどの理解はできてないですが、また理解と知識を深めたら共有していきます。