第十回
本日のtoeファイル ← ダウンロードしておいてください
今日は、ちょっと突っ込んだOpenGLのグラフィックのトピックをいつか紹介したいと思います。
ちょっととっつきにくいかもしれませんが、順を追って見ていけば結構単純です!
ジオメトリインスタンス
OpenGLの機能のひとつで、ジオメトリのコピーをGPUに処理させることで、とても大量のオブジェクトのコピーをリアルタイムで描画することができるものです。インスタンシングとも言ったりします。
わかりやすい例だとこのへん → three.js webgl - instancing test (single triangle)
TouchDesignerだとある程度オブジェクト数を出さないといけない場合、SOPなどでやるとすぐ限界がきてしまうので、物量感が欲しい場合には必須のテクニックになります。
とはいえ、基本はすごく簡単です。
基本のセットアップ
↑ の動画は、ジオメトリインスタンスを表示させるまでの最短の手順です。
使うのは、適当なSOP、SOP to CHOP
、 Geometry COMP
のみで、SOP to CHOP
でCHOPに変換した頂点データをGeometry COMP
に渡して描画してもらう、という流れです。
Geometry COMP
の Instance
> Instance
のトルグをONにして、Instance CHOP/DAT/SOP
パラメータに使いたいCHOPを設定します。
その後 TX
, TY
, TZ
などのパラメータに、インスタンシングをする時に使いたいチャンネル名を渡します。
一旦設定してしまえば、SOPレベルで位置や頂点数などを変更すればそれをもとにインスタンシングされたコピーにも反映されます。
SOPレベルのアニメーション
↑ では、SOP to CHOP
につないでいたジオメトリに Noise SOP
をかけることでインスタンシングのソースにアニメーションをかけています。
色の情報も含めてインスタンシングするには、 SOP to CHOP
の Attribute Scope
、Rename Scope
を編集します。
Attribute Scope
では、CHOP側に立ち上げたいSOPアトリビュートを指定します。
例えば、SOPを中クリックして出てくるインフォーメーションの中の Cd[4]
が色情報を表わすアトリビュートなのですが、それを立ち上げたい場合、Attribute Scope
には Cd
を。Rename Scope
には cr cg cb ca
又はもっと簡潔に c[rgba]
を追加します。
そうすると、SOP to CHOP
のチャンネルの中に新たに追加したアトリビュートが見れるようになるはずです。
CHOPレベルのアニメーション1
もうすこし複雑なアニメーションにもチャレンジしてみましょう。
CHOPのオペレーターとインタンシングを組み合わせると興味深いアニメーションを簡単に試すことができます。
↓ の動画では、グリッド上に配置したインスタンスを、Speed CHOP
で値を変更する事で全体を動かし、さらにその動きのスピードを調整できるようにしています。
また、動かしたままだとすぐに画面の外側にいってしまうので、 Limit CHOP
を使って特定の範囲の中で折り返すようにしています。
Limit CHOP
で折り返すようにした上で、インスタンスの初期位置を決定している Grid SOP
を十分に大きくすると空間全体に一様に広がりつつループ的なアニメーションをするシーンが作れます。
CHOPレベルのアニメーション2
↓ の動画では、さきほど作ったシーンに対してさらにCHOPでエフェクトを加えています。
位置のアニメーションを加えたCHOPにさらに Noise CHOP
を接続して、細かいレベルのアニメーションを作り、それを Math CHOP
を使って Combile CHOPs
> Add
で 加えることで、大きな動き + 小さな動き というふうな動きのレイヤーを重ねることができます。
また、小さな動きのほうを Rename CHOP
を使って c[rgb]
にチャンネル名を変更し、Marge CHOP
でまとめたものをインスタンスのソースに使うことで、シーン側のインスタンスのほうにも着色することができます。
GLSLを使ってジオメトリにエフェクトをかける
GLSLとは?
GLSLは、OpenGL Shading Language の略で、C言語によく似た構文でGPUの内部で処理されるプログラムを書くことができます。ひらたく言うと、メチャ高速な3D頂点データ、カラーデータ専用のプログラミング言語 です
TouchDesignerでは、今回紹介する GLSL MAT
を使って独自のカスタムマテリアルを作るほか、GLSL TOP
を使ってテクスチャに対してエフェクトを作ることができますが、TOPのほうはまた次の機会にしようと思います
まずは Geometry COMP
を用意します。その後 GLSL MAT
を作り、Geometry COMP
にアタッチします。
GLSL MAT
を作ると Text DAT
が複数作られます。
それぞれ、Vertex Shader (頂点データ用のシェーダー)、Pixel Shader(カラーデータ用のシェーダー)、エーラーログ等が表示されるDAT です。
GLSL MAT
を作った時には、 Vertex Shaderは ↓ のようになっているはずです。
// Example Vertex Shader
void main()
{
vec4 worldSpacePos = TDDeform(P);
gl_Position = TDWorldToProj(worldSpacePos);
}
それを、こう ↓ 書き変えてみましょう。TDDeform
のカッコの中が変更されています。
// Example Vertex Shader
void main()
{
vec4 worldSpacePos = TDDeform(P + vec3(1, 0, 0)); // !!!
gl_Position = TDWorldToProj(worldSpacePos);
}
これは、入力されたジオメトリの情報を、X方向に1ユニット動かせ という処理のシェーダーとして動きます。
また、Pixel Shaderのほうは 最終的に変数 fragColor
に入っている色で描画されることになっているので、
// Example Pixel Shader
// uniform vec4 exampleUniform;
out vec4 fragColor;
void main()
{
TDCheckDiscard();
vec4 color = vec4(1.0);
TDAlphaTest(color.a);
fragColor = TDOutputSwizzle(color);
}
となっているのを、
// Example Pixel Shader
// uniform vec4 exampleUniform;
out vec4 fragColor;
void main()
{
TDCheckDiscard();
vec4 color = vec4(1.0);
color.rgb = vec3(1, 0, 0); // !!!
TDAlphaTest(color.a);
fragColor = TDOutputSwizzle(color);
}
として、変数 color
を途中で変更してしまうか、
// Example Pixel Shader
// uniform vec4 exampleUniform;
out vec4 fragColor;
void main()
{
TDCheckDiscard();
vec4 color = vec4(1.0);
TDAlphaTest(color.a);
fragColor = TDOutputSwizzle(color);
fragColor.rgb = vec3(0, 1, 0); // !!!
}
として最後の最後で fragColor
を書き換えれば任意の色に変更できます。
Phong MATをGLSL MATに変換する
TouchDesignerの強力な機能として、既存の Phone MAT
や PBR MAT
を GLSL MAT
に変換できる、というものがありますので紹介します。
さきほど説明した GLSL MAT
だと、たしかにシェーダーは書けるようになるのだが、あまりにもプリミティブな所からのスタートになってしまうのでGLSLのプログラミングを相当勉強しないといい感じのレンダリング結果は出ません。
ですが、Output Shader
機能を使うと途中までパラメーターを調整していい感じにしたマテリアルを GLSL MAT
として書き出し、Phone MAT
などだけでは実現できなかった事を、自らカスタムすることによって独自のマテリアルを作ることができます。
Phone MAT
を調整していい感じになった所で、 RGB
> Output Shader...
のボタンを押すと、その時点でのパラメタ変更が適応された GLSL MAT
に変換されます。
変換されて出てきたシェーダーコードは結構分量が多くなっているのですが、TDDeform(P)
のあたりが頂点情報を扱っている、という所は変わらないのでさきほどの GLSL MAT
の例と同じくオフセット等を変更することができます
テクスチャによってジオメトリを変形させるシェーダー
折角GLSLを使っているのに右に1移動させてばっかでもしょうがないので、テクスチャの色情報を使って頂点を動かしてみましょう。
GLSL MAT
でテクスチャを扱うには2ステップあります。
1. GLSL MAT
のパラメーターを編集する
Sampler 1
> Sampler Name
, TOP
を編集します。
TOP
には、使いたいTOPをアサインします。今回だと Noise SOP
を指定しました。
Sampler Name
には、GLSLコード側でどういう名前にするかを指定します。とりあえず uNoise
にしました。
2. GLSLコードを編集する
動画の中で最終的にできたコードはこちらです
uniform sampler2D uNoise;
void main()
{
vec4 c = texture(uNoise, uv[0].xy);
vec4 worldSpacePos = TDDeform(P + c.xyz);
gl_Position = TDWorldToProj(worldSpacePos);
}
まず、GLSLコード側で、 GLSL MAT
で指定したパラメタを使うぞという意思を表明します。 uniform sampler2D uNoise;
という部分がそれです。その宣言以降、 uNoise
という名前でテクスチャの情報にアクセスすることができるようになります。
そして、GLSLの texture()
関数で、どのテクスチャのどの部分の色をもらってくるかを指定して、テクスチャの色情報をひっぱってきます。どの部分かに関しては、ほとんどの場合、uv[0].xy
を指定していればOKです。
uv[0]
は、P
と同じように、TouchDeisnger側で用意してくれている変数で、SOPのアトリビュートから自動的にマッピングされています。詳細はこちら → Write a GLSL Material - Derivative
vec4 c = texture(uNoise, uv[0].xy);
として、色情報を uv[0]
をキーにして取得したら、それをまた TDDeform(P + c.xyz)
として頂点の位置を動かすパラメタとして使います。これでテクスチャを使った頂点アニメーションができました
TOP側の調整
シェーダーができたら、TOP側でテクスチャを変更してどういうアニメーションにするかを調整できます。
Noise TOP
であれば Monochrome
を Off
にすることでカラーノイズになるので、xyzの軸に対して動くようになりますし、Common
> Pixel Format
を 16-bit float(RGBA)
にすることで、0-1以上の値でも動いてくれるようになります