CrossRoad

XRを中心とした技術ブログ。 Check also "English" category.

Babylon.jsでナイトプールを作って、Unityとの作りやすさを整理しました

以前、UnityのShaderの勉強のため、ナイトプールのような風景を作ったことがあります。

【Unityアセットアドカレ】Shader Forgeでナイトプールを作ろう! - CrossRoad

今回、Babylon.jsの勉強を兼ねて、前に作ったものに似せたナイトプールを作って、Unityで作った場合の比較を考察してみました。なお、動作確認は以下の環境で行なっています。

Chrome  : 68.0.3440.106
Babylon.js :v3.2.0




0. Babylon.jsで開発するための事前準備

テキストエディタを準備して、以下のコードを貼り付けます。
(長いのでブログには表示しておりません。クリックで確認ください)

gist01b5059b8cca9f56877b96102a87fc62

これは、Babylon.jsのコミュニティサイトで提供されているサンプルコードです。私の場合、ゼロからhtmlやscriptタグ、基本文法を追加していくとうまく動きませんでした。例えば、ゼロから書いたコードでテクスチャの貼り付けをしようとしたところ、このようなエラーが出たことがあります。

uncaught TypeError: e.isPointerCaptured is not a function
    at e.callback (advancedDynamicTexture.ts:593)
    at r.notifyObservers (babylon.js:3)
    at HTMLCanvasElement._onPointerDown (babylon.js:12)

もちろん、私がまだBabylon.jsの使い方を理解できていないのが原因ですが、提供されているサンプルコードをベースに作る方が確実なので今回はこの方法を紹介いたします。

1. MeshBuilderで枠を作る

Mesh Builderとは、基本図形を作るメソッドです。下記に詳細がありますが、SphereやBoxなどの図形を作ることができます。このようなコードを書きます。


gist65f18bcb15ebe1a6d63c2a5dd7fd2def

CreateBoxで枠部分、CreateGroundで水部分を作ることができます。

すると、このようになります。CreateGroundはこの時点ではただの板ですが、あとで水面に変化させます。

BJSのMeshBuilderメソッドを使って、プールの枠を作った状態

ここで参考にしたURL
Babylon 101 Discover Basic Elements

2. 枠にレンガのテクスチャを適用させる

レンガのテクスチャを適用させるには、新しくマテリアルを作ってテクスチャを入れ込みます。このようなコードを書きます。StandardMaterialメソッドでマテリアルを定義して、テクスチャと対応づけます。


gist4083d91ca1585b8cf01dbd78d65a69cc

すると、このようになります。

BJSのStandardMaterialメソッドを使って、プールの枠にテクスチャを貼った状態

ここで参考にしたURL
Babylon 101 Material

3. Skyboxで星空を作る

Unityと同じようにSkyboxを使うことができます。実際はSkybox専用の設定はあまりなく、空間を覆う巨大な立方体を作って、その六面体にテクスチャを貼り込むイメージです。このようなコードを書くことで実現できます。


gist56821741e65b3872b8f9b3106b8d50bc

Skybox用の6枚のテクスチャは、ファイル名の最後にnx,ny,nz、px,py,pzが付いている必要があります。それらが付いた上で接頭辞の名称を一致させ、上のgistのように省略形で表現します。今回は"night_star"が共通の接頭辞です。

BJSでCubeTextureに設定する時のテクスチャファイル名の例

すると、このようになります。

BJSのStandardMaterialメソッドを使って、Skyboxを適用させた状態

ここで参考にしたURL
How To Use a Skybox




4. WaterMaterialで水の表現を作る

Babylon.jsには水面を表現するマテリアルが準備されています。これをCreateGroundで作った平面に適用させるため、このようなコードを書きます。


gist39b4bf9d168d9b076eff0da1dd2f722b

レンガのテクスチャを適用させたときと考え方は同一です。WaterMaterialで定義したあと、最後に平面オブジェクトのマテリアルと対応づけをします。

1つ注意事項があります。まだ理由がわかっていませんが、WaterMaterialのコードはSkyboxよりも後で定義しないと有効になりませんでした。サンプルコードではWaterMaterial以外ほとんど書いてないので、気づくのに時間がかかりました。

WaterMaterialが効くと、このようになります。

BJSのWaterMaterialメソッドを使って、水面を表現した状態

ここで参考にしたURL
Extentions Water

5. GlowとPoint Lightで光の球を作る

最後に、光の球を水中に配置します。球を光らせるにはGlowLayerメソッドを使います。このようなコードを書きます。


gist2a01c699958018321c65a7881ea77f31

