先日、 VFX-JS Ver.1.0 をリリースしました。
VFX-JS は、Web 上の画像・動画・テキストに対して WebGLで 視覚的なエフェクトを加えるライブラリです。他のWebGLライブラリと比べて、canvasのセットアップが自動化されていることや、画像・動画の HTML 要素をそのまま入力として渡せるのが特徴です。
例えば、このようなエフェクトをWeb上で実現できます:
CRT-like post effect with VFX-JS #WebGL #VFXJS #Codepen pic.twitter.com/evFae2H06E
— 𝘼𝙈𝘼𝙂𝙄 (@amagitakayosi) June 26, 2025
Pixel Stretch + Gradient Map + Dither #VFXJS pic.twitter.com/3l0iAiH0Dd
— 𝘼𝙈𝘼𝙂𝙄 (@amagitakayosi) June 30, 2026
Fluid simulation on normal HTML elements, using VFX-JS.
— 𝘼𝙈𝘼𝙂𝙄 (@amagitakayosi) April 7, 2026
You can try it on Codepen (link below)#WebGL #VFXJS pic.twitter.com/sQhtsdfgSh
Pixelsort on HTML-in-Canvas demo.
— 𝘼𝙈𝘼𝙂𝙄 (@amagitakayosi) May 27, 2026
Built with VFX-JS#WebGL #VFXJS pic.twitter.com/Xt9DKOBAUl
VFX-JS supports HTML-in-Canvas now.
— 𝘼𝙈𝘼𝙂𝙄 (@amagitakayosi) April 14, 2026
You can turn HTML element into a WebGL texture.
It automatically detects the browser and fallback to the old SVG foreignObject workaround.
So it works on Chrome, Firefox, and Safari, of course!#WebGL #VFXJS #Codepen pic.twitter.com/2At40C6DHV
このライブラリは前身の REACT-VFX から6年ほどチマチマ開発を続けていますが、最近大きめの機能追加と、APIの大幅なリニューアルができたので、改めてバージョン 1.0 としてリリースすることにしました。
この記事では VFX-JS の概要と、今回実装した新機能について紹介します。 あわせて、リリースに関して考えたことについても書いていきます。
VFX-JS とは
VFX-JS はその名の通り、Web 上の画像や動画に視覚的な効果(ビジュアルエフェクト)を付与できるライブラリです。 例えば、CSSではできない細かい色の調整や、色収差エフェクト、グリッチ、グロー、ハーフトーンといった、Webで実現しづらいエフェクトなどを手軽に使用できます。 他のライブラリと比べてとにかくセットアップが簡単で、HTML要素に一発ででエフェクトをかけられるのが特徴です。
const vfx = new VFX(); vfx.add(img, { effect: [new BloomEffect()] });
WebGL を使ったWeb開発では、全てのオブジェクトを WebGLの3D空間上でレイアウトする必要があります。 一般的なWeb 開発のような CSS での位置/サイズ指定ができないため、通常のテキスト要素やWeb独自の要素と組み合わせるのが難しい、という問題があります。
VFX-JS では、 HTML 上の要素の配置をもとに、 WebGL のキャンバス上へオブジェクトを自動で配置し、ページのスクロールや要素の移動にも自動で同期します。これにより、通常の Web 開発フローのまま WebGL エフェクトを書けるのが特徴です。

