PTW Tips / Blenderに画像を送る / M・A・T / ポージングツール / WebGLの近未来 / そして年末へ…

この記事は[WebGL Advent Calender 2017](https://qiita.com/advent-calendar/2017/webgl)の11日目の記事です。

こんにちわ。ワロタロです。
今年取り組んだり考えたりしたWebGL関連の色々をまとめました。


# 第一部：取り組んだこと

## ゲーム用プログラム集 PTW Tips

去年の冬頃から、自分がゲームを作った時に使ったコードの総まとめをするPTW Tipsというリポジトリを作っています。ずいぶん時間がかかりましたがほぼ完成し、Git Hubで公開しています。言語はTypeScriptです。

[PTW Tips](https://github.com/warotarock/ptw_tips) 

![Image1.jpg](https://qiita-image-store.s3.amazonaws.com/0/59191/bf029de8-340b-44c7-a7b0-974a041828bb.jpeg)

### 内容

内容はゲームでの使用を前提(ここが重要)としたサンプルプログラムと解説を集めたものです。あくまでTips集という体裁で、多少の３ＤＣＧのプログラミングの経験がある人向けです。

次の四つの段階に分類してまとめました。

1. 基盤技術　…描画関連
2. 補助技術　…ＧＣ対策のメモリ管理など
3. 汎用サブシステム　…ゲームパッド入力、音声再生など
4. ゲーム用サブシステム　…リソース管理、タスク管理など

量は少ないですが、ひと通りのものは揃っているので簡単なゲームなら作ることができると思います。ただ自分としてはこれで本当にゲームを作ってほしいというより、サンプルプログラムとして公開することで誰かの何かの役に立てばいいなと思っています。

それと自分の自己紹介のかわりに人に見せたりしたいと思います。むしろ一番役に立つのはその形だったりして。

## MAT(Multi Angle Texture) - そんなものは無いけど

長くなってしまったので[別の記事](https://qiita.com/warotarock/items/37c158c4cadee57e0a33)にしました。大雑把にいうとプリレンダ画像を必要な角度のぶんだけ用意しておくというおそらく古くからある手法です。

![Rimg1367s.jpg](https://qiita-image-store.s3.amazonaws.com/0/59191/bfc4cb3f-ae38-aac2-ee00-baf0224175ea.jpeg)

![Image7.png](https://qiita-image-store.s3.amazonaws.com/0/59191/006c85ca-9314-8cbf-5b5b-eaa09626ba4f.png)

![test14.gif](https://qiita-image-store.s3.amazonaws.com/0/59191/a61ba7cd-e134-b8a9-6484-bf5ea3f0919e.gif)

[ライブデモ１](https://warotarokz.sakura.ne.jp/main/demos/webglac2017/mat/001/)
[ライブデモ２](https://warotarokz.sakura.ne.jp/main/demos/webglac2017/mat/002/)

すね毛じゃないよ。

## GLSLマテリアルの簡易な実現 - Blenderに画像を送るやつ

### GLSLをマテリアルとして活用したい

GLSL SandboxやShaderToyなどGLSL共有サイトで素晴らしい作品が公開されているので、これを見るだけでなく素材として使うことができないかと以前から考えていました。個人的にはBlenderでマテリアルとして使うことができたら嬉しいのですが、Blenderのレンダリングの仕組みの中にうまく組み込む方法を思いつきませんでした。新しいレンダリングエンジンを作るのは実装が大変ですし、既存のレンダリングエンジンの恩恵を受けられなくなってしまいます。

簡易な方法として一つ思いついたものが、Blender上の画像にWebGLで描いた画像データを送り込むという方法です。これなら既存のレンダリングエンジンで簡単に利用することができます。

### WebSocketで画像データを送る

ブラウザからBlenderにデータを送る手段は、Pythonのサンプルがそれしか見つからなかったのでWebSocketにしました。WebSocketは双方向通信をブラウザでできるようにする技術で、サーバとクライアントの間でテキストデータやバイナリデータを送信することができます。WebSocketなら一般のウェブサイトからBlenderにデータを送ることもできるので、将来のことを考えると良さげな感じがします。

ということで作ってみました。WebGLの画像を送ることまではできなかったのですが、画像を送ることはできました。

![Image41.jpg](https://qiita-image-store.s3.amazonaws.com/0/59191/3105cad2-93bf-a9a4-a3c9-381ae4775ac0.jpeg)

作ったのはBlenderのアドオンのPython（サーバ）と、ブラウザ側のHTMLとJavaScript（クライアント）です。作るにあたっては次のサイトが参考になりました。そのサイトでは画像データというよりオブジェクトなどのデータを主にやり取りしていましたが、WebSocketは画像データを送ることも可能です。

参考にしたサイト：[KoltesDigital / websocket-server-for-blender](https://github.com/KoltesDigital/websocket-server-for-blender) 


### 今後の発展

~~まずGLSLから画像を取れるようにすることですね。なんかうまく取れなくて、まだ原因を調べてすらいないのです。すみません。~~

それと、今回は画像の送信だけが可能なBlenderアドオンでしたが、Blenderでなくとよいですし、もっと色々なデータが通信できれば用途が広がります。例えば Google Polyのようなサイトからボタン一発でモデルデータをDCCツールに取り込むことができたら、なかなか楽しいのではないでしょうか。そうなるとWebGLは３Ｄモデルのプレビュー表示としての役割が広がっていくかもしれませんね。

~~中途半端で申し訳ないのですが、ソースコードは以下になります。いずれGitHub等できちんとしたものを公開したいと思います。~~
2017/12/17： GLSLで描画した結果をBlenderに送る事ができるようになりましたので、ファイルを更新しました。今後の更新の予定もないためGitHubでの公開はしないことにしました。

[クライアント](https://warotarokz.sakura.ne.jp/main/demos/webglac2017/blender_recieve_image/client/)
[サーバアドオン(zipファイル)](https://warotarokz.sakura.ne.jp/main/demos/webglac2017/blender_recieve_image/image_recieve_from_browser.zip)

## 簡易ポージングツールの試作

### 「某絵を描くスタジオの３Ｄ機能が使いづらくてカッとなって作った。」

ふと思い立って前から考えていた３Ｄデッサン人形の操作方法の実験をしてみました。もともと２Ｄの線画専門のドローツールを趣味で作っていたのですが、アドベントカレンダーのネタを探している時に思いついたので先にやってみることにしました。 

![Image32.jpg](https://qiita-image-store.s3.amazonaws.com/0/59191/f1818569-cdfe-8c3e-1214-60ce920ab349.jpeg)

操作はまず頭の位置に円を描くところから始まり、右側のパネルで入力対象を切り替えながらだんだんと身体の末端に向かって入力していく感じです。頭以外の全て部分は画面に表示される半透明の球の表面をクリックすることで入力します。 手動による切り替えで奥側も入力することができます 。

![Image14.jpg](https://qiita-image-store.s3.amazonaws.com/0/59191/c4462c2c-d512-3f6c-c1a0-e8fdb25c51a9.jpeg)

![Image16.jpg](https://qiita-image-store.s3.amazonaws.com/0/59191/8e67d236-941a-2ca8-9775-ed8d5f6000a5.jpeg)

![Image18.jpg](https://qiita-image-store.s3.amazonaws.com/0/59191/386936cd-f82b-62bc-bffc-d6d4f738ac79.jpeg)


### どうしてこうなった

絵を描くとき、ラフのさらに前の段階で、まず人間の配置を棒人間で描いてみたりするのはよくあると思うのですが、棒人間を描いたらそれがそのまま３Ｄになったらいいなといつも思っていました。それでWebGLアドベントカレンダーの機会に作ってみることにしました。とはいえ２Ｄの棒人間を３Ｄにするには様々な問題があります。

一つの大きな問題は、すでに描かれている絵、つまり画像データから棒人間を検出するプログラムを作るのは難しいということです。少なくとも私には難しい。そこで、すでに描かれている絵ではなく、「まず頭の丸を描く」「次に首の線を描く」というふうに段階を区切って描いていくのであれば可能であろうと考えました。

それともう一つ問題は、二次元で描いた腕や脚の線をどうやって三次元に変換するかということです。これはそれほど難しい問題ではなく、腕や脚などの本来の長さが分かっていれば、カメラから見た長さと角度から三次元的な位置が推定ができます。ただ手前に向かっているか奥に向かっているかはどうしてもわからないので、手動で入力ことにしました。ロール回転は何かの基準を設けて自動で決まるようにし、後から手動で入力することもできることにしました。

### 棒人間は必要なかった

実際に作ってみると、実際には棒人間を描く必要がないことがわかりました。 手先とか足先の座標だけわかればいいので、線の末端の点だけが必要だったのです。それでも途中までは「いや俺は棒人間を描くんだ」 と言ってかたくなに線を描画していたのですが最終的には「かえってわかりづらいかな」となり、棒人間はいなくなりました。

![Image34.jpg](https://qiita-image-store.s3.amazonaws.com/0/59191/c842eefc-6eb0-451d-7740-b7535269d224.jpeg)


### 深度を描くシェーダで入力座標をとる

必要なのは座標だけであるため、マウスでクリックした位置とその奥行きが分かればカメラの逆行列を使って3次元位置を計算できます。今回は奥行きの情報を取得するために深度バッファを使うことにしました。

![Image33.jpg](https://qiita-image-store.s3.amazonaws.com/0/59191/94124aed-eb6d-858f-005e-e78b6a796bb8.jpeg) 

少しつまずいたのは、深度値を ピクセルに保存するときにアルファ値に1.0以外を保存すると同じピクセルに描画があったときに深度値が壊れてしまうということ。これはWebGLでblendFuncやblendFuncSeparateでアルファブレンドされるようになっていたからで、深度値の描画前に単にソース側の色が書き込まれるように設定する必要があります。

### 球型マニピュレータだけでも結構入力できる

個人的にちょっと革新的だったのが、 球型マニピュレータです。例えば手先を入力する時には、肘の位置を中心として肘から手先までの長さを半径とする球型のモデルを深度バッファに描画します。 この球はどこをクリックしても手先ちょうどの位置を指定することができるので、わりあい直感的です。球を奥方向に-1倍したモデルを深度バッファに描画すれば奥方向の位置も指定できます。 今回は平行投影でやっているのですが、たぶんパースがかかってもできると思います。 

### とりあえず満足した

まだまだ改善の余地はあると思います。体のパーツが足りませんし、頭の回転は自由度が足りないと思います。すでに入力済みのパーツを後から修正しても他のパーツが自動的に修正されたりもしません。でも余計な自動修正がない方が扱いやすかったりするかもしれません。 その辺りは今後の課題として、今回は思ったよりも簡単にポーズが入力でき満足したので一区切りとしました。 今後は本来の目的に戻ってドローツールとしての機能を追加していこうかなと思います。 いつ完成するのか全くわかりませんけれども。

[ライブデモ](https://warotarokz.sakura.ne.jp/main/demos/webglac2017/posingtool/)

# 第二部：考えたこと

## Android Instant Appsが登場→WebGLの需要が微減？

今年5月、GoogleがAndroid Instant Appsを一般の開発者が使用できる形で公開しました。Instant Appsはネイティブアプリをインストールすることなく実行できる仕組みです。ユーザはブラウザのＵＲＬをクリックするだけでネイティブアプリを利用できるようです（試してないです）。

ということは当然、OpenGL ESで描画を行うアプリも実行できるはずです。ということは、画面構成によってはWebGLを使わなくとも３Ｄを使ったサイトが構築できるのと同じではないでしょうか。

WebGL界隈への影響でいうと、ゲームエンジンからのWebGL出力の需要は微弱に減ると思います。まだAndroidだけなので影響は微弱でしょう。ただ、将来的にiOSでもInstant Appsのよう仕組みが導入されたら結構影響があるかもしれません。

## WebGLを活用したリアルタイムに作業を共有できるＤＣＣツール時代到来の予感というか妄想

### リミックスを推し進める業界の傾向

今年10月、GoogleがPolyを公開しました。無償の3Dモデルがわんさか手に入るサイトです。これでAR、VRのコンテンツ作りが捗るとどこかで聞きました。また今年は、Windows 10 Creators Updateがリリースされました。このアップデートには「ペイント３Ｄ」や「View 3D」、「Remix 3D」など一般のユーザ向けのＡＲ、ＶＲ、３Ｄコンテンツ関連のツールが含まれています。なんとなく、Gooleもマイクロソフトも専門家ではない一般ユーザがコンテンツを作るように何かを推し進めているように感じがします。GoogleもマイクロソフトもRemixという言葉を使っているのも印象的です。

![Image38.jpg](https://qiita-image-store.s3.amazonaws.com/0/59191/26a88540-5fc8-9df8-33f1-88bc0e46b870.jpeg)


### リアルタイム共同編集が増えている

少し話が飛びますが、去年から今年にかけ、Google Document で複数人で同時に文書を書く機会が何度かありました。自分が文章を書いている間にも誰かが別の所を編集していて、編集がリアルタイムに反映され、いつの間にか文書全体が出来上がっていくのが不思議な感覚でした。文書上で会話になることすらあり、ある種のチャットのようでもあります。

前に創作関連の知人が「複数人で同時に一つの空間で３Ｄのコンテンツを作る作業ができるツールが欲しい」というようなことを言っていたのを思いだし、こういう感じなのかなと思いました。複数人でわいわいものづくりをするのは楽しいですし、そういった作り方はすごいエネルギーを生み出しますよね。

ちなみにマイクロソフトのOffice Onlineも複数人で同時に文書を編集できるようですし、最近ではAtomエディタでもVisual Studioでも複数人による編集ができるようになっているらしいです。

### 求められるＤＣＣツール

ここまでのことを考えると、登場が予測されるのは

**「複数人で同時に一つの空間で３Ｄコンテンツを作る作業ができて、なおかつ誰でも簡単に操作できるインターフェイスを備えたＤＣＣツール」**

ということになるのではないでしょうか！？最近は特定の分野（ＲＰＧとか）に機能を絞り込んだ軽量なゲームエンジンも登場してライトなユーザー向けにシェアを広げているようですし、さらにユーザ層を広げるために誰でも操作できるインターフェースが進歩してＶＲなども活用されるかもしれません。

なので近い将来、一般家庭でも次のようなデジタルクリエイティブな光景が見られるかもしれません。

![tree_kazaritsuke_family2.jpg](https://qiita-image-store.s3.amazonaws.com/0/59191/c2e2175a-6be7-5351-1e64-d5065a610d01.jpeg)

なにこれ寂しい。

で、それがWebGLとどう関係するかなのですが、ライトなユーザー向けのＤＣＣツールはブラウザアプリとして提供されると導入しやすくて良いのではないかと思います。Google Docmentと同じ形ですね。とすると、描画はWebGLということになります。

近い将来、WebGLは今よりもっとクリエイティブな目的で使われるようになっていくような気がします。Google Polyのような素材サイトは今よりもっと増えて、クラウドストレージに直接ファイルを保存できるようになると思います。素材サイトはアセットをWebGLでプレビュー表示して、WebGLの技術者はオンラインのＤＣＣツール用のアセットを作る技術者として重宝されるかもしれません。

…本当に？…自信はありません(笑)

---

長々とお付き合いいただきありがとうございました。以上になります。
来年はどんな一年になるのでしょうか。何作ろうかなぁ。

WebGLと皆様のさらなる発展を祈りつつ、
少し早いですが皆様よいお年を。