原一浩

Reactといえばコンポーネント!React VRの3Dプリミティブコンポーネントを探る、触る

連載: React VR (3)

今回のサンプルの完成版。ライティングとかもやるぞ

前回、React VRでパノラマ写真を見るというコンテンツを作成しました。
サンプルを試していただいた方は「なんか結構できたじゃん感」を満喫できたと思います。それもそのはず、360度写真のみのコンテンツは、天球にパノラマ画像を貼り付けた時点で、目的の99%を達成できたといえるからです。ほとんど完成といっていい状態でしょう。

しかし、他のVRコンテンツを触ったことがある人間なら、少しもの足りなさを感じることと思います。一つはインタラクティブ性のなさ、そしてもう一つはモノの存在感のなさです。

インタラクティブ性のなさは、イベント駆動型のVRコンテンツの作成というハードルが待っていますが、今回はそれはさておき、モノの存在感について書いていきます。

パノラマ画像だけで構成された世界は、「一見、目の前で展開されている感じなのに、触ることができないほど遠くに広がる世界」と言えます。目の前の芝生に近付いて触ることはできませんし、奥の人に近付くこともできません。

仮に頑張って、インタラクティブ性を高めて奥に進めるように作ったとしても、そこにあるのは拡大されて画素が粗くなった人のようなナニカでしかありません。

VRのモノとしての存在を確固たるものにするために大事なことは、VR空間に実際にモノを置いてみるということになります。

ということで、今回はReact VRに用意されているコンポーネントのうち、モノとして置けるコンポーネント、3Dプリミティブについて扱っていきます。

いろいろなタイプのReact VR Components

公式ドキュメントにあるReact VR Componentsの目次は下記のような構成になっています。

  • AmbientLight
  • Box
  • LiveEnvCamera
  • Cylinder
  • CylindricalPanel
  • DirectionalLight
  • Model
  • Pano
  • Plane
  • PointLight
  • Scene
  • Sound
  • Sphere
  • SpotLight
  • Video
  • VideoControl
  • VideoPano
  • VrButton

いろいろありますね。「あれ?、これだけしかないの?」という見方もあるかもしれません。主要なものを役割ごとにカテゴライズしてみましたので順に見ていきましょう。各種コンポーネントの実装コードに興味がある方は、GitHubのReact VRリポジトリのViews以下を見てみるとよいでしょう。

空間を作るタイプのコンポーネント

まず、チェックしておきたいのは空間を作るタイプのコンポーネントです。

  • VideoPano
  • CylindricalPanel
  • Pano

Panoは、既に登場しましたが、360度写真をVR空間に貼り付けるタイプのコンポーネントです。

VideoPanoは、Panoと同様ですが、貼り付け可能コンテンツが360度動画となります。CylindricalPanelは、ちょっと特殊なコンポーネントで、内側にテクスチャを貼ることができ、子コンポーネントを収録できるタイプです。今回は触れません。

ビデオ・オーディオ関連のコンポーネント

ビデオの話が少し出ましたが、ビデオ・オーディオ系に関係してくるコンポーネントは以下となります。

  • Sound
  • Video

Soundは、シーンに配置するコンポーネントですが、何か形があるわけではありません。音の発生源として配置する形になります。3Dオーディオをサポートしており、ヘッドマウントディスプレイを被って顔を左右に振ったりすると、音源の場所に応じたサウンドになることが確認できます。

Videoは、2Dのビデオを再生するためのコンポーネントです。これをユーザーの前面に貼ると巨大なテレビが目の前に広がったような演出ができます。

ユーザーインターフェースとなるコンポーネント

続いて、VR世界のユーザーインターフェースとなるコンポーネントが下記2つです。

  • VrButton
  • VideoControl

VrButtonは、ボタンです。応用性が高く、使い勝手の良いコンポーネントと言えるでしょう。VideoControlは、ビデオをコントロールするためのユーザーインターフェースとなります。 VideoコンポーネントとVideoControlコンポーネントを組み合わせると、VR空間にビデオプレーヤーを作ることができます。

Videoコンポーネントでビデオを表示させているサンプル

形状コンポーネント

そして、今回扱う形状コンポーネントです。

  • Box
  • Cylinder
  • Plane
  • Sphere
  • Model

上記のうち、Modelを除いた4つは3Dプリミティブコンポーネントと呼ばれます。Boxは立方体や直方体などを作成することができるタイプのコンポーネントです。Cylinderは、円筒形の形状コンポーネントで、設定によっては円錐形の形状を作成することができます。Planeは、フラットな平面コンポーネントです。

ちなみに、Modelは空間に配置するコンポーネントだけど、別の3Dソフトなどで作成したモデルデータを使用するためのもので、今回は一旦スキップします。

これ以外にもライティングに関するコンポーネントも存在しますが、実際に使うところで解説していきます。

では、今回は実際に3Dプリミティブコンポーネントを、シーンにいろいろと配置し、様々なライティングをしてみましょう。

3Dプリミティブコンポーネントを配置してみよう

