できる！おうちプロジェクションマッピング！

こんにちは、odasatoshiです。
今日はプロジェクションマッピングを使って遊んでみたいと思います。

# プロジェクションマッピングとは？
[プロジェクションマッピング](https://ja.wikipedia.org/wiki/%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%83%9E%E3%83%83%E3%83%94%E3%83%B3%E3%82%B0)は様々なモノに映像を照射する技術です。特にスクリーンのような平面だけではなく建物のような立体、曲面、球体など様々な物体に照射することが多いです。特にその物体の形状を活かした表現をする演出が行われることが多いです。[ディズニーランドでのシンデレラ城](https://www.tokyodisneyresort.jp/tdl/show/detail/946/)の演出などはとても有名なのでご存知のかたも多いかもしれません。

# 事前準備

基本的なプロジェクションマッピングは、とてもシンプルな構造をしています。最低限必要な資材は、
- 照射される対象物
- プロジェクタ
- 制御用のPC

だけです。
今回プロジェクタは[iOCHOW社のIO2](https://www.amazon.co.jp/dp/B074J5VWTL/) というプロジェクターを使いました。いわゆるプロジェクタの明るさとしては200lmですが、暗い部屋の中であれば十分な明るさです。普段は寝室の天井に映画などを映す用途に利用しています。

![Image from Gyazo](https://i.gyazo.com/7be74efcc2fb5d3f8ab42d5dfab84584.png)

制御用のPCは基本的にはなんでも大丈夫です。映像の出力をしなければならないのでHDMI出力が可能なものがよいと思います。今回利用したMacbook Air 11inch(2013)です。ディスプレイポートしかないのでHDMIへの変換ケーブルが必要でした。複雑な演出をリアルタイムに行おうとするとそれなりのCPUやGPUが必要となりますが、ビデオファイルを再生するだけならばそれすら必要ありません。

## ソフトウェアによる制御
プロジェクションマッピングを行うためのソフトウェアはいろいろとありますが、今回使用するのは[MadMapper](https://madmapper.com/)というプロダクトです。2018年12月現在、Version3.6がリリースされています。価格は359ユーロ、日本円で45000円前後でしょうか？趣味で買うにはちょっと高いソフトウェアですが圧倒的に使い方に関する情報量が多いので、まずはデモバージョンで試してみて本格的に遊ぶためには購入してしまうことをお勧めします。

まずは立方体にプロジェクションマッピングすることで、いわゆる通常の映写と何が違うのかを見てみましょう。

## マッピング


分かりやすいように格子を描画してみます。正面からの照射ではないのでいわゆる台形補正が必要な状態になっています。
![格子](https://i.gyazo.com/467daf03385f6db8a45cb5fde1f8459a.png)]

これをソフトウェア的に補正してあたかも立方体に映像が張り付いて見えるように補正します。

![Image from Gyazo](https://i.gyazo.com/d4ffdf06010855d8909d2a24a33bbf97.png)]

少しプロジェクションマッピングっぽくなったでしょうか？ここからさらに演出を加えていきます。

## Materialを作ってみよう
Madmapperは、Materialsという画面エフェクトの素材を使うことで簡単に演出を行うことが可能です。
例えば、標準のMaterialの一つであるCausticsはこういったエフェクトが表示されます。

![Image from Gyazo](https://i.gyazo.com/c472b4d83397315c6720fdac6e771d36.gif)]

折角なのでオリジナルのMaterialを作ってみましょう。どうせならば色々なところで使い回せるMaterialを、ということでプロジェクションマッピングの最初の演出によくある、建物の形を縁取る効果を作ってみたいと思います。

Madmapperの[MadMapper Materials](http://madmapper.com/doc/materials/)は、ISF（[Interactive Shader Format](https://www.interactiveshaderformat.com/)）の仕様に沿った形で実装されており、そこにいくつかのMadmapper独自の入力、パラメータ、標準GLSLライブラリを追加した形で利用可能になっています。

MadMapperでは、
最初にJSONで扱うパラメータを指定し、vec2の値を入力としてvec4の値を返すmaterialColorForPixel関数を実装することで様々なエフェクトを実現します。

まず、真っ黒なエフェクトを作ります。

```
vec4 materialColorForPixel( vec2 texCoord )
{
  vec4 color = vec4(0.0, 0.0, 0.0 ,1.0);
  return color;
}
```

この関数は、texCoord.xとtexCoord.y値が入っているtexCoordが与えられたとき、その点は、何色ですか？
に対する答えを実装する関数です。vec4は、RGBAの順にfloatが入っています。
これはどのようなtexCoordが入力に与えられてもvec4(0.0, 0.0, 0.0, 1.0)を返すため、真っ黒なエフェクトになります。

```
vec4 materialColorForPixel( vec2 texCoord )
{
	vec4 color = vec4(0.0, 0.0, 0.0, 1.0);
	if ((pow((texCoord.x - 0.5), 2) +
		 pow((texCoord.y - 0.5), 2) < 0.1)){
		color = vec4(1.0, 0.0, 0.0, 1.0);
	}
  return color;
}
```

例えば、このようにすると、赤い色の円が表示されます。

![Red Circle](https://i.gyazo.com/b5b3eb36c8a7076b3712b08ccf0df8d3.png)

与えられるパラメータの中でTYPEがtime_baseという値が重要で、この値を使うことで時間によるエフェクト（アニメーション）を実現します。

```
"GENERATORS": [
     {"NAME": "mat_animation_time", "TYPE": "time_base", "PARAMS": {"speed": "mat_speed", "speed_curve":2,"bpm_sync": "mat_bpm_sync", "link_speed_to_global_bpm":true}},
 ]
```

mat_animation_timeをRGBAのGの要素とBの要素に反映してみましょう。

```
vec4 materialColorForPixel( vec2 texCoord )
{
	vec4 color = vec4(0.0, 0.0, 0.0, 1.0);
	if ((pow((texCoord.x - 0.5), 2) +
		 pow((texCoord.y - 0.5), 2) < 0.1)){
		color = vec4(1.0, sin(mat_animation_time), cos(mat_animation_time), 1.0);
	}
  return color;
}
```
この場合、mat_animation_timeが時間を表す値になります。
![red circle](https://i.gyazo.com/74a04c984a46b125fe785da80ea46838.gif)

通常、このような描画（シェーダーと呼ぶことが多いです）は、時間Nの状態を描画するために時間N-1の状態を利用することが出来ません。その代り任意の時間に対して並列演算が可能なためGPUなどで高速に処理することが出来ます。

![縁取りスクリプト](https://i.gyazo.com/50c27a57c5ce96d8ed179eb4b8fe8b6c.gif)

先の太さ、速さ、色をGUIのConfig画面から変えることも出来ます。簡単ですね。

![コンフィグ画面](https://i.gyazo.com/c864ead192e84e7de290d361662e6df3.png)

スクリプトは、[gist](https://gist.github.com/odasatoshi/8fb553dc73af612fceea1ba41eee2b19)
においておきます。

これを先程の立方体に照射してみましょう。

![立方体マッピング](https://i.gyazo.com/490bd93c0fd75e20f6d0068a13fdfda4.gif)]


# おうちでプロジェクションマッピング！

今日はクリスマスです。せっかくなのでクリスマスツリーをにプロジェクションマッピングを施して、いつもとは一味違ったクリスマス気分を味合ってみましょう。


## クリスマスツリーを飾り付ける

![ツリー](https://i.gyazo.com/52cab81b7e7b3e1297c28f4cfae9240d.png)

折角なのでクリスマスツリーっぽいものを買ってきました。いろんなオーナメントが付いています。
どのような演出をするかはセンスの見せ所なのですが、今回はわかりやすくするために、

 1. 上のリボン
 2. 白い珠
 3. 真ん中のプレート

を中心に演出を加えてみることにしましょう。

## Madmapper

実際にプロジェクターを接続し、照射できる範囲を調整したら、上記の部品に合うように、四角や三角、丸のオブジェクトを配置していきます。

大型のもので実施する場合は、プロジェクタの設置予定場所にカメラを設置し、そこから撮影された写真をもとに映像位置を調整しますが、ご自宅で遊ぶ程度の距離では実際に映写しながら調整したほうが早いかと思います。

実際に配置した図はこのようになりました。
![Quad](https://i.gyazo.com/15755326475f88d7b82c4981b66664a6.png)

上の写真と見比べてみるといいかもしれません。

## 音楽をつける

プロジェクションマッピングの特徴の一つに、音と映像が連動して動く、というのがあります。折角なので音楽をつけてみましょう。最近のDTM環境の充実は凄まじく、iPhoneなどに無料でインストールできる
[Garage Band](https://www.apple.com/jp/ios/garageband/)などを利用すると、適当に鼻歌を歌いながらポチポチ押しているだけでそれっぽい音楽を作ることが出来てしまいます。
![Garage band](https://i.gyazo.com/1f1d203a510566f807070a5ba538ff0b.png)

これに背景動画素材を合わせてiMovieなどでベースとなる映像を作ります。
今回は、[After Effects Style](https://ae-style.net/materials/)の素材を利用しました。

# おわりに

こんな感じになりました。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">おうちのツリーを光らせて遊んでた <a href="https://t.co/O0txJuLPI7">pic.twitter.com/O0txJuLPI7</a></p>&mdash; Oda (@oda_satoshi) <a href="https://twitter.com/oda_satoshi/status/1077119315738996736?ref_src=twsrc%5Etfw">2018年12月24日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

それではみなさん、良いお年を！