Grimoire.jsとは
Grimoire.jsとは、WebGLを既存のWeb開発フロー上で扱うためのフレームワークである。通常のWeb開発側はjQueryでも、ReactやAngularなどのフレームワークでも連携できる。
実際に簡単に以下の様に使うことが可能だ。
<head>
<!--(1)ライブラリ自体を読み込む-->
<script src="Grimoire.jsへのパス"></script>
<!--(2)プラグインを読み込む-->
<script src="プラグインへのパス1"></script>
<script src="プラグインへのパス2"></script>
<script src="プラグインへのパス3"></script>
</head>
<body>
<!--(3)WebGLのキャンバスを埋め込みたいところにtype="text/goml"となる、-->
<!--scriptタグを入れる。これを読み込んでキャンバスが生成される-->
<script type="text/goml">
<goml>
<scene>
<camera/>
<light intensity="3"/>
<model src="./Duck.gltf"/>
</scene>
</goml>
</script>
</body>
Grimoire.jsの場合、上記の様に埋め込みたい要素の中にgomlというXMLベースのマークアップ言語を記述すると、その親の要素にフィットする様にWebGLのキャンバスが用意される様になる。
また、このような属性で値を指定する形式のライブラリはどんな属性があるかわかりにくくなるものだが、Grimoire.jsは独自のChrome拡張を公開しており、以下のように各ノードの属性一覧を見たり値を変えて見たりすることができる。
動的に値を変えるのも容易だ。例えばjQueryのクエリセレクタに近いAPIが用意されていてsetAttributeすることができる。
例えばWebのUI側との連携をjQueryを用いて記述する様なら以下の様になる。
$(".left").on("click",()=>{
gr("*")(".model").setAttribute("position","-3,0,0");
});
$(".right").on("click",()=>{
gr("*")(".model").setAttribute("position","3,0,0");
});
このようにGrimoire.jsの場合、属性を変更するとその結果が通常のHTMLの様に反応する。この様なデータを変えれば即座に反映される様な仕組みは近年のWeb開発の潮流である厳格なリアクティブ性や様々なステートを管理するためのアーキテクチャ上で連動しやすい。
この様な表面上の属性やイベントなどを組み合わせることでWebエンジニアは既存のWebページ開発の中にWebGLの構造を含めることができる。
一方で高度な表現をする際、どうしても3DCG側の操作に特化した記述法が必要である。そこで、Grimoire.jsでは各ノードにくっついている様々な振る舞いを示す部品を誰もが記述することができる。(この仕組み上でGrimoire.jsのすべては成り立っている)
しかもTypescriptで記述ができるので型のある環境に慣れているであろうCGサイドのエンジニアが簡単に記述することができる。
import Component from "grimoirejs/ref/Node/Component";
import ISceneUpdateArgument from "grimoirejs-fundamental/ref/SceneRenderer/ISceneUpdateArgument";
import TransformComponent from "grimoirejs-fundamental/ref/Components/TransformComponent";
import Vector3 from "grimoirejs-math/ref/Vector3";
import gr from "grimoirejs";
class Wave extends Component{
public static attributes = {
amp:{
default:1.0,
converter:"Number"
},
speed:{
default:1.0,
converter:"Number"
}
};
public amp:number;
public speed:number;
private transform: TransformComponent;
public $mount():void{ // 初期化時の処理(UnityでいうとStart)
this.transform = this.node.getComponent(TransformComponent);
this.__bindAttributes(); // bind component attributes to fields
}
public $update(t:ISceneUpdateArgument):void{ // 各フレームでの処理(UnityでいうとUpdate)
this.transfrom.position = new Vector3(this.transform.position.X,Math.sin(this.speed * t.timer.timeInSecound) * this.amp,this.transform.position.Z);
}
}
gr.registerComponent("Wave",Wave); // Waveという名前で機能(コンポーネント)を追加する
例えば、これはWaveという名前で上下に時間に合わせて変化するという機能(コンポーネント)だが、これを以下の様に記述することで各モデルを上下させたりすることができる。
<model src="./Duck.gltf">
<model.components>
<Wave amp="10"/>
</model.components>
</model>
これによりCGに強いエンジニア(特にUnityなどのモダンなゲームエンジンを用いたことのある者)の作成した様々な機能を簡単にWeb常に生かすことができる様になる。
少しだけさらに踏み込んでみる。modelにWaveコンポーネントが付いているノードをwaved-modelと名づけたいとする。
gr.registerNode("waved-model",["Wave"],{},"model");
の様に記述すると、
<waved-model src="./Duck.gltf" amp="10"/>
で先ほどのGOMLのコードと同等のことができる様になる。実際、このようにGrimoire.jsではすべてのタグはこのようにタグを継承して作成されている。Grimoire.jsはこのようにCG側の得意な書き方とWeb側の得意な書き方の架け橋を作るフレームワークなのだ。
他にもHTMLの様な記法でWebGLを扱えるライブラリは少々存在するが、Grimoireは基本的にすべての構造がこの上で成り立っている。レンダラーの仕組みもシーンの仕組みも一つとしてこの法則から外れているものはない。
実際、今回扱ったのは本当に一部で、シェーダーを書くこともできるし、動画をテクスチャに使ったり、レンダラーを差し替えたりといったこともすべてこの延長線上で行える。WebGLを余すことなく、さらに効果的に使えるフレームワークなのだ。
まとめ
Grimoire.jsを使うと、今までのWeb開発の延長線上で開発ができ、結果的にCG系のエンジニアとの分業可能、あるいはリソースの使い回しが可能になる。インスペクタなども提供されていて簡単にデバッグができ、すべての構造はあくまでシンプルに設計されているフレームワークなのですべてその延長線上でWeb上でのCGを記述することができる。
興味があればぜひ公式サイト(https://grimoire.gl )を訪れて見てほしい。また、OSSに興味があったり3DCGのフレームワークの開発などに興味があればぜひ開発チームslack(参加リンク)にも訪れていただきたい。