さて、これから3Dプリミティブコンポーネントを配置していろいろ実験していくわけですが、その前に、何か仮想現実の実験ぽくするための会場づくりをしましょう。React VRで何も背景に敷かない場合、漆黒の空間に単なる立方体が浮かぶことになります。それでは何も趣がないですよね。

ということで、VR空間をホロデッキ(アメリカのTVドラマ・映画のスタートレックに登場するホログラフィックルーム)として定義してみましょう。ホロデッキってなあに?って方は、Wikipediaのホロデッキに関する説明と写真をご覧ください。

ホロデッキは、黒い部屋に、方眼紙のような感じで黄色の線が入っている部屋です。これを実現するためにPanoコンポーネントを使います。Panoコンポーネントは360度写真を閲覧するために前回使いましたが、Panoコンポーネントはもう一つ使い方があって、6つのテクスチャを配列で渡してあげると、立方体のの内側にテクスチャが貼られた部屋を作ることができます。

では、まず新規React VRプロジェクトを作成するところから始めてみましょう。

1. 新規React VRプロジェクトを作成し、Panoコンポーネントで部屋を作る

まずはなにはともあれ、新規ReactVRプロジェクトを立ち上げましょう。名前はHello3DObjectとしましょう。

続いて、Panoコンポーネントを使って、テクスチャが貼られた立方体の空間を作っていきます。プロジェクトルートにある「index.vr.js」のViewコンポーネント以下を編集していきます。今回Panoコンポーネントの内側には、前後左右上下の6面にテクスチャを貼ります。貼るテクスチャは、フリーのグリッドパターン – 20 Seamless Photoshop Grid Patternsのうち一枚をPhotoShopで修正した格子状のものです。

ホロデッキっぽいテクスチャ画像

上記リンク先でダウンロードしたファイルを解凍し、中に入っている「holodeck.png」を「static_assets」ディレクトリ以下に配置します。

Panoコンポーネントに対して六面にテクスチャを貼るには、source属性にuriプロパティを持ったオブジェクトを6つ含んだ配列を渡します。asset関数は、ファイル名を渡すと{uri: パス名}の形式で返るので、asset関数をそのままsource属性へ渡せばいいことになります。

さて、まずはここで一旦ビルドしてみましょう。

ブラウザで、http://localhost:8081/vr/を開いてみましょう。スタートレックのホロデッキのような空間が出現したと思います。テクスチャのつなぎ目とか細かい点はサンプルということでご容赦ください。

ホロデッキに入った

2. Boxをいくつか並べて配置してみる

ホロデッキ的な空間が出来たところで、Boxコンポーネントを配置してみましょう。Boxコンポーネントはシンプルなコンポーネントですが、よくありがちな失敗として、Boxコンポーネントをインポートし忘れるということがあります。これから登場するCylinderSphereも同様にimportし忘れがないようにしましょう。

では、Boxコンポーネントを目の前に3つ配置してみます。Panoコンポーネントの下にBoxコンポーネントを下記のように3つ記述します。

dimWidthdimHeightdimDepthの各属性は、幅、高さ、奥行きのサイズに相当します。この比率を変えることで、立方体や柱のようなもの、平らな板のようなものを作り出すことができます。

また、style属性で色が定義されていることもわかります。3つの色は右から青、赤、緑の原色です。style属性にtransformというプロパティが定義されていますが、ここで配置を指定しています。位置関係の変形は、translateで指定します。配列で指定し、左からX座標、Y座標、Z座標となります。Z座標は奥行きです。ちなみにマイナスの数値になればなるほど初期状態の位置から奥へ向かって移動する形になります。

litという属性がありますが、こちらはライティングに関するプロパティで、後ほど解説します。

Boxコンポーネントを3つ配置した

Boxコンポーネントを配置できたところで、他のコンポーネントを配置していきましょう!

3. Boxだけでなく、CylinderSphereを配置してみる

さて、今度はCylinderSphereもシーンに配置してみます。一旦Boxコンポーネントのパートで作った3つのボックスは消してしまいましょう。勢いあまってホロデッキっぽくしているPanoまで消さないようにしてくださいね、情感がなくなってしまいますので。

まず、Cylinderコンポーネントについて。Cylinder、つまりカタカナでいうシリンダーは、円筒を意味しますが、Cylinderコンポーネントはプロパティ次第で円錐形にもなります。ポイントはradiusTopradiusBottomで、radiusTopが小さければ山のようになっていき、radiusBottomが大きければ、ラッパのような形状になっていきます。どちらの値も等しい時だけ円筒形になります。

続いてSphereコンポーネントですが、Sphereというのは球体です。Sphereコンポーネントはなかなか使い出があるコンポーネントで、四角形や円筒形を使う機会はそれほどないかもしれませんが、球体というのはテクスチャを貼り付ければ惑星になったりと応用性が高い3Dプリミティブコンポーネントです。下記のようにシーンに配置してみました。それぞれ一つずつ配置しています。SphereコンポーネントにはwidthSegmentsheightSegmentsというプロパティがありますが、これは球体を構成するセグメント(分割数)を定義しています。この数が増えるとなめらかな球体へ近づいていきます。

