mcpField
S
shadertoy

shadertoy

github.com/ckorhonenクリエイティブ・メディア2247 回インストール5 週間前に更新
リポジトリ

shadertoy について

Shadertoy風のGLSLフラグメントシェーダーを作るための開発リファレンスです。プロシージャルグラフィックスや視覚効果を制作するアーティストや開発者向けに、レイマーチングやマルチパス描画、デバッグ、最適化のパターンをまとめています。

主な機能

  1. 01GLSL ES構文とShadertoy入力
  2. 02プロシージャル描画と色のパターン
  3. 03レイマーチングと距離場
  4. 04マルチパス描画とフィードバック
  5. 05シェーダーのデバッグと性能指針
  6. 06参考パターンとサンプルシェーダー

活用シーン

  1. 01アニメーション付きプロシージャル表現の作成
  2. 02レイマーチングによる3Dシーンの構築
  3. 03フィードバックを使うマルチパス効果の開発
  4. 04GLSLシェーダーのデバッグや最適化

インストール

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

$npx skills add https://github.com/ckorhonen/claude-skills --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()によるトランジションを活用します
  • エフェクトを重ねる - 複数の手法を組み合わせて、豊かな表現にします
  • 偶然を受け入れる - バグが興味深いビジュアルにつながることもあります
  • 参考資料を調べる - 既存のシェーダーから学び、手法を理解します
  • 最適化は後回しにする - まずビジュアル品質を優先し、その後でパフォーマンスを改善します

コメント