mcpField
S
shadertoy

shadertoy

github.com/bfollingtonクリエイティブ・メディア521.5k 回インストール2 日前に更新
リポジトリ

shadertoy について

GLSL ES と Shadertoy のシェーダー制作を支援するスキルです。プロシージャルグラフィックスや WebGL フラグメントシェーダー向けに、数学パターン、マルチパス描画、デバッグ、性能調整を扱います。

主な機能

  1. 01GLSL ES の構文と組み込み入力の資料
  2. 02プロシージャルグラフィックスと色のパターン
  3. 03レイマーチングと距離場の手法
  4. 04マルチパス描画とフィードバック
  5. 05シェーダーのデバッグと性能調整

活用シーン

  1. 01.glsl シェーダーの作成や編集
  2. 02ジェネラティブアートやプロシージャルテクスチャの制作
  3. 03レイマーチングによる 3D シーンの実装
  4. 04シェーダーのコンパイルや数値問題のデバッグ

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/bfollington/terma --skill shadertoy

インストール後、Claude Code で/shadertoyを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
common-patterns.md
example-compact-shader.glsl
glsl-reference.md

詳細

Shadertoy シェーダー開発

概要

Shadertoy は、WebGL を使用してブラウザー上で実行する GLSL フラグメントシェーダーを作成・共有するためのプラットフォームです。このスキルでは、GLSL ES の構文、一般的なパターン、数学的手法、リアルタイムのプロシージャルグラフィックスに特化したベストプラクティスなど、シェーダーの作成に関する包括的なガイダンスを提供します。

このスキルを使用する場面

次の場合に、このスキルを有効にしてください。

  • .glsl シェーダーファイルを作成または編集するとき
  • プロシージャルグラフィックス、ジェネレーティブアート、視覚効果を作成するとき
  • Shadertoy.com のプロジェクトや WebGL フラグメントシェーダーを扱うとき
  • レイマーチング、距離場、プロシージャルテクスチャを実装するとき
  • シェーダーコードのデバッグやパフォーマンスの最適化を行うとき
  • GLSL ES の構文リファレンスや Shadertoy の入力変数が必要なとき

基本概念

シェーダーのエントリーポイント

すべての Shadertoy シェーダーは、mainImage 関数を実装します。

void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
    // fragCoord: pixel coordinates (0 to iResolution.xy)
    // fragColor: output color (RGBA, typically alpha = 1.0)

    vec2 uv = fragCoord / iResolution.xy;
    fragColor = vec4(uv, 0.0, 1.0);
}
Shadertoy の組み込み入力

シェーダーでは、次の入力を常に使用できます。

型名前説明
vec3iResolutionビューポートの解像度(x、y、アスペクト比)
floatiTime現在の時刻(秒単位。主なアニメーション駆動要素)
floatiTimeDelta1 フレームのレンダリングにかかる時間
intiFrame現在のフレーム番号
vec4iMouseマウス:xy = 現在の位置、zw = クリックした位置
sampler2DiChannel0-iChannel3入力テクスチャ/バッファー
vec3iChannelResolution[4]各入力チャンネルの解像度
vec4iDate年、月、日、時刻(秒単位)(.xyzw)
座標系の設定

座標を正規化する一般的なパターン:

// Aspect-corrected UV centered at origin (-1 to 1, aspect-preserved)
vec2 uv = (fragCoord.xy - 0.5 * iResolution.xy) / min(iResolution.y, iResolution.x);

// Alternative compact form:
vec2 uv = (fragCoord * 2.0 - iResolution.xy) / min(iResolution.x, iResolution.y);

// Simple normalized (0 to 1)
vec2 uv = fragCoord / iResolution.xy;

一般的なシェーダーパターン

1. プロシージャルカラーパレット

滑らかな色のグラデーションには、Inigo Quilez のコサインパレットを使用します。

vec3 palette(float t, vec3 a, vec3 b, vec3 c, vec3 d) {
    return a + b * cos(6.28318 * (c * t + d));
}

