WebGLフレームワークGrimoire.jsとは？

# Grimoire.jsでWeb上でのCG表現をもっと誰でも

![grimoirejs.png](https://qiita-image-store.s3.amazonaws.com/0/147288/3ac8d98f-ba1c-5872-06ec-391cc19e2222.png)

WebGLと聞いて思い浮かべるのはどんな画面でしょうか? フルスクリーンのゲーム? 360度画像プレビュー?

いや、WebGLはもっともっといろんなことに使えます! じゃあどんなことに使えるのか、この後で紹介していくフレームワークのGrimoire.jsの公式のサンプルを先にいくつか覗いてみましょう。

## Webカメラにエフェクトをかけて撮影

<img width="420" height="320" src="https://i.gyazo.com/87bd5da6106df336f1fcfc9bba00b05e.gif"/>
デモ: https://grimoiregl.github.io/grimoire.gl-example/#webcam

あえて全然3DCGではないところから紹介。Webカメラで撮影したものに手軽にエフェクトをかけるのもWebGLがあればできます。

## CSSでは難しいアニメーション


<img width="300" height="300"  src="https://i.gyazo.com/91a5e4f196e4f2cb445fd7c8300a48df.gif" />

デモ: https://grimoiregl.github.io/grimoire.gl-example/#clover

こちらも3DCGではない例。CSSでは難しいようなランダムなエフェクトも作ることが可能です。
(実際にはこの例はシェーダーだけで記述しているため、かなり難しい作成例)

## 3D空間の設置

<img width="420" height="300" src="https://i.gyazo.com/56abf296233dd9a4fd0162a7247d010b.gif"/>
デモ: https://grimoiregl.github.io/grimoire.gl-example/#demo4

もちろんWebGLが本領発揮できる3Dだって扱えます。

---

このように、WebGLでできることは普段私たちが思っているよりも多いのです。特に、昨今ではWebページは**情報が集まる場から機能が集まる場**に変貌を遂げています。このような中でWebGLを用いれば実現できる新たな可能性を模索するのは非常に大きな競争力となるのではないでしょうか。

こんなWebGLをもっともっと簡単に、Web開発の延長線上で扱えるためのライブラリ**Grimoire.js**を今回は紹介します。まだまだ発展途上なライブラリではありますが、興味があったら是非触っていただけたら幸いです。

# Grimoire.jsを見てみる

実際に軽く使っていきながら、Grimoire.jsがどんなフレームワークなのか見ていきましょう。

Grimoire.jsは`npm`からもしくは`<script>`タグで読み込むことにより使用することができます。今回は`<script>`タグで読み込んで使ってみました。

まず公式サイトからGrimoire.jsを[ダウンロード](http://grimoire.gl/guide/download.html)して解凍して`grimoirejs-preset-basic.js`をscriptタグから読み込みます。

同ディレクトリ内に`index.html`、`index.goml`を作成しましょう。

```html:index.html
<!DOCTYPE html>
<html>
    <head>
        <script type="text/javascript" src="./src/grimoire-preset-basic.js"></script>
        <script type="text/javascript" src="./src/main.js"></script>
    </head>
    <body>
        <script id="main" type="text/goml" src="./index.goml"></script>
    </body>
</html>
```

```xml:index.goml
<goml>
    <scene>
        <camera/>
        <mesh geometry="cube" color="green" />
    </scene>
</goml>
```

ディレクトリ構成は以下のようにしました。
> 
root/
　├ index.html
　├ index.goml
　├ src/
　 　└ grimoirejs-preset-basic.js
　　 └ main.js

これでGrimoire.jsは使用可能です。実際に確認してみると、緑の立方体が表示されているはずです。

（実際に表示した例）
<img width="350" alt="sample-image.png" src="https://qiita-image-store.s3.amazonaws.com/0/147288/587098e2-4417-9791-c039-ab72bbe38ce6.png">



---

ところで、HTMLでbodyの中で`script`タグで謎のgomlファイルなるものを読み込んでいるのに気がついたでしょうか?

これこそGrimoire.jsの特筆すべき点の一つです。読み込んでいる`.goml`ファイルはcanvasの中の要素を扱うためのいわば**キャンバスDOM**のような存在で、**差し込んだ場所に対応するcanvasが生成**されて動作するようになっているのです。

このようにWebエンジニアが普段触れているHTMLに近い文法であるXMLの記法の上で、キャンバスを扱えるようになっているのです。

html内に`type="text/goml"`を指定した`scriptタグ`があると、自動的にGrimoire.jsが解釈して動かすのです。

## javascriptで操作する


```js:main.js
gr(function() {
    var colors = ['blue', 'red', 'lime'];
    var i = 0;
    setInterval(function() {
        gr('#main')('mesh')
            .setAttribute('color', colors[i % 3]);
        i++;
    }, 1000);
});
```

<img width="320" src="https://i.gyazo.com/f3daa3c7ef1bf6ea148201080750b869.gif"/>
公式サイトに記載されているものですが、これで立方体の色が変わります。もし、jQueryを使ったことがある人がいたら、何か近しいものをいじったことがあると感じるのではないでしょうか?

jQueryの$のキャンバスDOMバージョンとして、Grimoire.jsは`gr`という変数を定義します。
grの中に関数を渡したら、jQueryではHTMLのDOM構築を待ちますが、Grimoire.jsではキャンバスDOMの構築を待ちます。

HTMLとは異なり、キャンバスは複数存在する可能性があるので、まず、操作する際はどのキャンバスを操作したいのか指定する必要があります。そこで、**gr(`gomlのスクリプトタグへのセレクタ`)(`CanvasDOM内のセレクタ`).`行いたい操作`** のような文法をGrimoire.jsは取ります。
故に、上記の例では、meshのカラー属性が1000msごとに切り替わった動作をするのです。

# まとめ

以上のように、少し特殊な使い方をするWebGLフレームワークですが、一方でWeb開発の中に組み込むのはかなり容易なはずです。 別にunityエンジニアなどを雇う必要もなく、three.jsを使った時のようにイベントドリブンのWebのフローの中にループベースのコードがおり混ざるようなことはありません。

お気付きの方はA-Frameというライブラリに近いと感じるかもしれませんが、Grimoire.jsはもともとjThreeという名前で開発されていたライブラリで、実はもっと前から開発されていた上、今回触れられていないもっと多くの便利機能を備えています。 だれもがcanvas上のタグという形で資産を使い回せるようにする、そのためのフレームワークなのです。

また、このライブラリの開発は、実はIPAの主催する未踏事業の一環のOSSです。Web上でのWeb3D表現をもっともっと当たり前に使えるようにする。そんな未来を切り開いていければいいですね。

さてさて、初日のGrimoire.jsアドベントカレンダーはここまでですが、より興味あれば公式サイトやGithubを是非ご確認下さい。チュートリアルなどではその場で動かして試すことが可能です。(スターも...)

公式サイト: http://grimoire.gl/
GitHub: https://github.com/GrimoireGL/GrimoireJS