glslsandbox のシェーダを簡単にインポート可能な超軽量ライブラリ fragmen.js を作った話

## 背景

GLSL は WebGL の登場によりブラウザ上で簡単に実行することができるようになりました。

ハイエンドなグラフィックスをリアルタイムに描画することの難しかったウェブブラウザに、WebGL と GLSL がもたらした恩恵はとても大きいものであると確信できる一方で、これらを導入したり、あるいは導入するために学習したりといったことには、通常のフロントエンドの開発とはちょっと異なる知識や考え方が必要となり、とても敷居の高いものになっています。

誤解のないように一応書いておくと、ネイティブアプリケーションとして GL 実装を作ることに比べれば、WebGL + GLSL の実装の手軽さは比較するまでもないくらい簡単です。しかしそれがウェブを舞台に活躍するエンジニアのみなさんにとって、体感として簡単・手軽なものであるかは必ずしも一致しないでしょう。これは単に、慣れの問題であるとも言えますし、得意分野の違いという風に捉えることもできると思います。

しかし、WebGL と GLSL を用いることで実現できるハイエンドグラフィックスの素晴らしさは、知らずに終わらせてしまうにはあまりにも惜しいものだと個人的には思っています。

また、広い視点で見れば、ウェブがこれから先進化を続けていくなかで、必ず今以上に高い表現力を求められる場面が増えてくるはずです。足踏みするのは簡単ですが、ここはひとつ、あくまでも可能性のひとつとしてで構いませんので、WebGL や GLSL の持つ魅力の一端を感じてほしい。そんな思いで、勉強会や、スクールの運営、ワークショップなどの開催などを行なってきました。

そのようなイベント等を主催していくなかで感じることには、本当にいろいろなことがあり、ある意味ではとりとめのないものです。ただそのなかのひとつの側面を抜き出して考えたとき、「GLSL を単なるツールのひとつ」として、ウェブ表現におけるアクセントに使うだけのカジュアルな用途があってもいいのではないか、と私は最近思うようになりました。

たとえばウェブページを装飾するためにフリー素材の画像やウェブフォントを使うのと同じように、シェーダだってもっとカジュアルに、様々なところで活用されていいはずだと私は思っています。

> ただしこの話をする上では、シェーダのコードに著作権があるのかといった、ちょっと面倒だけども大切な問題も絡んできますね。この場でその議論をしようという意図はありませんし、今回ご紹介する自作ライブラリが、シェーダコードの盗用を推奨するものではないことは明記しておきたいと思いますが、ウェブ上で公開されている多くの画像やイラスト、テキストなどがそうであるように、シェーダのコードにも著作権は存在しますので、そのことを踏まえた適切な運用・利用が求められることは言うまでもありません。

fragmen.js は、[GLSL Sandbox](http://glslsandbox.com/) で公開されているシェーダのソースコードを、簡単にウェブページに配置されたエレメントにアタッチできるものです。もちろん、自分で記述したシェーダのコードを簡単にウェブ上で公開する用途にも使うことができます。要は、glslsandbox 互換のシェーダのソースコードが、簡単に埋め込みできるライブラリと考えていただければいいかと思います。

より具体的には、fragmen.js は指定された HTML Element に canvas エレメントを append し、WebGL による描画処理を実行します。

## 使い方

fragmen.js の使い方は非常に簡単です。

逆に言うと、非常に軽量なライブラリですので、今のところあまり汎用的な作りにはなっていません。できることは非常に単純で **glslsandbox 互換のシェーダのコードを HTML Element にアタッチして実行する** ことだけです。

[fragmen.js DEMO](https://doxas.org/work/fragmen.js/)

![fragmen.jpg](https://qiita-image-store.s3.amazonaws.com/0/39638/14d5f70b-97b5-df57-c550-83fc84bc4498.jpeg)

キャプチャ画像をよーく見るとわかるかと思いますが、fragmen.js は HTML Element に動的に canvas エレメントを append するので、挿入先のエレメントを CSS 等で任意に配置しておけば、そのエレメント全体を覆うような大きさで自動的に実行されます。オプションの指定を行なってやれば、ウィンドウのリサイズイベントに反応してサイズを自動的に調整させるような挙動も勝手にやってくれます。

背景用にスクリーン全体を覆うような DOM を準備しておけば、ページ全体を覆う GLSL エフェクトとして、あるいはコンテンツ上の任意のエレメントにアタッチしてパーツのひとつとして実行させることもできます。

JavaScript では `onload` などのイベントから fragmen.js を初期化し `render` メソッドにソースコードを与えて実行してやるだけでです。

詳しい用法については [Github](https://github.com/doxas/fragmen.js) にも記載してありますが、たとえば以下のようにします。

```javascript
window.addEventListener('DOMContentLoaded', ()=>{
    const source = 'your fragment shader source (compatible with glslsandbox)';
    const target = document.getElementById('target_element');
    const option = {
        target: target,
        eventTarget: window,
        mouse: true,
        resize: true,
        escape: true
    };
    const frag = new Fragmen(option).render(source);
}, false);
```

まあ適当にオプション指定してインスタンス作るだけです。

DEMO を見ればおわかりのとおり、ページ内に複数のインスタンスによる同時描画も問題なく行えます。

また、マウスイベントを利用する場合は、そのマウスイベントを拾ってくるターゲットとなるエレメントも指定できるようになっています。ウィンドウ全体をターゲットにすれば、もちろんページ全体のマウスカーソルの動きに対してインタラクションが得られます。


## 最後に

しつこいようですが、シェーダのコード盗用や、そういった行為を助長させる目的でこのようなライブラリを実装したのではありません。

画像やテキストに対して適切な著作権表記や引用表記が必要なのと同様に、もし glslsandbox からそのままシェーダのコードを持ってきたのなら、少なくとも引用元 URL については明記すべきかなと思います。

このライブラリを作り、また公開していく意図や背景については冒頭に書いたとおり。

私の思いは、GLSL の素晴らしさや楽しさ、あるいはその可能性を多くの人に感じてもらいたい、このことに尽きます。

遠くない未来に、フロントエンドエンジニアのスキルセットのひとつに、GLSL や WebGL を扱うことができること、という項目が加わるでしょう。いやむしろ、もう既にそれは大きなアドバンテージとして認識されつつあるようにさえ、私は感じています。

シェーダや GLSL に対して少しでも興味があるのなら、まずは触れてみましょう。トライしてみましょう。そのなかで、自分自身がそれらの技術とどう向き合うべきかの答えが見つかると思います。

最後に、glslsandbox や three.js など、WebGL 界に多大な貢献をされている Mr.doob に感謝。

[Github - fragmen.js](https://github.com/doxas/fragmen.js)