また、画像や動画だけでなくテキスト要素にもエフェクトをかけられるのが強みの一つです。これはもともと、SVG の foreignObject を使って HTML を Canvas に変換するというハックによって実現していました。しかし今回、HTML-in-Canvas という API がブラウザに実装されたことで、より高度な表現が可能になりました (後述)。
新機能
HTML in Canvas サポート
今回、Chrome が「HTML in Canvas」をサポートしたことで、HTML 要素の描画結果をそのまま WebGL のテクスチャとして読み込めるようになりました。 VFX-JS でもこれをサポートしています。従来のtextキャプチャ機能と区別するため、新たに API を用意しました。
const el = document.querySelector("#div");
vfx.addHTML(el, { effect: [...] });
VFX-JS はもともと div のキャプチャ自体には対応していたが、これまでは SVG の foreignObject 機能を使って HTML を無理やり Canvas に変換する(HTML → SVG → Canvas → texture)という方法を取っていました。この方法にはいくつか制限があり、例えば CSS のスタイルを完全に再現できなかったり、Web フォントのサポートが現実的に不可能だったりしました。
しかし、HTML-in-CanvasAPI では ブラウザが実際にレンダリングした HTML の出力をそのまま Canvas として読み込めるため、これまでできなかった Web フォントもバッチリサポートできるようになりました。実際に HTML Canvas を使ったデモをいくつか用意してあります。
- https://amagi.dev/vfx-js/examples/works/liquid-glass
- https://amagi.dev/vfx-js/examples/works/halftone
HTML-in-Canvas API は Firefox でもすでに実装されてるけど、まだいくつか制約があります(動画が再生できない等)。 CSS animationは動作するので、アニメーションが一律でブロックされているわけではなさそうだけど、この辺りはブラウザの対応次第という状況です。
とはいえ、確実に表現の幅は広がっており、実際、WebGL 界隈の人たちはこぞって HTML-in-Canvas で面白いデモを作って公開しています。 このAPIがモダンブラウザで安定して使えるようになれば WebGL の状況は大きく変わると思うので、VFX-JS でも積極的にサポートしていきたいと思っています。
Effect API
今回、Effect というinterfaceを定義し、ユーザーが自分でエフェクトを実装して配布や再利用できるAPIを公開しました。
以前の VFX-JS では、ユーザーがシェーダー (GLSLのコード) とパラメータを指定するという形になっていましたが、それには様々な制限がありました。 例えば、パラメータのデフォルト値を定義したり、マウスクリックに応じて内部状態を変化させる、といったケースです。
これまでは、ユーザー側の JS で状態を管理してもらうという設計になっていて、僕が CodePen に投稿していたデモもそのような形を取っていました。 ただ、これはさすがに扱いづらく、もう少し親切なAPIを提供したいと考えていました。
そこで今回、エフェクトを Effect インターフェースとして定義しました。
エフェクトが内部状態を自分で更新したり、テクスチャ等のリソースも持てるようになり、パーティクルや流体シミュレーションのような複雑なエフェクトも閉じたオブジェクトとして扱えるようになりました。


また、これらのエフェクトは重ね掛けできるので、例えば Scanline と Bloom を組み合わせて CRT ディスプレイを再現したり、グラデーションとハーフトーンを組み合わせてポップな表現ができたりします。