今回、ちょっと配置に工夫をしています。translateプロパティの値を変更していて、手前に立方体、奥に行くにしたがって円筒形、球体と並ぶようにしています。これで3Dプリミティブの配置は完了したわけですが、何かもの足りません。のっぺりしていて立体感がないのです。ということで、この3Dオブジェクトに光を当てていきましょう。

配置された、球体、円錐形、立方体

4. 3Dプリミティブオブジェクトに光を当ててみる

React VRでライティング(照明)を行うには、用意されている4つのコンポーネントのいずれかもしくは複数の組み合わせを使用します。

用意されているReact VRコンポーネントは下記の4つです。

  • AmbientLight
  • DirectionalLight
  • PointLight
  • SpotLight

AmbientLightは、環境光と呼ばれるもので、シーン全体に均一な影響を与える光源を定義します。これは無指向性で、すべてのオブジェクトが等しく明るくなります。

DirectionalLightは、指向性があるが、距離による明かりの減光は発生しないタイプの光源です。太陽の明かりのようなものと言えます。

PointLightは、ある一点から発生する光源で、距離による減光もあります。見えない間接照明のようなものと言えるでしょう。

SpotLightは、文字通りスポットライトのような特性を持つととらえられる光源です。指向性があり、距離による範囲の拡大と減光があります。

20程度のコンポーネントしか用意されていないReact VRにおいて、ライティング関係だけで、4つもコンポーネントが用意されているのは、一つはVRにおいてそれだけ重要であるということと、React VRが使用しているThree.jsにおいても手厚いサポートがされていること、そしておそらくはこうしたライティング関係は、カスタムコンポーネントとしての作成が困難であろうことなどが推測されます。

まずは普通の光を当てましょう。太陽のように上から降り注ぐ普通の明かりです。こういった明かりは、DirectionalLightコンポーネントを使うことで実現できます。

では、まず準備段階として、先ほど作成した3種類の3Dプリミティブオブジェクトが持っているlitプロパティをtrueにしてみましょう。これで光源の影響を受けるようになります。試しにtrueにした段階で、ブラウザをリロードしてみてください。まだ光が当たっていないため、真っ黒のオブジェクトになってしまったと思います。

真っ黒の3Dプリミティブオブジェクト

続いて、DirectionalLightコンポーネントを配置します。Panoコンポーネントの下あたりでOKです。こんな感じにします。(importを忘れずに)

intensityプロパティは、光の強度を設定します。また、光源にも色をつけることができ、スタイルシートで定義します。transformプロパティでrotateXの設定をしていますが、これは、ちょっと斜め前方から光を当てたいからです。本当の真上からあたる光は、側面すら陰になってしまい、あまり面白みはありません。

DirectionalLightを設定したシーン

次はPointLightコンポーネントを配置してみましょう。PointLightは点光源なので、任意の位置に配置すると、その周囲を照らしてくれます。うまく使うと印象的な効果を与えることができます。さて、今回は、PointLightをちょっと手前に配置し、しかもちょっと青系の光として照らしてみましょう。どんな感じになるでしょうか。

DirectionalLightコンポーネントの下に、下記のようにPointLightコンポーネントを設置します。

intensityプロパティはちょっと強めの5にしました。色は青色、そして位置はちょっと手前でちょっと下から照らす感じにしています。

すると、こんな感じで、青い光がオブジェクトに反射するような雰囲気になりました。ちょっとムーディで怪しげですね。

PointLightを反映させた3Dプリミティブオブジェクト

さて、これで終了にしてもいいのですが、全体的にちょっと暗いですよね、そこで光の調整をしたいと思います。

ではAmbientLightコンポーネントを配置してみましょう。AmbientLightは環境光で、全てのオブジェクトに均等に光を当てるという機能を持っています。AmbientLightコンポーネントを使うことで、全体的な光の加減を微調整することもできます。

intensityプロパティは、ほんの少しだけ設定しました。これでブラウザをリロードしてみると、ほんのりと明るくなったことがわかると思います。

AmbientLightを反映させた3Dプリミティブオブジェクト

いろいろな形状のものを置き、ライティングを終えたところで、こんな風に思った方はいないでしょうか。
「現実世界で立方体や球なんて、積み木とかにしか存在しないじゃないか!」
と。

四角や丸を置くためにVRを始めたわけじゃないんだという気持ちはよくわかりますので、次回は応用編として既存の3DモデルをReact VRで扱う方法について解説していきます。

Powered byNTT Communications

tag list

アクセシビリティ イベント エンタープライズ デザイン ハイブリッド パフォーマンス ブラウザ プログラミング マークアップ モバイル 海外 高速化 Angular2 AngularJS Chrome Cordova CSS de:code ECMAScript Edge Firefox Google Google I/O 2014 HTML5 Conference 2013 html5j IoT JavaScript Microsoft Mozilla Node.js PhoneGap Polymer React Safari SkyWay TypeScript UI UX W3C W3C仕様 Webアプリ Web Components WebGL WebRTC WebSocket