ほぼ実録 three.js 案件とピュア WebGL 案件 2019 年版

## introduction

みなさまこんばんは。
doxas と申します。

こちらは [Three\.js Advent Calendar 2019 \- Qiita](https://qiita.com/advent-calendar/2019/threejs) の 12 日目の記事です。

令和元年の年の瀬、いかがお過ごしでしょうか。
私はと言いますと、なかなかに余裕の無い毎日を送っておりまして今年はアドベントカレンダーも書く余裕が無いなと思っていたのですが、technohippy さんが毎日のようにアドベントカレンダーへの投稿を呼びかけているのを見るにつけ、これはせめて少しでもお手伝いしなければと思い立ち筆を執った次第です。（イベントの主催とかもそうですが、こういうの呼びかける側というのはそこそこに精神的疲弊があったりしますよね……）

technohippy こと、あんどうやすしさんはオライリーの「初めての Three.js」の訳者さんなのはみなさんご存知かと思いますが、私もこれで three.js 勉強しました。なので私にとってはいわば先生のような存在ですね……

いつもありがとうございます！

## agenda

以下、すべて doxas 氏の「個人的な意見・経験」としてお送りします。

* three.js とピュア WebGL
* 2019 年の three.js 案件でのコミット数や実作業時間
* 2019 年の WebGL 案件でのコミット数や実作業時間

## three.js and pure WebGL

three.js と WebGL の違いについては、こちらの記事を読んでらっしゃるみなさんには説明不要だと思いますのでここでは割愛します。簡潔に言うなら、WebGL を（圧倒的に）扱いやすくしてくれる（とても偉大な）ライブラリが three.js ということになるのかなと思います。

[three\.js – JavaScript 3D library](https://threejs.org/)

私自身は、ピュアな WebGL から入ってしまったという不幸な生い立ちがありまして three.js を使うときは時にドキュメントを見ながら、あるいはソースコードを見ながらという感じで調べながら実装していきます。まあでもこれは、別に three.js に限ったことではなくてどんな開発でもそうですよね。

最近では、案件がそもそも three.js で動き始めていて途中からアサインされるとか、納品後に私がいなくてもメンテナンスができるようにとあえて three.js を採用したりとか、そういうことも増えてきまして、少しずつですが私自身も three.js を使えるようになってきたような気がします。ここ数年は自身が主催する WebGL スクールでも three.js を取り入れるようにしていますし、教える側が全然知らんというのはいかんじゃろ～ と思って機会を見つけては触ってみるようにしています。

three.js が優れたライブラリであることは、ちょっと使ってみるとすぐにわかるのですが……

もともとのピュアな WebGL の ~~地獄さ~~ 素敵さ加減を知ってから three.js に触れてみると、よりそのありがたみがわかるのではないでしょうか。

私の体感的には、ピュアな WebGL の実装における難易度や手間の具合を 100 とするなら、three.js を使うことによってこれを 10 くらいにまで軽減できるような気がします。ですからライトな感じで WebGL を使ってみたいなら、圧倒的に three.js がおすすめです。私の場合はピュアな WebGL で実装する方法だったらすぐに思い浮かぶのですが、それを three.js 的にはどういうふうに書けばいいのかわからないので、いつも調べてばかりです……

ほんとうにつらい……

## 2019 年の three.js 案件

突然ですが、GitHub のアカウントのトップページで草原をクリックしてやると、その日に何をコミットしたかとか、その履歴をざっくりと見ることができますよね。

![コメント 2019-12-11 214018.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39638/619bc68d-6bcd-5bdc-c9b5-03ad0c175390.png)

ここからは、2019 年の最初のほうから doxas 氏がどういうコミット履歴を残してきたのかを、この草原の草たちをぽちぽちしながら見ていきたいと思います。

なお、コミット数を併記していますが、コミットの数は多ければ良いとか少なければいいとか、そういうものではないと思いますので、あくまでも参考程度に見てください。私はあんまり人と比較したことがないのでわからないですが……たとえばコメント直すならコメント直すだけのコミットを打ち、コードの変更とは別々のコミットになるようにする、みたいな感じの粒度というかポリシーでコミットするようにしています。

### アパレル系のカスタマイザ three.js 実装

| 内容 |  |
|---|---|
| 総コミット数 | 約 230  |
| 主に実装していた期間 | 約 3 ヶ月  |

ちょうど 2019 年の最初の頃は、アパレル系の WebGL のカスタマイザを実装していたようです。

ユーザーが選択した生地や形状を WebGL でリアルタイムにプレビューすることで、より直感的に商品イメージを訴求できるというものですね。オンラインで購入が可能な他、実際の店舗側でも営業さんたちがタブレット片手に売り込みができるアプリケーションとして稼働しなくてはならない、という機能要件でした。まさに、WebGL ならではのマルチプラットフォームな実装という感じです。

こちらの案件では、とにかく扱う生地などの素材の量が半端ではないというのがひとつのポイントでした。生地の種類がまず尋常じゃない量があることに加え、袖や襟などの形状の違い、ボタンの有無から仕立ての違いまで、冗談ではなく星の数ほどのバリエーションがあって、それの取り回しが大変でした（遠い目）

three.js には glTF のローダーですとか `MeshStandardMaterial` ですとか、質感重視（より現実に近い本物感のある質感）の案件にはピッタリの機能が最初から備わっておりますので、それらを活用させていただいた次第です。本当に three.js はすごいですなあ……

![コメント 2019-12-11 214235.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39638/0b3f7a55-4b6a-d25c-6eeb-32a9d93751fa.png)
[MeshStandardMaterial – three\.js docs](https://threejs.org/docs/#api/en/materials/MeshStandardMaterial)

ユーザーが選択した途中経過の状態の、一時保存の機能なども実装する必要があったのですが、そのときの選択状態をもとにした外見についてもスクリーンショットで保存する必要があり、これは Canvas2D を経由して data URL に変換して保存したりとかしたような気がします。こういうときに必要となる設定とかも、ピュア WebGL の実装だったらすぐにわかるんですけど、three.js の場合は初期化のときに何を指定すればいいんじゃろうか？ みたいなのを調べないといけなかったような記憶があります。

three.js の場合は、こういったちょっと特殊な対応が必要なケースであっても、それらの機能が three.js 独自のメソッドやプロパティに置き換わってることが多いとは言え「その手段自体がそもそも提供されていない」ということはほぼ無いので、そのあたりのカバー範囲の広さもすごいなあと思います。

### コーポレートサイトの three.js 実装

| 内容 |  |
|---|---|
| 総コミット数 | 約 20  |
| 主に実装していた期間 | 約 2 日 |

こちらは、とある企業のコーポレートサイトの、背景部分に WebGL の実装が置いてある的なよくあるやつです。

上記の実装期間を見てもらえばわかると思いますが、すごく簡単な内容のものでした。

というかぶっちゃけると、これは既に three.js で動いている途中まで作られた実装がある状態で、どうしても元請けさんたちのほうで技術的に解決が難しい部分があるということで、突発的に降って湧いたものでした。

頂点シェーダでページ遷移に合わせてパーティクルが形成するシルエットを変更するというものだったような……気がする……

three.js には独自のシェーダを盛り込む方法もきちんと用意されていますし、頂点シェーダやフラグメントシェーダをバリバリに使った実装を作るのも、それほど難しくはありません。そういったところも、玄人でも使いやすいようにいろいろ考えて作ってあって、本当に three.js はすごい……

### キャラクター系の 3D モデルビューア three.js 実装

| 内容 |  |
|---|---|
| 総コミット数 | 約 70  |
| 主に実装していた期間 | 約 1 ヶ月 |

キャラクターと言うといろいろなものが当てはまってしまうのですが、こちらの案件では人型の 3D モデルを、アニメーション付きでウェブサイトに載せたい、さらに衣装を着せ替えたりしたいということで、実装がスタートしました。

three.js には、先述の通り glTF のローダーがあるので、そのリソースを用意することができる別働隊がいる場合は非常に話が早くて、あらかじめキレイに作り込まれたキャラクターの 3D モデルを、これまたあらかじめキレイに作り込まれたモーションで動かすということが比較的簡単にできます。

こういうときに問題になるのが、どうやって 3D モデリングツールと three.js を連携させるかというところだったりするのですが、残念ながら（？）今回のケースでは比較的あっさりと実装できてしまった感じでした。

先方から送られてくる glTF には、特に何も指定してなかったのですが Draco 圧縮が掛かっててマジかよってなったのですが、three.js の `glTFLoader` なら一撃でした。本当に three.js は神様ですね……

[GLTFLoader – three\.js docs](https://threejs.org/docs/#examples/en/loaders/GLTFLoader)

### 医療系 three.js 実装

| 内容 |  |
|---|---|
| 総コミット数 | 現時点で約 300  |
| 主に実装していた期間 | 約 2 ヶ月 |

こちらは現在も進行中の案件で、医療系の、ブラウザ上で動作するウェブアプリケーションです。

お医者さんとか、その助手さんとか、医療関係者の方々が利用されるツールですね。現在も開発が続いてますが約２ヶ月（たぶん実働は２０人日くらいかな？）でコミット数 300 超えしてるとか頭おかしいなと自分で書いていて思いました。（コミットの数が多い・少ないは実装力とは無関係だと思ってますがそれにしても多すぎる気がした）

実装自体は three.js をベースにしているのですが、主にユーザーからの入力を受け付けるインターフェースとして Control 周りとかは独自に実装している部分もあります。

マウス操作がアプリケーションに対してどのように作用するかという 3D アプリケーション特有のインターフェースの実装は、だいぶ難易度が高い世界の話なんじゃないかなあとふんわり思ってますが、こういうのって実際にやったことがないとなかなか身につかないスキルだと思うので、ぜひみなさん一度自分でカメラを操作するコントローラーみたいなの実装してみるといいと思います。私の憧れの 3D 系のエンジニアさんが、sketchfab のビューアのカメラがすごいと言ってて、よくよく観察してみたら本当にすごいので、そういうパンチの利いた実装にチャレンジしてみたいという方は参考にしてみるといいかもしれません。

`OrbitControls` で事足りないことなんてあるの！？ と思うひとももしかしたらいるかもしれないですが、特殊な用途の 3D アプリケーションの場合は、こういうのはよくある話なんじゃないかなあという気もします。基本的に、だいたい自作するしかなくなりますよね……（わかるひとにはわかるとおもう）

three.js の場合、行列やベクトルはもちろん、クォータニオンとかもかなり便利に使えるように実装があらかじめ用意されていますので、スクラッチで数学周りの実装を書くことに比べたらだいぶラクに作れると思います。

いや～ 本当に three.js ってすごいです。

## 2019 年のピュア WebGL 案件

さて、ここまでは three.js を利用した案件を振り返ってきましたが、私の場合はむしろピュアな WebGL の実装のほうが手に馴染んでいます。

もし選択の余地があるなら、よほどのことがない限りはピュア WebGL で実装していきますので、ここからはそれらの案件についても見てみましょう。

### コーポレートサイトの WebGL 案件

| 内容 |  |
|---|---|
| 総コミット数 | 約 120 |
| 主に実装していた期間 | 約 1.5 ヶ月 |

こちらの案件では、背景にキレイな WebGL シェーダ芸がふよふよしていて、スクロールしたらシェーダ芸がそれにインタラクティブに反応してドバーっとなるような感じのものです。

もう少し真面目に書くと、ペライチの Canvas が CSS で言うと `position: fixed` 的な感じで背景に固定されている状態で、そこにフラグメントシェーダだけで風景をレンダリングします。いわゆるレイマーチングに近いものですね。

ただ、この案件の妙なところは、そのレイマーチングのシェーダ芸によるシーンの中になにくわぬ顔で頂点によって描画されているジオメトリが合成されていて、流れ星みたいに画面を横切るところだけが別途ジオメトリによって表現されている、みたいなところです。

なんでそんな実装にしたんだか……ちょっと記憶がもはや曖昧なのですが、たぶん後半のほうでクライアント（の上層部）から「ここに流れ星的ななにかを流してはどうでしょうか？」と言われたのだと思います。レイマーチング的な感じの実装だと、もちろんいろいろなケースがあるので一概には言えないですが、それフラグメントシェーダでやっちまったら負荷がやばくない？ みたいな状況は結構あると思うので、別のパスの頂点シェーダでジオメトリを普通に描画してやったほうが、マルチパスだとしてもまだマシみたいなことはあるのかなあという気がします。


### 建築系のフレームワーク実装を含む WebGL 案件

| 内容 |  |
|---|---|
| 総コミット数 | 約 200 |
| 主に実装していた期間 | 約 2 ヶ月 |

こちらの案件では、ピュア WebGL のフレームワークの実装から携わっていて、それは過去（去年くらいだったかな……）に既にある程度の実装ができていたのですが……

再度、そのフレームワークを使って社内用のビューアツールの実装（の基礎部分）を作って欲しいということで、対応しました。

話を聞いたところ、ブラウザでかる～く動作するというよりは、結構ガッツリ目の「ウェブアプリ」という感じではあったので、いわゆる React や Vue といったモダンなフレームワークを使うことも一応提案したのですが、もともとこちらのクライアントでは JavaScript に長けている実装者が少ないということもあって、できればネイティブな JavaScript だけで実装できているほうがよいということでしたので、WebGL の実装を含むフレームワーク＋フロントの実装そのものをまるっと私の方で実装するという運びになりました。

クライアントがもともと持っているサーバ実装があって、そこからバイナリがズドーンと送られてくるので、そいつをギュイーンするみたいな……なんかそんな感じです（察してください）

ポイントだったのは、WebWorker の別スレッドがこの巨大なバイナリをさばく役割として裏側にいるようにして、フロントの部分は極力軽快に動くように作る、みたいなところだったと思います。API の設計のところとかもガッツリひとりで全部ゼロからやるっていうのは、まああれですね（察してください）


### コーポレートサイトの WebGL 案件

| 内容 |  |
|---|---|
| 総コミット数 | 約 170 |
| 主に実装していた期間 | 約 1 ヶ月 |

こちらは、私の場合は特にそうなのですが、珍しく作ったものを作ったと公言できる稀有な案件でした。

実装に関することは、過去に WebGL 総本山という怪しげなサイトで紹介してくれてましたので、そちらを参照してください。

![1505_001.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39638/6c505f99-95d8-5607-f3e6-29554e96ce30.jpeg)
参考： [地球規模での環境課題の解決「バイオエコノミー」を目指すオリシロジェノミクス株式会社のウェブサイト \- WebGL 総本山](https://webgl.souhonzan.org/entry/?v=1505)

この案件は[株式会社スタジオ ディテイルズ](https://www.details.co.jp/)のみなさんとご一緒させていただいたものなんですが、あの組織のひとたちは全員のレベルがクッソ高い感じで WebGL おじさんとしても界王拳を使わないとマズイ！ という感じでした（実際は単に納期が短かっただけなんですが、ディテイルズの人たちがみんなやばいというのは本当です）

デザイナーさんからご提示いただいたモックというか叩き台のデザインを見た時に、これは短納期ということもあるし three.js 使ってたらたぶん間に合わないなと思ったので、ピュア WebGL で実装しました。SVG を解析して頂点データにコンバートしたりとか、そういうのはまあ three.js 使ってもたいして手間は変わらないとは思うのですけれども、いちいち調べてたら埒が明かんということで、全部自分で作りました。

本当に不器用なのは損ですね……

### 建築系 WebGL 案件

| 内容 |  |
|---|---|
| 総コミット数 | 約 1,000 |
| 主に実装していた期間 | 約 5 ヶ月 |

さて、なんかコミット数がそろそろバグってきたかな？

残念ながらバグってはいません。自分でも驚きましたが数えてみたらそれくらい行ってました……

こちらの案件は、実はまだローンチされていないのであまり詳しくは書けませんなのですが、ピュア WebGL を利用してかなりガッツリ目に作られているお目々飛び出しちゃうよね～　案件です。

この案件の大変なところはまあいろいろあるのですが、glTF のパーサーをゼロから実装することになったのはなかなか楽しい思い出です（遠い目）

もともと、glTF が 1.0 しか存在しないころに軽くパーサーを書いた経験があったので、なんとかなりました。

glTF は、バイナリ版と JSON が別途用意されている版と複数のファイルフォーマットが仕様上存在するのですが…… glTF のバイナリ版のほうは、その中身を開けたら JSON がぴょーんって出てくるんですよね…… これ知識としては知っててあらかじめわかっててもなんか面白いなあと思っちゃいますよね（共感できるひとはいるのかしら問題）

また本案件では、とある特殊な事情により「フレームバッファを封印して画作りせざるを得ない」という激アツな条件の元、様々な工夫を凝らしてシーンを最大限かっこよく見せるということで、いろいろ手を尽くしていくうちにコミット数がバグったのだと思われます。

なぜ最初から three.js で作らなかったのですかという問いはご法度です。

WebGL おじさんはピュア WebGL で作ったほうが早いからです。


### コーポレートサイト WebGL 案件

| 内容 |  |
|---|---|
| 総コミット数 | 約 400 |
| 主に実装していた期間 | 約 2 ヶ月 |

こちらのコーポレートサイト案件では、WebGL はイントロ部分にしか出てこないのですが、結局いろいろあってその他のフロントの実装全部を作り込むことになったというものでした。

記憶している大変さに比べてコミット数がやけに多く感じるのですが、たぶんフロント周りの普通の HTML とか CSS とかの実装分も入ってるからなんだろうと思います。

私の場合、基本的に WebGL 案件しか受託しないという感じなので、フロントの全体を自分でまるっと作るというのは稀です。できなくは無い……できなくは無いのですが……好きではないです……

WebGL おじさんには HTML や CSS は極力与えないほうがいいと思います……


## 余談

さて、ざっくりと 2019 年の案件を振り返ってみましたが、これやってみると結構「そういやこれやってたなあ」みたいな感慨があって面白いですね。

ここで掲載していない案件なども一部ありますのであしからず……

クライアントに絶対に迷惑が掛からない程度に抽象化したつもりですが、オイちょっと待て的な部分がありましたら、お手数ですが教えていただけますと嬉しいです。

また、総本山を毎日更新する作業や wgld とか glslfan をメンテナンスする工数や WebGL スクールと GLSL スクールのスライド・サンプル作成の時間や webgl_editron のバージョンアップや書籍の執筆作業や法人の経理・事務・届け出や家族サービス一切合切は上記には含まれておりませんが私はなんとか生きています。

## 最後に

three.js は本当に素晴らしいライブラリで、このライブラリがもしこの世に存在しなかったら WebGL がこれほど認知されることは無かったと断言できます。

またウェブの開発というのはその性質上、軽快かつ迅速にプロトタイプやプロダクトを仕上げていく必要があり、そういう意味でも three.js や Pixi.js などをベースに手軽に WebGL を使っていくというのはウェブの開発においては正しい形だと思います。

一方で、私の今年の実装してきたものたちをよくよく見てみるとなんとなくお察しいただけるかもしれませんが、ピュアな WebGL を使えて CG や 3D 数学にも造形の深い開発者は、まったく違ったフィールドでも活躍することができます。というか、そういうのができるひとが本当に少ないので、正直なところ人手は不足していますし意外に思われるかもしれませんが仕事は結構いっぱいありますね……　ただ、そういう性格の案件の場合、OrbitControls 相当のカメラ周りの実装とかは普通に難なく自作できるくらいのスキルは欲しいところですし、そうなってくるとフロントエンドの界隈にそれを求めていくのはまあ厳しいよなあとは思います。

昨今のそういったウェブと WebGL の関係性を観察していると、来年の WebGL スクールはさらに three.js 寄りにして、より手軽に、簡単に 3D 開発やシェーダを使った開発ができるというところを重視しないといけないのかなあと思ったりもします。ピュアな WebGL をコツコツ勉強することは「間違いなくその人の技術的な資産」になるのですが、かといってそれは向き不向きもありますし、なによりいわゆる普通のウェブの制作ではそこまで深い知識が必要になることはそれほど多くないというのが現実だと思います。

最近は、より「開発者それぞれのスキルに応じた案件の最適化」みたいなことが起こってるように感じています。

three.js を使うことは手抜きではないですし、ピュアな WebGL を扱えないことが恥でもないと思います。これは本当に強調しておきたい。ピュアな WebGL が使えるからすごいということではなくて、自分の実現したいことや学びたいことに合わせて、適切に選択を行えば良いというそれだけのことだと思います。

ぜひみなさんそれぞれの、ちょうどいい WebGL との接し方というか距離感を、探してみてもらえたらと思います。

なんだかんだでめちゃくちゃ長くなってしまった……丁寧に最後まで読んでくださった方、もしいらっしゃいましたら恐縮です。

いつもありがとうございます。