// Example usage:
vec3 col = palette(
    t,
    vec3(0.5, 0.5, 0.5),    // base
    vec3(0.5, 0.5, 0.5),    // amplitude
    vec3(1.0, 1.0, 0.5),    // frequency
    vec3(0.8, 0.90, 0.30)   // phase
);
2. ハッシュ関数(疑似乱数)

ノイズやランダム性に使うシンプルな 2D ハッシュ:

float hash21(vec2 p) {
    p = fract(p * vec2(234.34, 435.345));
    p += dot(p, p + 34.23);
    return fract(p.x * p.y);
}
3. レイマーチング

スフィアトレーシングによる 3D レンダリングの標準的なパターン:

// Distance field function
float map(vec3 p) {
    return length(p) - 1.0;  // Sphere at origin, radius 1
}

// Normal calculation
vec3 calcNormal(vec3 p) {
    vec2 e = vec2(0.001, 0.0);
    return normalize(vec3(
        map(p + e.xyy) - map(p - e.xyy),
        map(p + e.yxy) - map(p - e.yxy),
        map(p + e.yyx) - map(p - e.yyx)
    ));
}

// Ray marching loop
vec3 render(vec3 ro, vec3 rd) {
    float t = 0.0;
    for (int i = 0; i < 100; i++) {
        vec3 p = ro + rd * t;
        float d = map(p);
        if (d < 0.001) {
            // Hit - calculate lighting
            vec3 n = calcNormal(p);
            return n * 0.5 + 0.5;  // Normal visualization
        }
        if (t > 10.0) break;
        t += d * 0.5;  // Step (0.5 factor for safety)
    }
    return vec3(0.0);  // Miss
}
4. 回転

2D 回転:

mat2 rot2d(float a) {
    float c = cos(a), s = sin(a);
    return mat2(c, -s, s, c);
}
// Usage: p.xy *= rot2d(iTime);

3D 軸角回転(インプレースで変更):

void rot(inout vec3 p, vec3 axis, float angle) {
    axis = normalize(axis);
    float s = sin(angle), c = cos(angle), oc = 1.0 - c;
    mat3 m = mat3(
        oc * axis.x * axis.x + c,           oc * axis.x * axis.y - axis.z * s,  oc * axis.z * axis.x + axis.y * s,
        oc * axis.x * axis.y + axis.z * s,  oc * axis.y * axis.y + c,           oc * axis.y * axis.z - axis.x * s,
        oc * axis.z * axis.x - axis.y * s,  oc * axis.y * axis.z + axis.x * s,  oc * axis.z * axis.z + c
    );
    p = m * p;
}
5. ドメインの反復と折り畳み

フラクタルのような構造を作成します。

vec3 foldRotate(vec3 p, float timeOffset) {
    for (int i = 0; i < 5; i++) {
        p = abs(p);  // Mirror fold
        rot(p, vec3(0.707, 0.707, 0.0), 0.785);
        p -= 0.5;    // Translate
    }
    return p;
}
6. ポストプロセス

ビネット:

float vignette(vec2 uv) {
    uv *= 1.0 - uv.yx;
    return pow(uv.x * uv.y * 15.0, 0.25);
}

フィルムグレイン/ディザリング(バンディングを軽減):

float dither = hash21(fragCoord + iTime) * 0.001;
finalCol += dither;

ガンマ補正:

finalCol = pow(finalCol, vec3(0.45));  // ~1/2.2

マルチパスレンダリング

時間的なフィードバックや複数段階のレンダリングが必要な複雑な効果の場合:

Buffer A(計算):
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
    vec2 uv = fragCoord / iResolution.xy;
    // Generate or compute values
    fragColor = vec4(computedColor, 1.0);
}
Buffer B(フィードバック/ブレンド):
#define BUFFER_A iChannel0
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
    vec2 uv = fragCoord / iResolution.xy;
    vec4 current = texture(BUFFER_A, uv);
    vec4 previous = texture(iChannel1, uv);  // Self-reference
    fragColor = mix(previous, current, 0.1);  // Temporal blend
}
Main(最終出力):
#define BUFFER_B iChannel1
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
    vec2 uv = fragCoord / iResolution.xy;
    fragColor = texture(BUFFER_B, uv);
}

