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);

つまり、
・vUVは[0-1]の範囲に正規化されたx,y座標が入っている
・gl_FragCoordは[1280, 720]など生の解像度の値が入っている。


out vec4 fragColor と TDOutputSwizzle()

ここに最終的に値を入れると画像が生成される。

fragColor = TDOutputSwizzle(color);
と初期設定でなっている。

これは、Windowsとmac版での色の差異を補ってくれる関数のようなので、
入れとくと良い。


TOPの入力(texture)とGLSL

ここのinputの3つに好きなテクスチャとしてGLSLに送れる。

画像1


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;
画像2

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を押すと

画像3

GLSL TOPのVectorsの項目等に勝手に追加される

値も他のオペレーターからのReferenceを利用して自由に遅れるので便利。

画像4


GLSL TOP Extend Mode

GLSL TOPのGLSLタブの中の、Input Extend Mode UVを押すと、
描画範囲外の処理の扱いを簡単に行ってくれる。
Holdにすると伸びるような画像になり、
Repeat , Mirror , Zeroが用意されている。


画像5



GLSL と Pixel Format

GLSLでは基本的に[0-1]の範囲の値しか取り出せないが、

画像6

※これは単なるsin wave

画像7

Pixel Formatの値を変更することで出力範囲を変えれる。

画像8

初期設定 8bit fixed(RGBA)だと[0-1]の範囲でクリッピングされる

画像9

16bit float rgbaとかだと
マイナス領域に広がるかつ、範囲がデカくなる
どこまで広がっているのかは調べてないのでわからない。
パッと見結構広い

画像10
画像11


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の中で何かしらを与える。

画像12

GLSL TOPのGLSLタブの一番下 # of color buffersの値が初期値1になっている
これは1枚のバッファを扱うことができることを意味していて、上記の例で行くと3枚扱いたいので3にする

画像13

render select TOPを作り、TOPにglsl TOPを選択する。

画像14

color buffer indexの値を変えることによって、バッファを選択できる。
ここはインデックスなので0スタート。


分かりやすい説明。





GLSL TOPのビルドイン

GLSL TOPのビルドイン関数とかはここに書かれている。

Noiseとかも用意されているらしい。

uTD2DInfos[0].res

The components are defined as:
vec4 res; // contains (1.0 / width, 1.0 / height, width, height)

uTDOutputInfo.res





MAT to GLSL MAT

Phong MATやPBR MATからGLSL MATに変換することができる。

output shader..というところからoutputを選択し、ウィンドウのokを押すと生成される。

画像15
画像16


TDDeform()とTDWorldToProj()

TouchDesignerで用意してる変換行列

TDDeform・・モデル・ビュー座標変換用の関数

TDWorldToProj()・・プロジェクション座標変換用の関数


MVP変換について


vec3 newP = P;	
newP += TDDeform(newP).y;

~~~~~
画像33

GLSL MATとSampler2D

GLSL TOPと違って、textureをGLSLに送るにはノードをつなぐのではなく
タブ内のSamplersからTOPを選ぶ

画像17

受け取りは以下のようにして受け取れる。

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;

まず int id = gl_VertexID; で0から65535までの頂点のユニークなIDを取得します。
これを使ってuPosMap上の対応した座標のpixelの色情報を取りたい。
なので vec2 res = textureSize(uPosMap,0); でuPosMapの縦横の解像度を取得し、 vec2 uv = vec2(float(id % int(res.x)), float(floor(id / int(res.x)))) / res; でuPosMap上のuv座標に変換しています。ぱっと見見慣れないかもしれませんが、よく画像のpixelを舐めるときにfor文で書いてるアレです。
ただ、これだとpixelの左上端を見てしまうので、真ん中に持ってくるために vec2 texCoord0 = uv + (1.0 / res) * 0.5; の処理をします。
[引用] https://qiita.com/ToyoshiMorioka/items/91c4e1427c2b4296c2a4




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変数を追加することができる。

画像25


別ノートにpythonとTscriptについてのビルドインが乗っている。
https://note.com/omakazu/n/nb4b3177ee6e3#FBCVq


上の場合、
vertex shaderとかで、

in float PT;

で読み込むことができる。


GeometryとAttribute

geometry compのinstance3タブにChopとかTOPとかをCustom Attrib OPに入れると下記の方法でAttributeを作れる
XYZWの4chanの値を入れれる

画像34


TDInstanceCustomAttrib0()でGETできる。

Custom instance attributes can be retrieved using these functions:

