TouchDesigner GLSL メモ
随時更新されていきます
更新日2023/11/26/1:37
TouchDesignerとGLSLのメモです。
何もかも忘れっぽいのでメモします。
間違っていることや情報があればぜひ教えて下さい。
gl_FragCoord と vUV.st
下の二個のコードで同じ画像が生成される。
//UV画像が見れる
color = vec4(vUV.st, 0.0, 1.0);
//UV画像が見れる
color = vec4(gl_FragCoord.x / uResolution.x, gl_FragCoord.y / uResolution.y, 0.0, 1.0);
out vec4 fragColor と TDOutputSwizzle()
ここに最終的に値を入れると画像が生成される。
fragColor = TDOutputSwizzle(color);
と初期設定でなっている。
これは、Windowsとmac版での色の差異を補ってくれる関数のようなので、
入れとくと良い。
TOPの入力(texture)とGLSL
ここのinputの3つに好きなテクスチャとしてGLSLに送れる。
GLSL上ではsTD2DInputs[0-2]でsampler型(sampler2D?)で受け取れる
texture(sTD2DInputs[0], vUV.st);
//vUV.stの場所の引数には0-1までのテクスチャ座標を入れる
//テクスチャを正規化した座標上で対応する点のカラーが返ってくる
一般に、GLSLでは、texture()関数では
` fc = texture(image, gl_FragCoord.xy);`みたいな感じで、gl_FragCoord.xyで帰ってくる、ピクセル座標をそのまま参照してそれに相当するテクセルを返してくるということになっているが、
TouchDesignerでは、sTD2DInputs[index]が、uv形式で[0-1]のvec2での座標をいれることによって、テクセルが返ってくるように事前に処理されていることに注意。
単純にもう既に用意されている、vUV.stみたいなものを使うか、
‘vec2 uv = (gl_FragCoord.xy) / resolution.xy;`みたいな正規化を行ってUVを作るなどをしなくてはならない。(resolution.xyはuniform変数として用意しなくてはならない。)
vec2 p = (gl_FragCoord.xy * 2.0 - uResolution.xy) / min(uResolution.x, uResolution.y);
//中央を原点にする。
vec4 color = vec4(1.0);
color.rgb = texture(sTD2DInputs[0], p).rgb;
uResolution = [1280, 720]
texture解像度が[720, 720]だとすると、
こうすると、[0,0]が真ん中になるため、真ん中が画像の左下となる上記のような画像ができる。
Uniform変数
Uniform変数は簡単に作って渡せる。
GLSL内でuniformの宣言を行って普通に書く。
uniform vec2 uResoltuion;
void main(){
vec2 p = (gl_FragCoord.xy * 2.0 - uResolution.xy) / min(uResolution.x, uResolution.y);
fragColor = TDOutputSwizzle(vec4(p, 0.0, 1.0));
}
などと、最後のfragColorまでの出力までにどこかで使われているように書くと、
GLSL TOPのGLSLの項目でLoad Uniform NamesのLoadを押すと
GLSL TOPのVectorsの項目等に勝手に追加される
値も他のオペレーターからのReferenceを利用して自由に遅れるので便利。
GLSL TOP Extend Mode
GLSL TOPのGLSLタブの中の、Input Extend Mode UVを押すと、
描画範囲外の処理の扱いを簡単に行ってくれる。
Holdにすると伸びるような画像になり、
Repeat , Mirror , Zeroが用意されている。
GLSL と Pixel Format
GLSLでは基本的に[0-1]の範囲の値しか取り出せないが、
※これは単なるsin wave
Pixel Formatの値を変更することで出力範囲を変えれる。
初期設定 8bit fixed(RGBA)だと[0-1]の範囲でクリッピングされる
16bit float rgbaとかだと
マイナス領域に広がるかつ、範囲がデカくなる
どこまで広がっているのかは調べてないのでわからない。
パッと見結構広い
GLSL TOP と Frame Buffer
フレームバッファを取り出せる。
layout(location = 0) out vec4 color_uv;
layout(location = 1) out vec4 color_1;
layout(location = 2) out vec4 color_2;
void main(){
..............
color_uv = TDOutputSwizzle(colorUV);
color_1 = TDOutputSwizzle(color1);
color_2 = TDOutputSwizzle(color2);
}
layout(location = bufferの番号) out vec4 任意の名前
で宣言し、void mainの中で何かしらを与える。
GLSL TOPのGLSLタブの一番下 # of color buffersの値が初期値1になっている
これは1枚のバッファを扱うことができることを意味していて、上記の例で行くと3枚扱いたいので3にする
render select TOPを作り、TOPにglsl TOPを選択する。
color buffer indexの値を変えることによって、バッファを選択できる。
ここはインデックスなので0スタート。
分かりやすい説明。
GLSL TOPのビルドイン
GLSL TOPのビルドイン関数とかはここに書かれている。
Noiseとかも用意されているらしい。
uTD2DInfos[0].resは
uTDOutputInfo.res
MAT to GLSL MAT
Phong MATやPBR MATからGLSL MATに変換することができる。
output shader..というところからoutputを選択し、ウィンドウのokを押すと生成される。
TDDeform()とTDWorldToProj()
TouchDesignerで用意してる変換行列
MVP変換について
vec3 newP = P;
newP += TDDeform(newP).y;
~~~~~
GLSL MATとSampler2D
GLSL TOPと違って、textureをGLSLに送るにはノードをつなぐのではなく
タブ内のSamplersからTOPを選ぶ
受け取りは以下のようにして受け取れる。
uniform sampler2D uNoise;
Sampler2DのサイズもuTD2DInfos[]という変数名で取得可能
UVじゃなくても、
これでもカラー値を手に入れることができる。
vec3 color = texelFetch(uNoise, ivec2(w, h), 0).rgb;
GLSL MATとUV座標
GLSL MATではuv座標を取得するのには、uv[0].xyのようにすると使うことができる
texture(uNoise, uv[0].xy);
int id = gl_VertexID;
vec2 res = textureSize(uPosMap, 0);
vec2 uv = vec2(float(id % int(res.x)), float(floor(id / int(res.x))) ) / res;
vec2 texCoord0 = uv + (1.0 / res) * 0.5;
Vertex Shader Attribute変数
ビルドインされている、Attribute変数についてはこちらら参照できる。
layout(location = 0) in vec3 P; // Vertex position
layout(location = 1) in vec3 N; // normal
layout(location = 2) in vec4 Cd; // color
layout(location = 3) in vec3 uv[8]; // texture coordinate layers
Pはvertex positionとして割り当てられている。
pointとAttribute
Attribute変数を自分で追加できる。
glsl MATにつながっているジオメトリーのオブジェクトが
point SOPを経由している場合
customのタブからattribute変数を追加することができる。
上の場合、
vertex shaderとかで、
in float PT;
で読み込むことができる。
GeometryとAttribute
geometry compのinstance3タブにChopとかTOPとかをCustom Attrib OPに入れると下記の方法でAttributeを作れる
XYZWの4chanの値を入れれる
TDInstanceCustomAttrib0()でGETできる。
これで受け取れる
newP *= TDInstanceCustomAttrib0().x;
gl_InstanceID
インスタインシングしているときのインスタンスオブジェクトに対するIndexをもらうことができる。
gl_VertexID
vertexごとに変化を加えたいときに使える。
vertexのindexが入ってくる
TDInstanceTexCoord()
TDInstanceTranslate()
おそらく、InstanceのTranslateの値がそれぞれGETできる
つまり、Instance元のPointの個数だけ
newP = P;//このPは(今回で言えばTubeの)pointのpositionが入ってくる。
newP.x += TDInstanceTranslate().y;
//TDIsntaceTranslate()は元なっている、(今回で言えばboxの)ポイントのpositionが入ってくる。
TDInstanceRotate()
Rotateのところを扱える?
TDInstanceColor
同様にinstanceのcolorを手にれれる。
TDInstanceColor(Cd)とすれば、instanceのpoint事のカラーを設定できる。
TDRotateX(), TDRotateY(), TDRotateZ(), TDScale() TDTranslate()
変換行列
引数の中に値を入れると使える。
TDRotateは引数にradianを入れると正しい挙動。
newP*= TDRotateX(newP.y);
newP*= TDRotateX(newP.y);
newP *= TDRotateX(TDInstanceTranslate().y);//
GLSL TOPとCompute Shader
GLSL TOPのみComputeShaderが扱える。
GLSL TOPの右下赤矢印を押すことで、ComputeShaderようのDATがでてくる。
GLSL Versionは4.3以降から使うことができる。
ModeをCompute Shaderに切り替える必要がある。
gl_GlobalInvocationID
Compute Shaderはピクセルごとに処理が行われる。
グローバル変数 in uvec3 gl_GlobalInvocationIDでピクセル単位のインデックスが得られる。つまり、値は整数のピクセル座標が得られる。
UV画像を作りたいなら
uniform ivec2 res;
void main(){
//floatでキャストしないと整数値になっていしまう。
color = vec4(float(gl_GlobalInvocationID.x) / res.x, float(gl_GlobalInvocationID.y) / res.y, 0.0, 1.0);
imageStore(mTDComputeOutputs[0], ivec2(gl_GlobalInvocationID.xy), TDOutputSwizzle(color));
}
Compute Shaderとバッファ
Compute Shaderではバッファに対して読み書きができる。
Output accessをread-writeにするとバッファに対して読み書きができるようになる。
書き込みに関して
void imageStore(gimage2D image, ivec2 P, gvec4 data)で
第一引数に書き込みたいバッファオブジェクト
第二引数に二次元のピクセル座標(整数値)(UVではない。)
第三引数にピクセルのカラーの値
で書き出すことができる。
読み込みに関しては
gvec4 imageLoad(gimage2D image, ivec2 P);
第一引数に書き込みたいバッファオブジェクト
第二引数に二次元のピクセル座標(整数値)(UVではない。)
で該当する部分のピクセルのカラー値が得られる。
sTDComuputeOutputsとmTDComputeOutputs
sTDComuputeOutputsはmTDComputeOutputsに変更された。
これらは出力のColor Buffer(フレームバッファ)とが入っている。
こうすることで、1フレーム前のバッファを読み込むことができる。
//一フレーム前のバッファを参照
layout (local_size_x = 8, local_size_y = 8) in;
void main()
{
vec4 color;
color = imageLoad(mTDComputeOutputs[0], ivec2(gl_GlobalInvocationID.xy));
color.rgb += vec3(0.01, 0.03, 0.04);
color.rgb = fract(color.rgb);
color.a = 1.0;
imageStore(mTDComputeOutputs[0], ivec2(gl_GlobalInvocationID.xy), TDOutputSwizzle(color));
}
GLSL TOPのClear OutputsをOffにしとかないと、
フレームバッファが毎回リセットされてしまうので、注意。
GLSLTopとArrays
texture bufferとしてArrraysのタブからCHOPの値を送ることができる。
texture bufferとして送られたものは、
uniform samplerBuffer uniform名;
で受け取れる。
これは、texture()関数ではなくて、
texelFetch()関数を用いて値を取り出せる。
texelFetch(textureBuffer, Pixel_position)
第一引数にはtextureBuffer
第二引数にはピクセル座標(UVではない)
CHOPからの値を受け取れる方法として便利
uTDOutputInfo.res.xy holds (1.0 / width, 1.0 / height)
Cheat Sheet
Inigo Quilez :: fractals, computer graphics, mathematics, shaders, demoscene and more
Primitiveの作り方
The Book of Shaders
Shaderific - GLSL Functions
GLSL Build in Function