GlowLayerを使って、この中に準備されているcustomEmissiveColorSelectorで、対象オブジェクトについて発光色を指定します。これだけだと水面下の光があまり強調されなかったので、後半ではpoint lightを指定しています。



ここまで作ると、このようになります。

参考までに、Unityで作ったときの動画も掲載します。

Unityで作ったときはPoint Lightで周辺の光を綺麗にして、PostEffectをかけて強調しました。Babylon.jsではPoint Lightだけでは周辺が思ったほど強調できませんでしたが、WaterMaterialやGlowLayerである程度のものが作れることがわかりました。

現時点ではUnity作った方がきれいですが、これだけの表現がindex.htmlだけで実現できるのはよいと思いました。

今回作ったコードをGitHubにあげました。Gistでは概念をわかるようにしたので、GistとGithubのコードでは少し順番が変わっていますがご了承ください。

GitHub - flushpot1125/APool_under_the_star_filled_with_BJS: See : http://www.crossroad-tech.com/entry/a_pool_under_the_starfilled_withBJS

6. UnityとBabylon.jsの違いを検証

同じものをUnityとBabylon.jsで作ったことで、両者の違いが色々わかりました。そこで、今回作った各項目について、作りやすさの観点で整理しました。
ただし、UnityとJavascriptのバックグラウンドを持った人によって印象が変わるので、今回の整理結果もかなり主観が入っています。こういう見方もある、という参考程度でお願いします。

6-1. 基本図形の生成

スクリプトで書いて、Chromeで確認する、というのも慣れるとよさそうですが、UnityのGUIですぐにCubeなどのオブジェクトを生成し、厚さ、高さなどをマウスで操作できるのは強いと思います。

Babylon.jsではBabylon.js EditorというGUI開発環境があるのですが、通信環境かPCのスペックの問題か、私の環境では起動や動作に時間がかかることと、いまいち使い方が把握できていないので、使えていません。

Post Processの設定項目が色々あって気になるので、別途調べたらまとめたいと思います。

6-2. テクスチャ

慣れの範囲なので、どちらがよいかは決めづらいところです。たとえば、Babylon.jsの場合、テクスチャをマテリアルの中に宣言してしまえば、<オブジェクト名>.material と対応づけるだけです。慣れるとこっちの方が早いかもしれません。

一方、実質全てコードで書くので、コード量が多くなるのはやりづらいかもしれないですね。

6-3. SkyBox

UnityではWindow / Lighting / Settings を開いてskybox用のcubemapを指定します。Babylon.jsでは、ファイル名のルールに沿った6枚のテクスチャを準備して、StandardMaterialで定義すれば使うことができます。

やはりGUIで定義できるUnityの方がやりやすそうですね。Babylon.js Editorの使い方がわかったら改めて比較したいと思います。

6-4. Water

UnityにもWater Shaderが準備されているので、問題なく使うことができます。(マテリアルで波の速さなども設定できます) 一方、Babylon.jsではWaterMaterialで定義ができるのと、簡単なプロパティ設定で波のスピード、反射物の指定などができます。

結局は好みですが、私はBabylon.jsの方がやりやすいと感じました。

6-5. 光の表現

現在わかっている範囲ではUnityの方がきれいな表現になると思います。ただし、Unityできれいな光の表現を作るには、下記の過去記事のようなことを調べ続けてわかったので、色々と試行錯誤がありました。

【Unity】HDRを使ったIBLができるアセットSkyShopの概要とAndroidで動かした結果をまとめました - CrossRoad

【2018/2/20更新】【Unity】3Dモデルの見た目をきれいにする方法 - CrossRoad

@Muro_CGさんの講演を元に、Unityの表現力を高める勉強をしました - CrossRoad

その点、Babylon.jsではGlowLayerメソッドを使って少し工夫するだけで、このようなぼんやりと光る球の表現ができました。

BJSのGlowLayerメソッドで光らせた球の例

もちろんUnityを通してある程度CGの知識がついたからBabylon.jsでの表現が早かったというのはありますが、数行のコード記述だけできれいになるのは魅力的と思いました。

7. 終わりに

今回、同じものをUnityとBabylon.jsで作ったことで、色々と違いがわかりました。作りやすさは好みが入るので決めづらいですが、Babylon.jsでは思った以上に少ないコードでやりたいことができると感じました。

ただ、Unityに慣れていると、Babylon.jsでの環境構築や作り方が難しく感じます。特に日本語の情報がほとんどなく、基本的な使い方についても実質英語でしか情報が提供されていない状態です。

そこで、次回はBabylon.jsで何かを作る時の基本的な準備やよく使うコードの解説などをしたいと思います。