GLSL ライブコーディング¶
どのノードも、中身は全画面のフラグメントシェーダーです。 自分のシェーダーを書く GLSL ノードを作れるほか、組み込みノードのシェーダーも編集できます。保存するとその場で反映されます。
GLSL ノードを作る¶
- ノードピッカーの GLSL タブ →
GLSL (new file)で、新しいシェーダーファイルを持つノードを作ります。 - 同じタブのファイル一覧(
shaders/user/*.frag)から選ぶと、そのファイルのコピーを持つノードになります。
各ノードは自分のファイルを持ち(プロジェクトの shaders/)、編集してもそのノードだけが変わります。
編集する¶
- アプリ内: ノードを選んで SHADER タブ。入力が止まったとき、または Ctrl+S / Cmd+S で保存します。
- エージェントに頼む: SHADER タブの
ASK AN AGENTに言葉で書くと、AI エージェントがシェーダーを書きます(AI エージェント連携)。 - 外部エディタ: NODE タブか SHADER タブの
OPEN IN EDITOR。エディタはLEMONADE_EDITOR、$VISUAL、$EDITORの順に探します(例:LEMONADE_EDITOR="code --reuse-window")。
保存すると、#include したファイルの変更も含めてホットリロードされます。
コンパイルに失敗したときは直前のバージョンが動き続け、エラーが行番号付きでノードと SHADER タブに表示されます。
組み込みノード(Blur など)のシェーダーを編集すると、最初の編集でそのノード専用のコピーができます。ほかのノードは組み込みのままです。
REVERT TO BUILT-IN でコピーを捨てて元に戻せます。
シェーダーの書き方¶
#version 450
#include "util/common.glsl"
layout(location = 0) in vec2 v_uv; // 0..1、左上が原点
layout(location = 0) out vec4 f_color;
// GLSL ノードのパラメータは、ここに書いたフィールド(順番どおり)
layout(set = 0, binding = 1) uniform NodeParams {
float gain; // 0..2 = 1 範囲と既定値。残りは説明
int shape; // circle|square 選択肢(int)
bool invert; // = true
vec4 tint; // color = 1,0.5,0
};
void main() {
vec3 src = texture(u_tex0, v_uv).rgb; // 最初の入力(未接続なら黒)
float bass = u_bands.y; // 低域
f_color = vec4(src + bass * gain * tint.rgb, 1.0);
}
NodeParamsのfloat/int/bool/vec4(色)のフィールドが、NODE タブのパラメータになります。1 行に 1 つ。//コメントの先頭に、範囲min..max(float の既定 0..1、int は 0..10)、選択肢a|b|c、colorを書き、続けて= 既定値。- 保存のたびに読み直され、名前と型が同じパラメータは値が保たれます。
NodeParamsがない(または読めない)ときは、0..1 のつまみa..dが付きます。- パラメータもワイヤーや式で動かせます(パラメータを動かす)。
エンジンの値(util/common.glsl)¶
| 名前 | 意味 |
|---|---|
u_time |
起動からの秒数 |
u_resolution |
描いているサイズ(ピクセル)。アトラスマッピング中は送出フレームのサイズ |
u_world_resolution |
ショーのフレームのサイズ(ピクセル) |
world_uv(v_uv) |
このピクセルのショーのフレームでの位置(0..1)。アトラスマッピング以外では v_uv |
sample_world(tex, uv) |
入力 tex の、ショーのフレームの位置 uv の色 |
u_level |
全体の音量(0..1) |
u_bands |
帯域(0..1): x sub(20–60 Hz)、y low(60–250 Hz)、z mid(250 Hz–2 kHz)、w high(2–16 kHz) |
fft(i) |
スペクトラムのビン i(64 個、20 Hz–16 kHz、対数) |
u_tex0 … u_tex3 |
入力テクスチャ(ポート順)。未接続は透明な黒 |
u_bpm |
テンポ |
u_phase |
拍の中の位置(0..1) |
u_beat |
拍ごとに 1 になり 0 へ減衰 |
u_beats |
経過拍数(連続値)。floor(u_beats) で拍ごとに 1 進む |
u_palette[8] |
パレットの 8 色 |
palette(t) |
パレットを t(0..1)で補間した色 |
u_triggers |
トリガーパッド 1〜4(x..w)。押すと 1、0 へ減衰 |
u_hits |
帯域ごとのアタック(sub / low / mid / high) |
よく使うパターン(トリガーのフラッシュ、ズームパンチ、ビートのステップ、音への反応)は シェーダーレシピ にあります。
アトラスマッピングに対応する¶
アトラスマッピングの間、ノードは送出フレームのレイアウトで描かれ、v_uv は送出フレームの位置です。会場で継ぎ目なくつながるように描くには:
- 位置に使うのは
world_uv(v_uv)。縦横比はworld_aspect()、ピクセルの大きさはu_world_resolutionで。 - 同じピクセルの入力は、これまでどおり
texture(u_tex0, v_uv)。 - ほかのピクセルの入力(ぼかし、ずらし、回転など)は
sample_world(u_tex0, world_uv(v_uv) + offset)。どのスロットにも映らない位置(スロットの間のすき間)は、近くのスロットの端の色を少しだけ延ばし(フレームの高さの 3 % まで)、その先は透明な黒になります。 util/uv.glslのto_centered/sample_edgeは会場の座標で動きます:to_centered(world_uv(v_uv))。
void main() {
vec2 uv = world_uv(v_uv);
vec2 d = vec2(8.0 * u_scale / u_world_resolution.x, 0.0);
vec3 c = sample_world(u_tex0, uv + d).rgb; // 8 px 右(となりのスロットからでも)
f_color = vec4(c, 1.0);
}
アトラスマッピングを使わないときは、どれも v_uv、u_resolution、texture() と同じです。
Code ノード¶
Code ノードは、ソースコードをシンタックスハイライト付きの映像にします。既定では SHADER パネルで編集中のシェーダーを表示し、入力に合わせて更新されるので、ライブコーディングをそのまま見せられます。 Blend(Add / Screen)で映像に重ねます。