GLSL ES の重要なルール

コンパイルエラーを避けるため、必ず次のルールに従ってください。

  1. f 接尾辞は禁止:1.0f ではなく 1.0 を使用します
  2. saturate() の使用は禁止:代わりに clamp(x, 0.0, 1.0) を使用します
  3. pow/sqrt を保護する:引数を pow(max(x, 0.0), p)、sqrt(abs(x)) のようにラップします
  4. ゼロ除算を避ける:分母をチェックするか、イプシロンを加えます
  5. 変数を初期化する:デフォルト値を前提にしないでください
  6. 名前の競合を避ける:関数に変数のような名前を付けないでください
  7. 対話型コマンドは禁止:find、grep は避け、代わりに Glob/Grep ツールを使用します

ワークフローガイド

新しいシェーダーの作成
  1. 座標系を設定する - 適切な UV 正規化方法を選択します
  2. 効果の中核を定義する - メインの視覚的アルゴリズムを実装します
  3. アニメーションを追加する - 時間的な変化に iTime を使用します
  4. カラーパレットを適用する - コサインパレットまたは独自の配色を使用します
  5. ポストプロセスを追加する - ビネット、ディザリング、ガンマ補正を追加します
  6. 最適化する - 反復回数を減らし、早期終了を利用して、分岐を最小限に抑えます
よく使うタスク

複素数の可視化:

  • references/common-patterns.md の複素数演算関数を使用します
  • cx_log()、cx_pow()、または多項式の評価でプロットします
  • 複素数の結果をパレットで色に変換します

3D シーンのレイマーチング:

  • map() 関数で距離場を定義します
  • カメラを設定します(レイの原点 ro、レイの方向 rd)
  • 標準的なループパターンでレイマーチングします
  • 四面体法で法線を計算します
  • ライティングとマテリアルのプロパティを適用します

ノイズや有機的なエフェクトの作成:

  • 乱数値には hash21() を使用します
  • 自然な変化を加えるために fbm()(フラクタルブラウン運動)を実装します
  • sin()/cos() と組み合わせて規則的なパターンを作成します
  • ドメインワーピングを適用して有機的な歪みを加えます

複数レイヤーの合成:

  • 異なるパラメーターで複数のパスをレンダリングします
  • mix() または独自のブレンドモードでレイヤーをブレンドします
  • レイヤー間の差分を比較して干渉パターンを追加します
  • smoothstep() で滑らかな遷移を作成します
デバッグの戦略

中間値を可視化する:

fragColor = vec4(vec3(distanceField), 1.0);  // Show distance
fragColor = vec4(normal * 0.5 + 0.5, 1.0);   // Show normals
fragColor = vec4(fract(uv), 0.0, 1.0);       // Show UV tiling

段階的に簡略化する:

  • ポストプロセスをコメントアウトします
  • 反復回数を減らします
  • 複雑な関数を単純なプレースホルダーに置き換えます
  • 座標変換をステップごとに確認します

NaN/Inf を確認する:

  • ガードを追加します:if (isnan(value) || isinf(value)) return vec3(1.0, 0.0, 0.0);
  • 除算と平方根を検証します

パフォーマンスの最適化

  1. 反復回数を固定する - 動的ループを避けます
  2. 早期終了条件 - しきい値に達したら終了します
  3. ステップ倍率の調整 - 品質と速度のバランスを取ります(0.5~1.0)
  4. テクスチャ読み込みを最小限にする - 繰り返し参照する値をキャッシュします
  5. 条件分岐を避ける - if の代わりに mix()、step()、smoothstep() を使用します
  6. 精度を下げる - 適切な場合は mediump または lowp を使用します(モバイル)

命名規則

クリエイティブな作品で見られるパターンに基づいています:

  • 詩的・印象的な名前 - "alien-water"、"heavenly-wisp"、"comprehension"
  • 技術的な説明名 - "complex-plot"、"noise-circuits"、"ray-marching-demo"
  • 複合語句 - "coming-apart-at-the-seams"、"form-without-form"
  • 小文字とハイフンを使用 - my-shader-name.glsl

