この記事は、WebGL Advent Calendar 2018 17日目の記事です。
WebGL採用されない問題
気づけばthree.jsもr99
までバージョンが上がっており、歴史も長く認知度も非常に高いライブラリとなりました。しかし、実際に多くのサイトで使用されているかと言うとそうでもありません。そもそもWebGLを使用したサイトと出会うことも少ないです。なぜなのでしょうか?
① WebGLは難しい
皆さんご存知の通りWebGLを扱うには多くの知識が必要です。そもそも3DCGと関わりのないエンジニアにとってはハードルが高すぎます。筆者も元から詳しい方ではなかったので今もまだ勉強中です。。。しかしthree.jsの登場により、WebGLを簡単に扱えるようになりました。しかしWebGLを採用するサイトが爆増したわけではありません。
② three.jsはファイルサイズが大きすぎる
three.min.js
ファイルは125KB
もあります。昨今ではアクセシビリティの向上を図り、SSRやServiceWorkerによるキャッシュなどページ読み込みを早くする工夫がなされています。そんな中でファイルサイズの大きいライブラリを使用してまでWebGLを採用しようとはならないでしょう。
もっとWebGLを気軽に採用してほしい
これらの問題により、WebGLを採用しているサイトは少し凝ったキャンペンページや、ツール系のサイト、それらを作っているエンジニアのポートフォリオサイトくらいでしかお目にかかれません。自分はもっとサイトの背景やちょっとしたマイクロインタラクションなどに**気軽に使われてもいいのでは?**と日々考えていました。
軽量なthree.jsなら使えるのでは?
筆者のような雑魚WebGL使いにとってやはりthree.jsの使いやすさは格別なものでした。であれば、three.jsの使いやすさを保ったままファイルサイズを抑えられれば気軽にWebGLを採用できるようになるのではと考えました。
作ってみました
ということで軽量版three.jsのshree.jsを作ってみました。(名前は適当です。)詳しくはドキュメントページを作ったのでそちらを参照ください。
主な仕様
- RawShaderMaterialとBufferGeometryのみで扱えるthree.jsを目指す
- なるべくthree.jsとインターフェースを合わせる
- 用意したクラス
- Renderer - THREE.WebGLRendererっぽいやつ
- Scene - THREE.Sceneっぽいやつ
- Camera - THREE.PerspectiveCameraっぽいやつ
- Object3D - THREE.Object3Dっぽいやつ
- Geometry - THREE.BufferGeometryっぽいやつ
- Material - THREE.RawShaderMaterialっぽいやつ
- Mesh - THREE.Meshっぽいやつ
- Points - THREE.Pointsっぽいやつ
- Vector3 - THREE.Vector3っぽいやつ
- Matrix4 - THREE.Matrix4っぽいやつ
- Quaternion - THREE.Quaternionっぽいやつ
簡単な使用例
例えば三角ポリゴンを表示する場合は以下のようなコードになります。
// sample.js
var wrapper = document.getElementById('wrapper');
// レンダラー
var renderer = new SHREE.Renderer();
renderer.setSize(wrapper.clientWidth, wrapper.clientHeight);
wrapper.appendChild(renderer.domElement);
// カメラ
var camera = new SHREE.Camera();
camera.position.z = 2;
// シーン
var scene = new SHREE.Scene();
// マテリアル
var material = new SHREE.Material({
vertexShader: document.getElementById('vs').text,
fragmentShader: document.getElementById('fs').text,
});
// ジオメトリ
var geometry = new SHREE.Geometry();
geometry.addAttribute('position', 3, [
0.0, 0.5, 0.0,
-1.0, -0.5, 0.0,
1.0, -0.5, 0.0,
]);
geometry.addAttribute('color', 4, [
1.0, 0.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0,
]);
geometry.index = [0, 1, 2];
// メッシュ
var mesh = new SHREE.Mesh(geometry, material);
scene.add(mesh);
// 描画
renderer.render(scene, camera);
// vertex shader
attribute vec3 position;
attribute vec4 color;
uniform mat4 pMatrix;
uniform mat4 mvMatrix;
varying vec4 vColor;
void main(void){
vColor = color;
gl_Position = pMatrix * mvMatrix * vec4(position, 1.0);
}
// fragment shader
precision mediump float;
varying vec4 vColor;
void main(void){
gl_FragColor = vColor;
}
three.jsと同じ感覚で描画することができました。
three.jsとの比較
記事の冒頭に貼ったGIFのアニメーションをthree.js版とshree.js版で作成してファイルサイズを比較してみました。尚、three.js版では余分なthree.jsのクラスを読まないようにTree Shakingがされるようにコードを書いています。
three.js版 343KB
[three.js版デモのコードを見たい方はこちら](https://github.com/sawa-zen/three_js_demo/tree/master/points_three)shree.js版 31.8KB
[shree.js版デモのコードを見たい方はこちら](https://github.com/sawa-zen/three_js_demo/tree/master/points_shree)約1/10にダイエット成功!!!
なんと1/10まで軽量化に成功しました!まだ機能が不十分なので軽量になっている部分もありますが、three.jsの便利なコア機能のみを残して不要な部分が削ぎ落すことができました!
まとめ
実は今年(2018年)の夏にdoxasさんのWebGLスクールを受講したのですが、その後何もしていなかったので復習を兼ねてshree.jsを作成していました。まだまだ皆さんに使ってくださいと言えるレベルではないですが、ほそぼそと自分の作品で使用していき少しずつバージョンアップしていこうと思います