shadertoy について
Shadertoy風のGLSLフラグメントシェーダーを作るための開発リファレンスです。プロシージャルグラフィックスや視覚効果を制作するアーティストや開発者向けに、レイマーチングやマルチパス描画、デバッグ、最適化のパターンをまとめています。
主な機能
- 01GLSL ES構文とShadertoy入力
- 02プロシージャル描画と色のパターン
- 03レイマーチングと距離場
- 04マルチパス描画とフィードバック
- 05シェーダーのデバッグと性能指針
- 06参考パターンとサンプルシェーダー
活用シーン
- 01アニメーション付きプロシージャル表現の作成
- 02レイマーチングによる3Dシーンの構築
- 03フィードバックを使うマルチパス効果の開発
- 04GLSLシェーダーのデバッグや最適化
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ ckorhonen/ claude-skills --skill shadertoyインストール後、Claude Code で/shadertoyを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/common-patterns.mdexample-compact-shader.glslglsl-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 の組み込み入力
シェーダーでは、次の入力を常に使用できます。
| 型 | 名前 | 説明 |
|---|---|---|
vec3 | iResolution | ビューポートの解像度(x、y、アスペクト比) |
float | iTime | 現在の時刻(秒単位。主なアニメーション駆動要素) |
float | iTimeDelta | 1 フレームのレンダリングにかかる時間 |
int | iFrame | 現在のフレーム番号 |
vec4 | iMouse | マウス:xy = 現在の位置、zw = クリックした位置 |
sampler2D | iChannel0-iChannel3 | 入力テクスチャ/バッファー |
vec3 | iChannelResolution[4] | 各入力チャンネルの解像度 |
vec4 | iDate | 年、月、日、時刻(秒単位)(.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 の重要なルール
コンパイルエラーを避けるため、必ず次のルールに従ってください。
f接尾辞は禁止:1.0fではなく1.0を使用しますsaturate()の使用は禁止:代わりにclamp(x, 0.0, 1.0)を使用しますpow/sqrtを保護する:引数をpow(max(x, 0.0), p)、sqrt(abs(x))のようにラップします- ゼロ除算を避ける:分母をチェックするか、イプシロンを加えます
- 変数を初期化する:デフォルト値を前提にしないでください
- 名前の競合を避ける:関数に変数のような名前を付けないでください
- 対話型コマンドは禁止:
find、grepは避け、代わりに Glob/Grep ツールを使用します
ワークフローガイド
新しいシェーダーの作成
- 座標系を設定する - 適切な UV 正規化方法を選択します
- 効果の中核を定義する - メインの視覚的アルゴリズムを実装します
- アニメーションを追加する - 時間的な変化に
iTimeを使用します - カラーパレットを適用する - コサインパレットまたは独自の配色を使用します
- ポストプロセスを追加する - ビネット、ディザリング、ガンマ補正を追加します
- 最適化する - 反復回数を減らし、早期終了を利用して、分岐を最小限に抑えます
よく使うタスク
複素数の可視化:
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); - 除算と平方根を検証します
パフォーマンスの最適化
- 反復回数を固定する - 動的ループを避けます
- 早期終了条件 - しきい値に達したら終了します
- ステップ倍率の調整 - 品質と速度のバランスを取ります(0.5~1.0)
- テクスチャ読み込みを最小限にする - 繰り返し参照する値をキャッシュします
- 条件分岐を避ける -
ifの代わりにmix()、step()、smoothstep()を使用します - 精度を下げる - 適切な場合は
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);
}
コレクション内でよく使われるシェーダーの種類
- 数学的な可視化 - 複素数プロット、関数グラフ
- レイマーチングによる3D表現 - 距離場レンダリング、折り畳まれた幾何形状
- プロシージャルテクスチャ - ノイズベースのパターン、有機的なエフェクト
- マルチパスエフェクト - 時間的フィードバック、バッファ合成
- パーティクルシステム - 点ベースのシミュレーション
- 2D パターン - 幾何学的、万華鏡的、干渉エフェクト
クリエイティブコーディングのヒント
- シンプルに始める - まず基本的な構造を動作させてから、改良を重ねます
- 時間を工夫して使う -
sin(iTime)、mod(iTime, period)、smoothstep()によるトランジションを活用します - エフェクトを重ねる - 複数の手法を組み合わせて、豊かな表現にします
- 偶然を受け入れる - バグが興味深いビジュアルにつながることもあります
- 参考資料を調べる - 既存のシェーダーから学び、手法を理解します
- 最適化は後回しにする - まずビジュアル品質を優先し、その後でパフォーマンスを改善します