TypeScriptとThreeJSで遊ぶ(WebGLのフォールバックを考える)


この記事はTypeScript Advent Calendarの16日目の記事です。

この記事では、WebGLの普及率と、 CSS3DRenderer について書きます。
ほとんどTypeScript関係なく、しかも「Naverまとめ」みたいになってしまいました。

## Three.js のレンダラについて

three.jsで3DプログラミングというとWebGL必須な印象がありますが、three.js は他の種類のレンダリング方法にも対応しています。
本体の three.min.js に同梱されているのはWebGLRendererのみですが、リポジトリのexample ディレクトリを見てみると、[example/js/renderer](https://github.com/mrdoob/three.js/tree/master/examples/js/renderers) 内にいろいろな種類のレンダラが格納されています。
このうち、特に使用頻度が高いのは CSS3DRenderer、CanvasRenderer の2種類だと思います。

## CanvasRenderer と CSS3DRenderer の特徴
CanvasRenderer はシェーダ関連の機能を除き WebGLRendererと互換性があります（つまり、WebGLRenderer用のコードはそのままCanvasRendererでも動作します）が、実際には明らかにパフォーマンスが悪く、3Dモデルデータなどは到底表示できません。
ですので、作成するコンテンツは単純なプリミティブ(新鮮でフレッシュ、みたいですが...)の組み合わせにする必要があります。
CSS3Drenderer はWebGLRendererとは根本的に仕組みが異なっており、通常three.js で使用するGeometry や Mesh などのクラスは使用できません。
CSS3DObject、CSS3DSprite(CSS3DSpriteはカメラに対して常に正面を向くという以外、この二つは同じです)のみを使用してコンテンツを作成します。
CSS3DObject は任意のDOM要素をthree.jsから扱うためにラップすることができ、実際の描画は、CSS3 の[transform 3D](http://caniuse.com/#search=transforms3d)を使用して行われます。

## 各ブラウザのWebGL対応状況

現在、WebGLはどれほどのブラウザでサポートされているのでしょうか？
[Can I Use ではこちらのような結果](http://caniuse.com/#search=webgl)になっています。

* Firefox、Chromeは比較的以前から対応しています。
* Safariも対応していることになっていますが、ユーザーが自分で設定変更をしないとWebGLを表示することはできず、デフォルトで有効になったのはYosemite からです。
* IEは11から（リリースは2013年10月）。
* iOSは8（リリースは2014年9月）。
* Android ブラウザは「37」となっていますが、これはAndroidOS 5 (リリースは2014年11月) において、標準ブラウザがChromeベースになったことによるものです。それ以前の標準ブラウザでは、端末メーカーごとに対応状況が異なり混沌としています。

対応する可能性が低かったiOSでも有効化され、WebGLは将来普通に使用できるようになることが確定しました。
しかし、現状ではまだ、フォールバックを考慮しないWebGLのみのコンテンツは、PCで3～4割(2年ほど前のHTML5 Canvasと似てますね)、スマートフォンだと大半のユーザーが閲覧できないことになります。
そこで、上記のCanvasRenderer、CSS3DRenderer をフォールバックとして使用する必要性があります。
WebGLを使用する際、主に問題となるブラウザについて、各レンダラの対応状況は以下のようになっています。

**IE**

|    IE8     |      IE9       |      IE10      |     IE11      |
|:----------:|:--------------:|:--------------:|:-------------:|
|   非対応    | CanvasRenderer | CanvasRenderer | WebGLRenderer |

**iOS**

|      iOS6       |       iOS7     |     iOS8      |
|:---------------:|:--------------:|:-------------:|
|  CanvasRenderer/CSS3DRenderer  |  CanvasRenderer/CSS3DRenderer | WebGLRenderer |

**Android(標準ブラウザ)**

|    < Android4     |                 Android4.x               |      Android5      |
|:-----------------:|:----------------------------------------:|:------------------:|
|       非対応(※CanvasRenderer)       |     CanvasRenderer/CSS3DRenderer <br /> または WebGLRenderer (端末により異なる)   |    WebGLRenderer    |

※遅すぎて実用的ではありません。

大まかに言うと、PCではCanvasRenderer (特別な理由がなければ、そもそもWebGLではなくFlashを使用したほうがよいのですが)、スマートフォンではCSS3DRenderer がフォールバック先として有効、ということになります。
というより、現状ではスマートフォンのブラウザ向けに3Dコンテンツを作成する場合、むしろWebGLRenderer よりも CSS3DRenderer のほうが第一候補のような気がします。

**※2014/12/19 追記**
スマートフォン向けのWebGLにチャレンジしているサイトも既にあるようです。
一流クリエイティブエージェンシーAKQA のWebGLデモサイトです。
http://webgl.souhonzan.org/entry/?v=0090
## サンプル

それでは、CSS3DRenderer ではどんなことができるのか？というところですが、既に色々とサンプルが存在しています。

* [Google Map] (https://www.safaribooksonline.com/library/view/threejs-essentials/9781783980864/ch06s02.html)

* [スマホでも動く物理演算で転がる3Dサイコロを作ったのでその解説](http://css-eblog.com/3d/css3drenderer-dice.html)

* [D3.js との組み合わせ](http://projects.delimited.io/experiments/d3-threejs/)



## まとめ
* WebGLで3Dコンテンツを作成するのは将来必ず可能にはなりましたが、現状のブラウザ対応状況を考えると色々と悩ましいところです。
* CSS3DRenderer は通常のWebGLRenderer とは作り方が異なるが、DOMをそのまま表示できるので、また違った種類の表現が可能です。
* TypeScript のthree.js 型定義ファイルでも、[CSS3DRenderer](https://github.com/borisyankov/DefinitelyTyped/blob/master/threejs/three-css3drenderer.d.ts)は使用できます。