クレジット表記とフォーク

シェーダーをフォークまたはリミックスする場合:

// Fork of "Original Name" by AuthorName. https://shadertoy.com/view/XxXxXx
// Date: YYYY-MM-DD
// License: Creative Commons (CC BY-NC-SA 4.0) [or other]

リソース

references/glsl-reference.md

GLSL ES の構文を網羅したリファレンスです。以下の内容を含みます:

  • 組み込み関数(三角関数、数学、ベクトル、行列、テクスチャ)
  • Shadertoy の入力変数の仕様
  • 型変換とスウィズリング
  • よくある落とし穴と修正方法

言語リファレンスの全文を確認するには、Read /references/glsl-reference.md で検索します。

references/common-patterns.md

包括的なパターンライブラリです。以下の内容を含みます:

  • 複素数演算(cx_mul、cx_div、cx_sin、cx_cos、cx_log、cx_pow)
  • カラーパレット関数(コサインパレット、複数レイヤーのパレット)
  • ハッシュ関数(hash21、PCG hash)
  • レイマーチングのテンプレート(レンダリングループ、法線計算)
  • 3D 変換(回転、ドメインの折りたたみ)
  • 距離場(球、ボックス、八面体)
  • ノイズ関数(シンプレックス、FBM)
  • ポストプロセス(ビネット、ぼかし、フィルムグレイン、ガンマ)
  • ブレンドモード(ソフトライト、ハードライト、ビビッドライト)
  • マルチパスレンダリングのパターン

特定の手法を検索するには、Grep "pattern" references/common-patterns.md を使用します。

references/example-compact-shader.glsl

以下の内容を示すリファレンス実装です:

  • コンパクトでアルゴリズム重視のシェーダーのコーディングスタイル
  • 最小限のコードで効率的に行うレイマーチング
  • 高度な行列演算と変換
  • クリエイティブ・コモンズライセンスのサンプル

クイックリファレンス

#define PI 3.1415926535897932384626433832795

void mainImage(out vec4 fragColor, in vec2 fragCoord) {
    // 1. Normalize coordinates
    vec2 uv = (fragCoord * 2.0 - iResolution.xy) / min(iResolution.x, iResolution.y);

    // 2. Compute effect
    float d = length(uv) - 0.5;  // Circle distance field
    vec3 col = vec3(smoothstep(0.01, 0.0, d));  // Sharp edge

    // 3. Animate with time
    col *= 0.5 + 0.5 * sin(iTime + uv.xyx * 3.0);

    // 4. Apply palette
    col = palette(col.x, vec3(0.5), vec3(0.5), vec3(1.0), vec3(0.0));

    // 5. Post-process
    col = pow(col, vec3(0.45));  // Gamma
    col *= vignette(fragCoord / iResolution.xy);

    // 6. Output
    fragColor = vec4(col, 1.0);
}

コレクション内でよく使われるシェーダーの種類

  1. 数学的な可視化 - 複素数プロット、関数グラフ
  2. レイマーチングによる3D表現 - 距離場レンダリング、折り畳まれた幾何形状
  3. プロシージャルテクスチャ - ノイズベースのパターン、有機的なエフェクト
  4. マルチパスエフェクト - 時間的フィードバック、バッファ合成
  5. パーティクルシステム - 点ベースのシミュレーション
  6. 2D パターン - 幾何学的、万華鏡的、干渉エフェクト

クリエイティブコーディングのヒント

  • シンプルに始める - まず基本的な構造を動作させてから、改良を重ねます
  • 時間を工夫して使う - sin(iTime)、mod(iTime, period)、smoothstep()によるトランジションを活用します
  • エフェクトを重ねる - 複数の手法を組み合わせて、豊かな表現にします
  • 偶然を受け入れる - バグが興味深いビジュアルにつながることもあります
  • 参考資料を調べる - 既存のシェーダーから学び、手法を理解します
  • 最適化は後回しにする - まずビジュアル品質を優先し、その後でパフォーマンスを改善します

コメント