Shadertoy の shader を抜き取る小さなツール ShadertoyTool
ShadertoyTool は単一ファイルの Python CLI だ。Shadertoy の URL か 6 桁の ID を投げ込むと、shader をソースコードごとテクスチャ・音声・動画まで一括で抜き取ってくれる。ウェブページ上では効果を眺められるだけで、入力リソースを全部揃えようとすると手動で Cloudflare を回避する必要があって面倒なので、いっそ自動化した。
すべての Render Pass(Image / Buffer / Sound / Common)を 1 つの .glsl にまとめて書き出し、各 pass の前にコメントヘッダを付けて出所をはっきり示す。
// ShaderToy ID: XltGDr
// Name: Contra
// Retrieved: 2025-01-01 12:00:00 UTC
// ===== Pass 0: Image (image) =====
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
// ...
}
// ===== Pass 1: Buffer_A (buffer) =====
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
// ...
}
参照しているテクスチャ・音声・動画・Cubemap は全部ダウンロードして <shader_id>_assets/ に入れ、さらに manifest.json を生成して各リソースの URL、ファイル名、ダウンロード状態、参照位置を記録する。これで shader 一式の現場がまるごと揃う。
使い方はシンプルだ。
python fetch_shadertoy.py https://www.shadertoy.com/view/4djyRD
# あるいは ID を直接渡す
python fetch_shadertoy.py 4djyRD
ソースだけでリソースはいらない場合は --skip-assets を付け、出力ディレクトリを変えるには -o を使う。Windows には fetch_shadertoy.cmd があり、まず requests、browser_cookie3、playwright がインストール済みかを確認し、足りないものは pip で自動補完してから実行する。
本当に骨が折れるのは shader のパースではなく、いかに安定してデータを取ってくるかだ。Shadertoy の前には Cloudflare が立ちはだかっていて、直接リクエストするとしょっちゅう門前払いを食らう。そこで、いちばん手軽なものからいちばん力技のものまで、3 段階の fallback を用意した。
- API v1:アプリを作って key を取得し、公式インターフェース
/api/v1/shaders/<id>?key=<key>を通す。Cloudflare を完全に回避でき、いちばん安定するので、一般的には key を設定しておくのを推奨する。 - Legacy POST:key がない場合は、ウェブクライアントを模して
https://www.shadertoy.com/shadertoyに内部リクエストを送る。Cookie はbrowser-cookie3でローカルのブラウザ(Chrome / Edge / Brave / Firefox)から抜き出す。 - ブラウザ fallback:前の 2 つがどちらもダメなら、Playwright でローカルの Edge を立ち上げて認証を突破し、ページ内で
fetchを使って同じインターフェースを叩く。--headlessも可能だ。
リソースのダウンロードも同じ発想で、まず requests で直接引っ張り、403 や Cloudflare に阻まれたものはブラウザコンテキストに投げ込んでリトライし、408/429/500 に当たれば自動でリトライする。スクレイピングは Shadertoy の内部インターフェースと Cloudflare の顔色次第なので、成功率はサイトの状況に応じて上下する。だから key を設定した経路を常に最優先にする。依存は 3 つだけ:requests、browser-cookie3、playwright、Python 3.8+ で動く。