vec4 TDInstanceCustomAttrib0();
vec4 TDInstanceCustomAttrib0(int instanceIndex);
vec4 TDInstanceCustomAttrib1();
vec4 TDInstanceCustomAttrib1int instanceIndex);
vec4 TDInstanceCustomAttrib2();
vec4 TDInstanceCustomAttrib2(int instanceIndex);
vec4 TDInstanceCustomAttrib3();
vec4 TDInstanceCustomAttrib3(int instanceIndex);
[引用] https://docs.derivative.ca/Write_a_GLSL_Material

これで受け取れる
	newP *= TDInstanceCustomAttrib0().x;




gl_InstanceID

インスタインシングしているときのインスタンスオブジェクトに対するIndexをもらうことができる。



gl_VertexID

vertexごとに変化を加えたいときに使える。
vertexのindexが入ってくる


TDInstanceTexCoord()



// To calculate the texture coordinates for your instance (if used in the Geometry COMP's parameters), use these functions
// For texture coordinates the passed in variable 't' is the current texture coordinate to be modified/replaced

vec3 TDInstanceTexCoord(int instanceID, vec3 t);
vec3 TDInstanceTexCoord(vec3 t);

Attribute Functions
When modifying the texture coordinates, these functions do the texture coordinate modifications per instance. t is the texture coordinate to modify. The version without instanceIndex will use the current value for gl_InstanceID automatically.

vec3 TDInstanceTexCoord(int instanceIndex, vec3 t);
vec3 TDInstanceTexCoord(vec3 t);

[引用] https://docs.derivative.ca/Write_a_GLSL_Material

https://forum.derivative.ca/t/why-does-touchdesigner-use-tdinstancetexcoord-in-vertex-shader/109813



TDInstanceTranslate()

おそらく、InstanceのTranslateの値がそれぞれGETできる
つまり、Instance元のPointの個数だけ

画像26
画像27
newP = P;//このPは(今回で言えばTubeの)pointのpositionが入ってくる。
newP.x +=  TDInstanceTranslate().y;
//TDIsntaceTranslate()は元なっている、(今回で言えばboxの)ポイントのpositionが入ってくる。
画像29
画像28



TDInstanceRotate()
Rotateのところを扱える?

画像30


TDInstanceColor

同様にinstanceのcolorを手にれれる。

TDInstanceColor(Cd)とすれば、instanceのpoint事のカラーを設定できる。



TDRotateX(), TDRotateY(), TDRotateZ(), TDScale() TDTranslate()

変換行列

引数の中に値を入れると使える。

TDRotateは引数にradianを入れると正しい挙動。

	newP*= TDRotateX(newP.y);


画像31


newP*= TDRotateX(newP.y);
newP *=  TDRotateX(TDInstanceTranslate().y);//
画像32



GLSL TOPとCompute Shader

GLSL TOPのみComputeShaderが扱える。
GLSL TOPの右下赤矢印を押すことで、ComputeShaderようのDATがでてくる。

画像18
画像19

GLSL Versionは4.3以降から使うことができる。
ModeをCompute Shaderに切り替える必要がある。

画像20


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));

}
画像21


Compute Shaderとバッファ

Compute Shaderではバッファに対して読み書きができる。

Output accessをread-writeにするとバッファに対して読み書きができるようになる。

画像22

書き込みに関して
void imageStore(gimage2D image, ivec2 P, gvec4 data)
第一引数に書き込みたいバッファオブジェクト
第二引数に二次元のピクセル座標(整数値)(UVではない。)
第三引数にピクセルのカラーの値
で書き出すことができる。

読み込みに関しては
gvec4 imageLoad(gimage2D image, ivec2 P);
第一引数に書き込みたいバッファオブジェクト
第二引数に二次元のピクセル座標(整数値)(UVではない。)
で該当する部分のピクセルのカラー値が得られる。


sTDComuputeOutputsとmTDComputeOutputs


sTDComuputeOutputsmTDComputeOutputsに変更された。

[引用]
GLSL TOP - Renamed Compute Shader output from sTDComputeOutputs to mTDComputeOutputs. Old name continues to work for backwards compatibility.

これらは出力のColor Buffer(フレームバッファ)とが入っている。

The sTDComputeOutputs[] uniform will be sized equal to the number of color buffers being output.


こうすることで、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にしとかないと、
フレームバッファが毎回リセットされてしまうので、注意。

画像23


GLSLTopとArrays

texture bufferとしてArrraysのタブからCHOPの値を送ることができる。

画像24

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




過去のGLSLのノート




References



















この記事が気に入ったらサポートをしてみませんか?