このエフェクトはユーザーが自分で再利用したり、npm で他の人に配布したりすることもできます。 VFX-JS 本体にも新たにエフェクトパッケージを用意し、別の npm パッケージとしてプリセットを配布するようにしました(後述)。
@vfx-js/effect パッケージの追加
従来のシェーダープリセットや、最近開発したエフェクトをまとめて @vfx-js/effect として公開しました。
実装済みのエフェクト一覧:
- AsciiEffect (アスキーアート化)
- BadJpegEffect (JPEG圧縮劣化シミュ―レート)
- BloomEffect
- ChromaticEffect
- ColoredEdgesEffect
- DatamoshEffect (データモッシュ)
- DitherEffect
- DuotoneEffect
- FluidEffect
- GlitchEffect
- GradientMapEffect
- HalftoneEffect
- HueShiftEffect
- JPEGGlitchEffect (JPEGグリッチ)
- MatrixEffect (Matrix風の文字降下)
- ParticleEffect
- ParticleExplodeEffect
- PatternRefractionEffect
- PixelStretchEffect
- PixelateEffect
- PixelSortEffect
- RainbowEffect
- RgbGlitchEffect
- RgbShiftEffect
- ScanlineEffect
- SinewaveEffect
- SliceShiftEffect
- TilePixelateEffect
- TritoneEffect
- VignetteEffect
- VoronoiEffect
- WarpEffect
これらのエフェクトはStorybookで試せるようにしています: https://amagi.dev/vfx-js/storybook/?path=/story/effect--bloom
使用する際は、 @vfx-js/core と合わせてimportしてください:
import { VFX } from "@vfx-js/core"; import { BloomEffect } from "@vfx-js/effects"; const vfx = new VFX(); vfx.add(img, { effect: [new BloomEffect()] });
Three.js 依存の削除
VFX-JSはThree.jsを使って実装していたけど、今回 WebGL を直で叩くようにして、 Three.js 依存を削除しました。
もともと Three.js を利用していたのは、開発がラクというのもあるけど、より多くの人がコードを読んで理解しやすいだろうという理由でした。 しかし、実際の所PRがたくさん来るわけでもなく、むしろ Three.js 依存によって容量が大きくなっていたので、利点を上回っていました。
というわけで、今回は Claude Code の力を借りて、生の WebGL API への移行を行いました。 VFX-JSは Three.js の機能のうち極々一部しか使っていなかったので、移行はほぼ一瞬で完了し、ビルドサイズはほぼ5分の1になりました。もっと早くやればよかった……。
この際、WebGL ではなく WebGPU に移行してしまうことも考えたけど、既存エフェクトとの互換性の問題があるため見送りました。 シェーダーをビルド時に自動変換する等もやろうと思えば可能ですが、WebGL と WebGPU では Y 軸の向きが逆になるなど互換性の問題があるため、良いアイデアが思い浮かぶまでは保留にしています。
Example ギャラリーの作成
VFX-JS で何かデモを作ったときは CodePen で公開していたのですが、自作ライブラリの機能紹介ばかりを CodePen に投稿するのは行儀が悪いだろうという点と、動画や画像を使ったデモは CodePen だと作りづらいという点があり、新たに Example ギャラリーページを作成することにしました。
ギャラリーのデザインは Claude Design でいくつかアイデアを出してもらい、それをベースに自分で手直ししたものです。 これで自由にデモを作れるようになったのですが、CodePen で公開していたときより明らかに反応が鈍いので、CodePen とギャラリーページの棲み分けについては、もう少し考え中です……😇
感想
VFX-JS は、2020年に僕がリリースした REACT-VFX というライブラリがベースになっている。 当時は React の Provider API でページ全体を1枚のcanvasで覆い、アプリ内の画像や動画の位置をトラッキングするという設計だった。 その後、React前提をやめてVFX-JSという名前でリリースし直した。生のHTML要素を直接引数で渡して、エフェクトの実装を気軽に始められるようにした。
そう、ライブラリの主眼としては「誰でも再利用できるエフェクト」というより、「エフェクトを気軽に開発するためのライブラリ」という位置づけだった。
WebGLの文脈では、誰でも再利用できるエフェクトというのは実はあまり求められていない。というのも、WebGLでのWeb開発というのはつまり「他にはないWebサイト」をいかに作るかということであって、他と同じでいいならわざわざWebGLを使う必要もないからだ。 VFX-JSは、最初から後者がメインのつもりだったんだが、GLSLを書くハードルが高すぎたのと、「誰でも再利用」というクリシェに引っ張られて、単なるpreset集になってしまっていた感じがする。プリセットについても、ある程度複雑なエフェクトになると以前の仕組みでは配布が難しく、本当にシンプルな物しか同梱できなかった。
「自分でエフェクトを開発するためのライブラリ」として、より凝った処理をするための Effect API やマルチパス対応は、それこそ2020年からやりたいな〜と思ってはいたものの、時間も実装力も足りずに実現できずにいた。
今年の春に HTML-in-Canvas が実装され始めたのと、Vercel のエンジニアがVFX-JSとほぼ同じ事をやってバズっていたのを見て、久しぶりに開発の機運が高まった。やりたいことは固まっていたので、 Claude Code をバシバシしばくことで、やっとこさ v1.0 にこぎつけた、というお話。
シェーダーの開発は以前としてハードルが高いとは思うんだけど、それこそAIの力を借りれば、WebGLの知識がない人でもある程度サクっとエフェクトが作れると思う。今回あらたにプリセットに追加したeffectでも、寝る前にClaudeに指示を投げて、出来上がってきたものを調整して作ったものが多数ある。AIはまだWebGLの描画結果を正しく解釈/評価できるほどには賢くなっていないが、期待する仕様、挙動、バグについて伝えれば、シェーダーは勝手に書いてくれる。
先日のFigma ConfigではFigma Shadersが発表されたが、これもユーザーにシェーダーを書かせるのではなく、ユーザーのプロンプトに対してAIがシェーダーを勝手に実装するという流れになっている。 シェーダーに限らず、UIコンポーネントでもなんでも、全体的なデザインの舵取りは人間がしつつ、個々のコンポーネントはAIがたたき台を作って調整する、という流れになっていくんだと思う。それでもマニエリスムというか、手でコードをこねくり回しているときにだけ訪れる閃きというのは存在するので、やはり我々はエディタを捨て去ることはできないのだが……。
今度、Claude Codeでエフェクトを実装するチュートリアルでも作ってみようかと思っている。




