V-Ray for Unity Babylon

提供: ディーズガレージ wiki
2019年10月18日 (金) 22:56時点におけるShogooda (トーク | 投稿記録)による版 (Compressed Texture ※)

移動先: 案内検索

高品質WebGLのワークフローを探ってみます。

Babylon04 thumb.png

https://dz.plala.jp/wiki_data/babylon04/

Babylon05 thumb.png

https://dz.plala.jp/wiki_data/babylon05/

Babylon06 thumb.png

https://dz.plala.jp/wiki_data/babylon06/

環境

DCCツール 3ds Max 2017, V-Ray, Unity 2018, Babylon.js
モデルデータ Evermotion Archinteriors vol.35 Scene2,6,7
検証環境 iPhone XS, Windows10(GTX1050Ti)

目標品質

引用: Scene7 AI35 Archinteriors - Evermotion
引用: Scene6 AI35 Archinteriors - Evermotion
引用: Scene2 AI35 Archinteriors - Evermotion
引用: Bedroom デモ: 建築ビジュアリゼーションとSSRR – Unity Blog

Unity Staffの仕事

  • リダクション
  • Directional Light (太陽)
  • Point Light (ランプ)
  • Cubemap
  • Light Probe
  • Reflection Probe
  • Screen Space Reflection

素材準備

参考: Baking lightmaps with Vray and 3D Studio Max, a tentative guide - Unity Forum
参考: Vray lightmapping workflow in 3dsmax - Unity Forum

※ 3dsMaxのUVWチャンネル2(UnityのUV1)は設定しない

データ修正

3ds Max
├ ガンマ 基本設定 > ガンマ/LUT 設定 > ガンマ 2.2
├ 単位 単位設定 > センチメートル, システム単位設定
> センチメートル
└ レンダリング設定 V-Ray tab > Color mapping >
Type: Linear multiply
Dark multiplier:1.0, Bright multiplier:1.0
GI tab > Primary engine: Irradiance map : Very low
GI tab > Secondary engine: Light cache
3ds Max
├ レイヤ分け 加工しやすいよう家具毎などに小分け
カメラとライト > Camera&Lightsレイヤ
GIが不要なもの > NoGIレイヤ
├ マルチ/サブOBJ デタッチ
├ リダクション プロオプティマイザーのUV保持 > 集約
├ マージ 同じマテリアルのオブジェクト
├ UVWアンラップ ベイク用 GI対象のみ
├ 整理 0レイヤ: GI対象すべて ユニーク名通し番
NoGIレイヤ: NoGI_***ユニーク名通し番
Camera&Lightsレイヤ: カメラとライト
└ 整理 ベイク解像度レイヤ分け 512 1024 2048 例外4096

露出固定

試行

  • 3dsMax2016以降のVRayPhysicalCameraについて
  • Bakeに使用されるCameraはViewerで使用してるCameraを使用?(非表示関係なく) > カメラ削除
  • VRayPhysicalCamera(旧)は露出制御を非アクティブにできない > 標準フィジカルカメラ新規作成
  • maxファイル読み込み時、「ガンマとLUTが一致しません」> ファイル出力ガンマ 1 or 2.2 > 結果、関係なし

環境と効果 > Vray Exposure Control > アクティブ: OFF > レンダリング or Bake
環境と効果 > フィジカルカメラ 露出制御 > アクティブ: OFF > レンダリング or Bake

  • Frame buffer: OK
  • イメージを保存 OpenEXR,PNG ガンマ:自動 > NG
  • イメージを保存 OpenEXR,PNG ガンマ:1.0 > NG
  • イメージを保存 JPG ガンマ:自動 > NG
  • イメージを保存 JPG ガンマ:1.0 > OK

未確認 vray linear workflow - Google 検索

ベイク処理

3ds Max
├ ベイクサイズ 512~2048 例外4096
├ 要素 VRayCompleteMap
VRayRawTotalLightingMap
├ 要素の固有設定 Apply color mapping ON
└ 保存 オブジェクト名VRayCompleteMap.jpg
オブジェクト名VRayRawTotalLightingMap.jpg

FBX具合

3ds Max Unity
標準 フィジカルカメラ ×
標準 フリーカメラ
標準 ターゲットカメラ 〇 Look At Constraint
VRayPhisicalCamera ×
3ds Max Unity
標準 ターゲットスポットライト △ Type:Spot *.Targetゴミ
標準 ターゲット指向性ライト △ Type:Directional *.Targetゴミ
標準 オムニライト 〇 Type:Point
標準 フリースポットライト 〇 Type:Spot
標準 フリー指向性ライト 〇 Type:Directional
標準 スカイライト △ Type:Point
フォトメトリック ターゲットライト △ Type:Point *.Targetゴミ
フォトメトリック フリーライト △ Type:Point
フォトメトリック サンポジショナ ×
VRayLight ×

FBX書き出し

3ds Max
├ VRayMtl Unityで詰めるのでVRayMtlのまま(書き出し時のエラーは無視)
├ VRayLight 標準ライトに修正
├ VRayCamera 標準カメラに修正
├ 書き出し オブジェクト カメラとライト以外を選択 > 書き出し > 選択を書き出し
└ 書き出し カメラとライト カメラとライトを選択 > 書き出し > 選択を書き出し

V-Ray for Unity

Build

  • Edit Menu > Project Settings > Player > Other Settings > Color Space: Linear
  • Lighting > Scene tab > Auto Generate OFF
  • FBX読込み
  • (GameObject).FBX > Inspector > Geometry > Generate Lightmap UVs OFF(デフォルト)
  • FBX配置
  • Hierarchy > (GameObject) > Inspector > Static OFF(デフォルト)

  • Collider.FBX > Mesh Collider追加
  • Light Type: Realtime, Intensity: 0.01 or 0
  • Material: Unity > Legacy Shaders > Lightmapped > VertexLit > Lightmap

  • Hierarchy > (GameObject) > Inspector > Static ON
  • Reflection Probe Type: Baked > Bake実行
  • Hierarchy > (GameObject) > Inspector > Static OFF
  • File Menu > Build Settings > Build

V-Ray comp版

Build Data: 88MB
AI35_006_02_completemap_build_windows.zip

V-Ray lightmap版

Build Data: 74MB
AI35_006_02_lightmap_build_windows.zip

Unity enlighten版

Unity
├ 読込み (GameObject).FBX
├ Generate UVs (GameObject).FBX > Inspector > Geometry > Generate Lightmap UVs ON > Apply
├ Color Space Edit Menu > Project Settings > Player > Other Settings > Color Space: Linear
├ 配置 Hierarchy > (GameObject)
├ Static Hierarchy > (GameObject) > Inspector > Static ON > Yes, change children
├ Cast Shadow Hierarchy > (GameObject) 窓ガラス以外全て選択 > Inspector > Cast Shadow: ON (窓ガラスはOFF)
├ Globalillumination Window Menu > Rendering > Lighting Settings >
Scene tab > Mixed Lighting > Baked Globalillumination ON
├ Lightmap bounses Window Menu > Rendering > Lighting Settings >
Scene tab > Lightmapping Setting > Bounses: 2 (デフォルト: 2)
├ Lightmap Resolution Window Menu > Rendering > Lighting Settings >
Scene tab > Lightmapping Setting > Lightmap Resolution 調整中10程度 仕上げ20程度
├ Lighting Mode Scene tab > Lighting Mode > Subtractive
└ Lightmap scale Hierarchy > (GameObject) GI対象全て選択 > Lightmap Static ON > Scale In Lightmap 調整中2程度 仕上げ8~10程度
Unity
├ Light Hierarchy > (GameObject)ライト > Type: Area(baked only)
Mode: Baked
Shadow Type: Hard(直射光) or Soft(反射光, 昼光)
Intensity: 1程度から始め微調整
├ SSR Post Processing Stack > Screen Space Reflection
├ Color Grading Post Processing Stack > Color Grading 不採用
├ Reflection Reflection Probe
├ Collider Mesh Collider
├ FPS FPSController, FirstPersonCharacter
├ Material Standard Shader (PBRマテリアル) 全て作り直し
└ Build File Menu > Build Settings > Build
Build Data: 121MB
AI35_006_03_unity_build_windows.zip

V-Ray for Babylon

参考: Getting Started (Unity exporter) - Babylon.js Documentation
参考: Getting Started - Babylon.js Documentation

ビデオチュートリアル
Unity Exporter (日本語字幕向け)
BabylonJS Editor

Build

  • Hierarchy > Main Camera > Inspector > Transform Position Y: 1
  • Hierarchy > Main Camera > Inspector > Add Compoment > Babylon > System Componrnts > Camera Rig > Camera Type: Universal Camera, Camera Input: Attach Render Canvas Input, Camera Speed: 0.04, Input Move Speed: 0.04, Apply Camera Gravity: OFF
  • Hierarchy > Create Empty > GameObject > Inspector > Add Component > Babylon > System Componrnts > Default Scene Controller > Lighting Options > Ambient Scale: 10 (V-Ray Completemap版)
  • Babylon Exporter > Default Engine Options > Default Image Format > JPG
  • Babylon Exporter > Toolkit Exportation Options > Show Render Stats: ON
  • Babylon Exporter > Build And Preview

V-Ray comp版

  • Unity Exporter > Set Image EncodingのJPG>JPG変換はQuality設定が機能していないように見える
  • ↑Build前に直接PhotoShopで保存し直す
  • Legacy Materialを正常な露出に戻す目的にAmbient Scaleを使用
  • ↑全体の露出補正をする手段がないので事前に露出確定
  • 4096サイズtextureを多用するとiPhone XSのload errorが出るように見える
  • ↑texture Size 2048x2048 サイズ制限
  • ↑Unity Exporterではサイズ書き換え設定がない Unity標準は4096サイズは2048サイズ表示
Build Data:48MB
https://dz.plala.jp/wiki_data/babylon01/
Build Data:75MB
https://dz.plala.jp/wiki_data/babylon02/
Build Data:120MB
https://dz.plala.jp/wiki_data/babylon03/

V-Ray comp+PBR版

  • 変更 Default Scene Controller > Lighting Options > Ambient Scale: 0
  • 変更 Legacy MaterialのLightmap(VRayCompleteMap)と同等のStandard Material設定
  • ↑Main Maps Albedo > VRayCompleteMap, Color:白
  • ↑Main Maps Emission > VRayCompleteMap or VRayRawTotalLightingMap, HDR Color:白
  • ↑VRayRawTotalLightingMapが正解に見える
  • Main Maps Metallic, Smoothness 主要なもの全てに設定
  • Main Maps Normal Map 主要なもの全てに追加
  • Directional Light Realtime No Shadows 追加 Normal向け
  • Default Scene Controller > Lighting Options > Ambient Scale 全体の露出補正
  • Ambient Scaleをマイナス補正出来ないが、個々のEnissionはUnity Exporterで機能する 代案
  • Secondary MapsのDetail AlbedoとNormal MapとTiling, Offsetが使えない 非効率だがMain Mapsを使用
  • Normal Mapはビルド後、余白部分ベタ塗 容量削減
  • texture Size 2048x2048 サイズ制限

具合

  • Babylon Standard Material設定後Unity Standard Materialに変更するとStandard Shader内にBabylon Optionsが出てくる バグ?使っていい?
  • マテリアル変更が不安定 再現性が取れてない
  • Secondary Mapsが無いのが致命的 強引にMain Mapsでディティールを作る
  • Add support for Secondary Normal Map / Detail Normal Map · Issue #5967 · BabylonJS/Babylon.js · GitHub
  • iPhone XSで2048 サイズ制限してもローディングエラーが出る texture:50, 2K-texture:30めどで様子見
  • iPhone XSで画面左端をフリックすると操作不能になる
  • iPhone XS, Windows10(GTX1050Ti)は60FPS グラフィックボード無しは20FPS
  • iPhone Xで動かない?
Build Data:52MB
https://dz.plala.jp/wiki_data/babylon04/
Build Data:90M
https://dz.plala.jp/wiki_data/babylon05/
Build Data:120MB
https://dz.plala.jp/wiki_data/babylon06/

Other

V-Ray Lightmap+PBR版
このスキームに合わない気がする

Unity Enlighten版
建築に向かないGIに見える

WebGL最適化

Babylon Inspector

参考: The Inspector overview - Babylon.js Documentation
参考: Introduction to the Inspector - video series - Babylon.js Documentation
参考: WebGL2 - Babylon.js Documentation

SYSTEM INFO

Driver NVIDIA GeForce GTX 1050 Ti Apple GPU
WebGL version 2 ※ 1
Std derivatives
Compressed textures
Hardware instances
Texture float
Texture half-float
Render to texture float
Render to texture half-float
32bits indices
Fragment depth
High precision shaders
Draw buffers
Vertex array object
Timer query
Stencil
Parallel shader compilation
Max textures units 16 8
Max textures size 16384 4096
Max anisotropy 16 16

※ EdgeはWebGL1

COUNT

Scene babylon04 babylon05 babylon06
Total meshes 42 59 93
Active meshes 33 47 77
Active indices 832,971 1,343,862 2,023,044
Active faces 277,657 447,954 674,348
Active bones 0 0 0
Active particles 0 0 0
Draw calls 34 47 77
Total lights 2 2 2
Total vertices 178,916 369,657 672,556
Total materials 39 55 86
Total textures 86 85 139

Web Inspector

参考: Mac Safari上でiOS SafariのWebインスペクタを表示 - Qiita
環境 Safari12.1.1
iPhone XS WebGL1

警告
Babylon.js performance monitor detected webgl version 1.
Render to float textures is not supported. Mipmap generation forced to false.
起動成功

iPhone XS WebGL2.0 ON

警告
Float texture filtering is not supported.
Mipmap generation and sampling mode are forced to false and TEXTURE_NEAREST_SAMPLINGMODE, respectively.
起動失敗

WebGL1互換が無難

gzip CORS

参考: Why and how we migrated babylonjs.com to Microsoft Azure – David Rousset
参考: gzipの各圧縮レベルでの圧縮率と処理時間の計測 - Qiita
apache .htaccessの場合

<IfModule mod_deflate.c>
SetOutputFilter DEFLATE
 
#古いブラウザ対策
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch \bMSIE\s(7|8) !no-gzip !gzip-only-text/html
 
#画像は圧縮しない GIF、JPEG、PNG、ICO
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|ico)$ no-gzip dont-vary

#圧縮するファイル
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE text/js
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/atom_xml
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/x-httpd-php
AddOutputFilterByType DEFLATE application/x-font-ttf
AddOutputFilterByType DEFLATE application/x-font-woff
AddOutputFilterByType DEFLATE application/x-font-opentype
AddOutputFilterByType DEFLATE application/json
AddOutputFilterByType DEFLATE application/babylonmeshdata
AddOutputFilterByType DEFLATE application/babylon
AddOutputFilterByType DEFLATE application/hdr
</IfModule>
Scene babylon04 babylon05 babylon06
babylonファイル 30.16 MB 59.91 MB 106.66 MB
転送量 10.08 MB 18.08 MB 34.17 MB

効果絶大
CANVAS汚染は無いのでCORS未設定

Compressed Texture ※

参考: Multi-Platform Compressed Textures - Babylon.js Documentation
参考: WebGLでのテクスチャ圧縮を容易化 – PlayCanvas

PVRTexToolのインストール
省略 astcenc.exeのダウンロード
PVRTexToolCLI.exe辺りに設置
設定

1.システム設定に移動し、「システムの詳細設定」を選択します。
2.「環境変数」を選択し、
3.環境変数の変数「Path」を選択し、「編集」をクリックします。
4. ASTCエンコーダーのフォルダを入力します。
5.「OK」をクリックします。

PVRTexToolCLI.exeのpathが通らない? PVRTexToolCLI.exeのフォルダにテクスチャte(JPGとPNG)とktx-files.batとmake-ktx-batch.batを配置
コマンドプロンプト

>cd PVRTexToolCLI.exeのフォルダ
>make-ktx-batch Q
エラーっぽいものが出るが無視
>ktx-batch
フリーする勢いで計算するので注意

Optimize Scene

参考: Optimize your scene - Babylon.js Documentation

■Reducing Shaders Overhead
追加

                            // Optimize scene
                            arrayMaterials = scene.materials;
                            for (var i = 0; i < arrayMaterials.length; i++) {
                                arrayMaterials[i].freeze();
                            };

■Reducing World Matrices Computation
パフォーマンスを改善できる
位置/回転/スケーリングの変更は無視され
追加

                            // Optimize scene
                            arrayMeshes = scene.meshes;
                            for (var i = 0; i < arrayMeshes.length; i++) {
                                /*arrayMeshes[i].freezeWorldMatrix();*/ // Clockが動かないのでコメントアウト
                                arrayMeshes[i].doNotSyncBoundingInfo = true;
                            };

■Freezing the active meshes
アクティブメッシュの計算時間を省ける
このスキームではScreenshotに影響がある
追加

                            // Optimize scene
                            /*scene.freezeActiveMeshes();*/ // メッシュが一部消える現象があるのでコメントアウト

■Not updating the bounding info
計算が高速になる
collisionを使用する場合問題になる可能性あり
追加

                            // Optimize scene
                            arrayMeshes = scene.meshes;
                            for (var i = 0; i < arrayMeshes.length; i++) {
                                arrayMeshes[i].doNotSyncBoundingInfo = true;
                            };

■Reducing calls to gl.clear()
ローエンドデバイス向け設定
閉鎖空間かスカイボックスで囲まないと背景色が変になる
追加

                            scene.autoClear = false;
                            scene.autoClearDepthAndStencil = false;

■Turning AdaptToDeviceRatio Off
ローエンドデバイス向け設定
修正

            // Optimize scene
            // var engine = new BABYLON.Engine(divcvs, antialias, null, adaptive);
            var engine = new BABYLON.Engine(divcvs, antialias, null, false);

■Blocking the dirty mechanism
追加

                            // Optimize scene
                            scene.blockMaterialDirtyMechanism = true;

■Using Animation Ratio
ローエンドデバイス向け設定
追加

                            // Optimize scene
                            scene.getAnimationRatio();

Optimize Cache

参考: Optimize using Cached Resources - Babylon.js Documentation
SampleScene.babylonと同じディレクトリにSampleScene.babylon.manifestを作成

{
	"version" : 1,
	"enableSceneOffline" : false,
	"enableTexturesOffline" : false
}

追加

BABYLON.Database.IDBStorageEnabled = false;

何故か画像辺りをIndexedDBにキャッシュしてる

Memory Footprint

参考: Reduce memory footprint - Babylon.js Documentation

IndexedDBはメモリを消費するためOFF
追加 こっちが完全OFFっぽいが画像辺りをIndexedDBにキャッシュしてる

            // Memory Footprint
            //engine.enableOfflineSupport = offline;
            engine.enableOfflineSupport = false;

コンテキスト復元サポートは大量のメモリを消費するためOFF
追加

            // Optimize scene
            //var engine = new BABYLON.Engine(divcvs, antialias, null, adaptive);
            //var engine = new BABYLON.Engine(divcvs, antialias, null, false);
            var engine = new BABYLON.Engine(canvas, true, { doNotHandleContextLost: true }, false);

追加 心配なのでこっちも

            // Memory Footprint
            engine.doNotHandleContextLost = true;

メモリを解放 キャッシュされた頂点データを削除
衝突、ピッキング、ジオメトリ編集、物理学が使えなくなる 追加

                        // Memory Footprint
                        scene.clearCachedVertexData();

メモリを解放 キャッシュされたテクスチャバッファの削除
追加

                        // Memory Footprint
                        scene.cleanCachedTextureBuffer();

Scene Optimizer

参考: Use SceneOptimizer - Babylon.js Documentation

追加

                        // SceneOptimizer
                        BABYLON.SceneOptimizer.OptimizeAsync(scene, BABYLON.SceneOptimizerOptions.LowDegradationAllowed());

Lowより強くするとぶっ壊れた

Firefox エラー

Uncaught Error: Positions are required

無効にするのが無難

Reflection Probe

※ やってみたが効果が無いように見える

ミラーが汚い Reflection.hdr Equirectangular形式
高解像度化してみる

Unityにインストール
360° Screenshot Capture - Asset Store
Camera 追加 (capture用) CameraにAdd Component > New Script > NewBehaviourScript > Create and Add
Assets > NewBehaviourScript 書き換え

using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;

public class NewBehaviourScript : MonoBehaviour
{
	public int imageWidth = 1024;
	public bool saveAsJPEG = true;

	void Update()
	{
		if( Input.GetKeyDown( KeyCode.P ) )
		{
			byte[] bytes = I360Render.Capture( imageWidth, saveAsJPEG );
			if( bytes != null )
			{
				string path = Path.Combine( Application.persistentDataPath, "360render" + ( saveAsJPEG ? ".jpeg" : ".png" ) );
				File.WriteAllBytes( path, bytes );
				Debug.Log( "360 render saved to " + path );
			}
		}
	}
}

Mierarchy > Main Camera > Inspecror > New Behavior Script
Image Width: 2048, Save As JPEG: OFF
Playポタン押す > pボタン押す > 保存
保存先確認 > Windows menu > General > Console

photoshopで32bit変換 > スクロールで位置修正 > ***_Reflection.hdr 上書き

効果が無いように見える
これかも?
参考: How to use Reflection Probes - Babylon.js Documentation

Babylon Static

参考: Static Batching (Unity exporter) - Babylon.js Documentation
描画呼び出しを削減できるが大量のメモリを使用?
不採用

Draw Call

参考: Reducing draw calls - Babylon.js Documentation
参考: Use Instances - Babylon.js Documentation

GIベイクワークフローのためオブジェクト数(メッシュ数)とマテリアル数はほぼ同数
加えて、Draw Callは上記とほぼ同数
加えて、スマホ向けにはDraw Callを100以下に抑えるという情報もある

参考: Performance/draw calls - Questions & Answers - HTML5 Game Devs Forum

マルチマテリアルを使用とある
参考: Use Multi-Materials - Babylon.js Documentation

3dsMaxの場合、オブジェクトをマージしマルチサブオブジェクトにすることが同意なのかも

Unityの場合
参考: Unityのシーン上に配置したモデルを結合する - テラシュールブログ

Environment

参考: Use a HDR environment (for PBR) - Babylon.js Documentation
参考: Babylon Art Tools (Unity exporter) - Babylon.js Documentation
Unity > Lighting > Enviroment Skybox MaterialにDDS画像入れるとIBLと思うんだけど変化が見えない
保留

WebGL機能追加 共通

Libraries

追加
jQuery MIT License
UAParser.js MIT License

    <!-- Libraries -->
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/ua-parser-js@0/dist/ua-parser.min.js"></script>

修正

    <!--<script type="text/javascript" src="scripts/babylon.js"></script>-->
    <script type="text/javascript" src="https://preview.babylonjs.com/babylon.js"></script>
    <!--<script type="text/javascript" src="scripts/babylon.inspector.js"></script>-->
    <script type="text/javascript" src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>

Title

修正

    <!--<title>New Unity Project</title>-->
    <title>V-Ray for Unity Babylon</title>
            <!--<div id="proj">New Unity Project</div>-->
            <div id="proj">V-Ray for Unity Babylon</div>
            /*title = "New Unity Project"*/
            title = "V-Ray for Unity Babylon";

文字が欠ける
追加

        #proj {
            height: 20px;
        }

Favicon

追加

    <link rel="shortcut icon" type="image/x-icon" href="favicon.ico">
    <link rel="apple-touch-icon" sizes="180x180" href="https://dz.plala.jp/wiki_data/babylon04/apple-touch-icon.png">

apple-touch-icon.png

Notranslate

追加

    <meta name="google" content="notranslate" />

CSS

参考: HTML5 Reset Stylesheet | HTML5 Doctor
https://dz.plala.jp/wiki_data/libs/resetCSS.css
追加

    <link href="../libs/resetCSS.css" rel="stylesheet" />

追加

        *:focus:not(.focus-visible) {
            outline: none;
        }

        .focus-visible {
            outline-color: lightgreen;
        }

Canvas

表示アニメーション
修正

                //divcvs.style.opacity = "1";

追加

                        // Canvas
                        scene.afterCameraRender = function () {
                            setTimeout(function () {
                                $("#cvs").animate({ opacity: 1 }, { duration: 600, easing: 'swing' });
                            }, 300);
                        };

Loading Screen

参考: Create a custom loading screen - Babylon.js Documentation

gzip圧縮の影響で? lengthComputableが機能してない

LoadingUIに表示されるもの

lengthComputable 単位 表示容量
Edge false  %
Firefox false MB 圧縮容量
Chrome false MB 非圧縮容量
Mobile Safari false MB 非圧縮容量
Safari false MB 非圧縮容量

追加

            var parser = UAParser();

            // Loading Screen
            var loadTotal;
            if (parser.browser.name == "Firefox") {
                loadTotal = 11; // gzip圧縮容量
            } else {
                loadTotal = 31; // gzip非圧縮容量
            };

修正

                        //updateStatus(amount + units);
                        updateStatus((amount / loadTotal * 100).toFixed() + "%");

Cursor

追加

                        // Cursor
                        scene.onPointerDown = function () {
                            scene.defaultCursor = "all-scroll";
                            if (!controlPanelIsClosed) {
                                hideCameraPanel();
                            }
                        };
                        scene.onPointerUp = function () {
                            scene.defaultCursor = "default";
                        }

Collision

参考: Cameras, Mesh Collisions and Gravity - Babylon.js Documentation
scene.clearCachedVertexData()を実行するとCollisionが機能しない
Memory Footprintなのでメモリを使用する 無理しない
変更なし

                        if (parser.device.type || intelGPU) {
                            // Memory Footprint
                            scene.clearCachedVertexData();
                        }

追加

                        // Collision
                        if (!parser.device.type && !intelGPU) {
                            scene.collisionsEnabled = true;
                            camera.checkCollisions = true;
                            camera.ellipsoid = new BABYLON.Vector3(0.1, 0.1, 0.1);
                            arrayMeshes = scene.meshes;
                            for (var i = 0; i < arrayMeshes.length; i++) {
                                arrayMeshes[i].checkCollisions = true;
                            };
                        };

Skybox

参考: Sky - Babylon.js Documentation
追加

https://raw.githubusercontent.com/BabylonJS/Babylon.js/master/dist/materialsLibrary/babylon.skyMaterial.min.js
    <script type="text/javascript" src="scripts/babylon.skyMaterial.min.js"></script>
                        // Skybox
                        var skybox = BABYLON.Mesh.CreateBox('SkyBox', 1000, scene, false, BABYLON.Mesh.BACKSIDE);
                        skybox.material = new BABYLON.SkyMaterial('skybox', scene);
                        skybox.turbidity = 1;
                        skybox.luminance = 2;
                        skybox.material.inclination = 0.1;

Light

スキームがGIベイクなのでライト無しで作れるがPBRマテリアルの効果が出ない
3dsMAXやUnityのライトをBabylonに取り込む
追加

                        // 調整
                        scene.getLightByName("Directional Light").intensity = 1.0;

Pipeline

参考: Use the default rendering pipeline - Babylon.js Documentation
追加

                        // Pipeline
                        if (!parser.device.type && !intelGPU) {
                            var pipeline = new BABYLON.DefaultRenderingPipeline("default", true, scene, [camera]);
                            //var pipeline = new BABYLON.DefaultRenderingPipeline("default", false, scene, [camera]);

                            // FXAA
                            pipeline.fxaaEnabled = true;
                            pipeline.samples = 8;

                            // DOF
                            /*pipeline.depthOfFieldEnabled = true;
                            pipeline.focalLength = 50;
                            pipeline.fStop = 11;
                            pipeline.lensSize = 82;*/

                            // Bloom
                            pipeline.bloomEnabled = true;
                            pipeline.bloomThreshold = 0.9;
                            pipeline.bloomWeight = 0.2; // 0.1~0.3程度
                            pipeline.bloomKernel = 64;
                            pipeline.bloomScale = 0.5;
                            pipeline.imageProcessingEnabled = true;
                        };

Color Curve

参考: Color Correction - Babylon.js Documentation
追加

                        // Color Curve
                        if (!parser.device.type && !intelGPU) {
                            var postProcess = new BABYLON.ColorCorrectionPostProcess("color_correction", "../libs/table.png", 1.0, camera);
                        };

Image Process

参考: Use PostProcesses - Babylon.js Documentation > configuration 追加

                        // Image Processing
                            scene.imageProcessingConfiguration.applyByPostProcess = true;

                            // Tone Mapping
                            scene.imageProcessingConfiguration.toneMappingEnabled = true;
                            /*scene.imageProcessingConfiguration.toneMappingType = BABYLON.ImageProcessingConfiguration.TONEMAPPING_STANDARD;
                            scene.imageProcessingConfiguration.contrast = 1.2;
                            scene.imageProcessingConfiguration.exposure = 1.6;*/
                            scene.imageProcessingConfiguration.toneMappingType = BABYLON.ImageProcessingConfiguration.TONEMAPPING_ACES;
                            scene.imageProcessingConfiguration.contrast = 1.1;
                            scene.imageProcessingConfiguration.exposure = 1.5;

                            // Vignette
                            scene.imageProcessingConfiguration.vignetteEnabled = true;
                            scene.imageProcessingConfiguration.vignetteBlendMode = BABYLON.ImageProcessingConfiguration.VIGNETTEMODE_MULTIPLY;
                            scene.imageProcessingConfiguration.vignetteWeight = 1.0;
                            scene.imageProcessingConfiguration.vignetteStretch = 0;
                            scene.imageProcessingConfiguration.vignetteCameraFov = 0.5;

Pipeline 不採用

SSAO
追加

                            // SSAO
                            var ssao = new BABYLON.SSAORenderingPipeline("ssaopipeline", scene, 1.0);
                            ssao.fallOff = 0.000001;
                            ssao.area = 1;
                            ssao.radius = 0.00001;
                            ssao.totalStrength = 0.5; // 0.5~0.8程度
                            ssao.base = 0.5;
                            scene.postProcessRenderPipelineManager.attachCamerasToRenderPipeline("ssaopipeline", camera);

Motion Blur
制限

グリッチを隠すためにシーンは閉じられた空間にするか最低でもスカイボックスを用意する必要あり
部屋の場合、窓の外に何も無いとガラス面辺りにグリッチが出る

追加

                        // Motion Blur New
                        var mb = new BABYLON.MotionBlurPostProcess("mb", scene, 1.0, camera);
                        mb.motionStrength = 2;
                        mb.motionBlurSamples = 16;

Firefox エラー

Error: WebGL warning: drawElements: Texture level 0 would be read by TEXTURE_2D unit 0, but written by framebuffer attachment DEPTH_ATTACHMENT, which would be illegal feedback.

Edge エラー

WEBGL11163: drawElements: Feedback loop formed between Framebuffer and active Texture.

参考: Use the standard rendering pipeline - Babylon.js Documentation
参考: https://www.babylonjs-playground.com/#ZMAJZB#7

苦労するなら古いpipelineでいいかも

Standard pipelineは維持されなくなり、今後はDefault pipelineを使用する必要があるが、後方互換のために保持されてる

追加

                            // Motion Blur
                            if (parser.browser.name != "Edge" && parser.browser.name != "Firefox") {
                                // Motion Blur New
                                var mb = new BABYLON.MotionBlurPostProcess("mb", scene, 1.0, camera);
                                mb.motionStrength = 2;
                                mb.motionBlurSamples = 32;
                            } else {
                                // Motion Blur Old
                                var pipelineOld = new BABYLON.StandardRenderingPipeline("standard", scene, 1.0, null, [camera]);
                                pipelineOld.MotionBlurEnabled = true;
                                pipelineOld.motionStrength = 0.05;
                                pipelineOld.motionBlurSamples = 64.0;
                            }

Parserで調整

モバイルデバイスとパソコンで設定を分岐し調整してみます
設定

                        if (parser.device.type) {
                            // Optimize scene
                            // Memory Footprint
                        }

                        if (!parser.device.type) {
                            // FXAA
                            // Motion Blur
                            // SSAO
                        };

Draw Call

babylon04 babylon05 babylon06
パソコン 132 148 231
モバイルデバイス 44 48 77

単純にPipelineが3個でDraw Call3倍になってるように見える

GPUで調整

参考: WEBGL_debug_renderer_info - Web APIs | MDN
Intel内蔵グラフィックのパソコンはモバイルデバイスと見なす分岐を加えてみます
確認
https://dz.plala.jp/wiki_data/babylon04/check.html

GTX 1050 Ti ANGLE (NVIDIA GeForce GTX 1050 Ti Direct3D11 vs_5_0 ps_5_0)
Intel内蔵GPU ANGLE (Intel(R) HD Graphics 4000 Direct3D11 vs_5_0 ps_5_0)
iPhone XS Apple GPU

追加

    <!-- Adjust with GPU -->
    <canvas id="check" style="position: absolute; top: 0; left: 0; width: 0; height: 0;"></canvas>
        // Adjust with GPU
        var intelGPU;
        var gl = document.getElementById("check").getContext("experimental-webgl");
        var renderInfo = gl.getExtension("WEBGL_debug_renderer_info");
        if (renderInfo) {
            var renderer = gl.getParameter(renderInfo.UNMASKED_RENDERER_WEBGL);
            if (renderer.indexOf("Intel") !== -1) {
                intelGPU = true;
            } else {
                intelGPU = false;
            }
        }

設定

                        if (parser.device.type || intelGPU) {
                            // Optimize scene
                            // Memory Footprint
                        }

                        if (!parser.device.type && !intelGPU) {
                            // FXAA
                            // Motion Blur
                            // SSAO
                        };

Control Panel ※

The Car demo をBabylon Exporter index.html向けに改変

追加
LibrariesのjQueryとUAParserの下辺り

http://dz.plala.jp/wiki_data/libs/controlpanel.js
http://dz.plala.jp/wiki_data/libs/controlpanel.css
    <!-- ControlPanel -->
    <div id="controlPanel" style="opacity: 0">
        <div id="controlsZone">
            Camera<br>
            <select id="camerasList"></select><br>
            Control<br>
            <button class="buttonControlPanel pushed" id="universalCamera">Universal Camera</button>
            <button class="buttonControlPanel" id="deviceOrientationCamera">Virtual Reality Camera</button>
            <button class="buttonControlPanel" id="virtualJoysticksCamera">Virtual Joysticks Camera</button>
            <button class="buttonControlPanel" id="anaglyphCamera">Anaglyph Camera</button>
            <!--<button class="buttonControlPanel" id="flyCamera">Fly Camera</button>-->
            Post-process<br>
            <button class="buttonControlPanel" id="toggleFxaa">FXAA anti-aliasing</button>
            <button class="buttonControlPanel" id="toggleFsaa4">FSAA anti-aliasing</button>
            <button class="buttonControlPanel" id="toggleBandW">Black and white</button>
            <button class="buttonControlPanel" id="toggleSepia">Sepia</button>
            Other<br>
            <button class="buttonControlPanel" id="fullscreen">Fullscreen</button>
            <button class="buttonControlPanel" id="enableDebug">Inspector</button>
            © shogooda
        </div>
        <div id="clickableTag"><img
                src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACcAAAAnCAYAAACMo1E1AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABfWlDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjaldG/axMBGMbxzyWVCgbqkKFDkRuqKFSRdBFxaqFdVEITIQkOXi6XtJBLwuVKB1fBteAguvjrH3DSVdDVSVCE4t8giC5S4hA1Rejg8y5fHnh/8LwU7vTjdDx3mXSQZ1uba2Gj2QrnD5T+VBSPRzdqG3XH6sdHAXy42I/Tsf/TqU4yjglOoh+Pspwgx9W9fJQTvEQ53o46BO+wkjWaLYKvKLcbzRaFOZR7U15EOatvrVNYweneEW4f4Xg7Sylcw3La341/3xOglAxu1VDFkp5IKhUJVVxSETqvZtdIIlN106bQhkhbZkcskkt0hKoyQ107+hIXOGbXGSzpGhjKdITGhrpyeyKZBBrNVvhv5uPuamU6rbTGiS+TybezzD/gcH8y+flsMjl8TvGAN4NZ//ApV75T3J95y09YuMertzOv/ZDX91n8PIqy6O/XCquVaX4owotP1O9y/T2PHnOuy8LtX60laOocniWpAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAABYSURBVHja7NbBCQAhDARAc9hrakq1uRYOUc7H7DuPgYXV6O5xa55xceDg4ODgfsz8clRV29+4zAy1nkr4lcCZErWaEjhTYkpMiVrh4ODg4NbyAgAA//8DAODAGEWFN8aEAAAAAElFTkSuQmCC" />
        </div>
    </div>
    <script src="../libs/controlpanel.js"></script>
    <link href="../libs/controlpanel.css" rel="stylesheet" />
                        // ControlPanel
                        if (parser.device.type) {
                            $("#fullscreen, #enableDebug").remove();
                        } else {
                            $("#enableDebug").remove();
                        };
                        for (var index = 0; index < scene.cameras.length; index++) {
                            var camera = scene.cameras[index];
                            var option = new Option();
                            option.text = camera.name;
                            option.value = camera;
                            if (camera === scene.activeCamera) {
                                option.selected = true;
                            }
                            camerasList.appendChild(option);
                        };
                        setTimeout(function () {
                            $("#controlPanel").animate({ opacity: 1 }, { duration: 600, easing: 'swing' });
                        }, 300);

カメラを切り替えるとアンチエイリアシング効果が消えてる 確認 The Car demo
これかも https://doc.babylonjs.com/how_to/how_to_use_postprocessrenderpipeline
横画面設定が無い
iPhone safari > ホーム画面に追加 > 再表示でタッチイベントが効かない > (カメラを切り替えると正常)
↑Virtual Joysticks Cameraも変
Google Cardboardで見ると汚い
↑WebVRFreeCameraもある 調査
検証中

Reset Camera

追加

            <button class="buttonControlPanel" id="resetCameras">Reset Position</button>
                        // Reset Camera
                        var default_pos = scene.activeCamera.position.clone();
                        var default_rot = scene.activeCamera.rotation.clone();
                        document.getElementById("resetCameras").addEventListener("click", function () {
                            scene.activeCamera.position = default_pos;
                            scene.activeCamera.rotation = default_rot;
                            default_pos = scene.activeCamera.position.clone();
                            default_rot = scene.activeCamera.rotation.clone();
                            hideCameraPanel();
                            canvas.focus();
                        });

Screenshot ※

参考: Render a Scene to a PNG - Babylon.js Documentation
参考: ScreenshotTools - Babylon.js Documentation
参考: https://github.com/BabylonJS/Babylon.js/blob/e5101a113cfbca77ed29e541d112ccb14f516573/src/Tools/babylon.tools.ts
追加

            <button class="buttonControlPanel" id="screenShot">Screenshot</button>
    <!-- Screenshot -->
    <div id="thumbPanel" style="opacity: 0">
        <div id="thumbZone">
            <div class="titleTop">Screenshot</div>
            <div class="titleTip">Long-press to save</div>
            <div id="thumbnail">
                <img class="screenshot" src="../libs/noimage.png" />
                <img class="screenshot" src="../libs/noimage.png" />
                <img class="screenshot" src="../libs/noimage.png" />
                <img class="screenshot" src="../libs/noimage.png" />
                <img class="screenshot" src="../libs/noimage.png" />
                <img class="screenshot" src="../libs/noimage.png" />
                <img class="screenshot" src="../libs/noimage.png" />
                <img class="screenshot" src="../libs/noimage.png" />
                <img class="screenshot" src="../libs/noimage.png" />
                <img class="screenshot" src="../libs/noimage.png" />
            </div>
            <button class="buttonControlPanel" id="deleteAll" style="width: 199px;">Delete All</button>
        </div>
        <div class="thumbtag" id="thumbClickableTag">
            <img
                src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACcAAAAnCAYAAACMo1E1AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABfWlDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjaldG/axMBGMbxzyWVCgbqkKFDkRuqKFSRdBFxaqFdVEITIQkOXi6XtJBLwuVKB1fBteAguvjrH3DSVdDVSVCE4t8giC5S4hA1Rejg8y5fHnh/8LwU7vTjdDx3mXSQZ1uba2Gj2QrnD5T+VBSPRzdqG3XH6sdHAXy42I/Tsf/TqU4yjglOoh+Pspwgx9W9fJQTvEQ53o46BO+wkjWaLYKvKLcbzRaFOZR7U15EOatvrVNYweneEW4f4Xg7Sylcw3La341/3xOglAxu1VDFkp5IKhUJVVxSETqvZtdIIlN106bQhkhbZkcskkt0hKoyQ107+hIXOGbXGSzpGhjKdITGhrpyeyKZBBrNVvhv5uPuamU6rbTGiS+TybezzD/gcH8y+flsMjl8TvGAN4NZ//ApV75T3J95y09YuMertzOv/ZDX91n8PIqy6O/XCquVaX4owotP1O9y/T2PHnOuy8LtX60laOocniWpAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAJTSURBVHja7JhPZFxRFIe/N6IRZjVkFUKyjRIipSFKKWWYaNNGZB3upsx2CN2FbEM3Z11qRLUaSikRShfJ5lFZVxazCrMaIhGmm/M4nr439737QhbvMJw5c++539xz//zei8bjMQ/VGjxgq+FquBrO2FTZjiIyC7SBV8BjYMH8/Bf4A3wFvgNXWXmcc9XBiUgT6AFdoJnRbEE/HWAEHAIH6t9PWUVkBbgA9nLA0tbU9hfAyr3AiUgb+AXMm3AM7AKLQGQ+ixqPTdt57d/2HTPyub5EZBn4Dcxo6AbYAo4nrSMR6QBHwLSGroG1BDxvzTU819g3A3YJrGeB/Qf0WNtfamhG8zWrKGvPlPIOeAucF1k7zrlz7XdnStwLgtPjomtCm0XBUoCbJtQFZkNmbsdMf+xbygkljs0u3gmBe2H8/YoO/v2M/IXhnhr/pCK4k4z8/nC6S1v6dQQMqyBzzg3NTdHScQrP3CPj31Z8p99mjOMN55WgpHn98UbO9NtS2hIHmYi0zAkw1HFKbYgz4z+vaNaeZeQvDPfD+HsVwb03/s8QuE9mZy2rPgspaUfzJCfAx9JwzrkrFYqJHQGrJcFWtX9ih3kK2ffiPwAG6k8D/aKACtY3smmgecNUie6mDdVhqJA89RWNKlJPtV+i5zZ8JHvk+65E10vf6LpEDHzQjTMw8TngJfDOrLEEbNsKiDyxGRV5kSMiT4AvOnhRGwCv08dHkBJOJToDllRZ+D5JjbT90qRzLWjmMp5b32jp5lKzFAOfQ55bo/r9XA1Xw9Vw4fZvAF2Dq1zDq3xzAAAAAElFTkSuQmCC" />
        </div>
    </div>
                        // Screenshot
                        if (parser.device.type != "mobile") {
                            $(".titleTip").remove();
                        }
                        document.getElementById("screenShot").addEventListener("click", function () {
                            alwaysSelectAsActiveMesh = true;
                            BABYLON.Tools.CreateScreenshotUsingRenderTarget(engine, scene.activeCamera, { width: 1200, height: 800 }, function (base64) { exportImage(base64) }, "image/jpeg", 4, true, "Screenshot.jpg");
                            alwaysSelectAsActiveMesh = false;
                            hideCameraPanel();
                            if (thumbClosed) {
                                $("#thumbPanel").css({ opacity: 1 });
                            }
                            btnThumbPanel();
                            canvas.focus();
                        });
                        function exportImage(base64) {
                            var src = $(".screenshot:last").attr('src');
                            if (src != "../libs/noimage.png") {
                                URL.revokeObjectURL(src);
                            }
                            $(".screenshot:last").remove();
                            var bin = atob(base64.replace(/^.*,/, ''));
                            var buffer = new Uint8Array(bin.length);
                            for (var i = 0; i < bin.length; i++) {
                                buffer[i] = bin.charCodeAt(i);
                            }
                            try {
                                var blob = new Blob([buffer.buffer], {
                                    type: 'image/jpg'
                                });
                            } catch (e) {
                                return false;
                            }
                            var url = URL.createObjectURL(blob);
                            if (parser.device.type) {
                                $("#thumbnail").prepend("<img class='screenshot' src='" + url + "'/>");
                            } else {
                                $("#thumbnail").prepend("<a href='" + url + "' download='Screenshot.png'><img class='screenshot' src='" + url + "'/></a>");
                            }
                        };
                        $("#deleteAll").on('click', function () {
                            hideThumbPanel();
                            setTimeout(function () {
                                for (var i = 0; i < 10; i++) {
                                    var src = $(".screenshot:last").attr('src');
                                    if (src != "../libs/noimage.png") {
                                        URL.revokeObjectURL(src);
                                    }
                                    $(".screenshot:last").remove();
                                }
                                for (var i = 0; i < 10; i++) {
                                    $("#thumbnail").append("<img class='screenshot' src='../libs/noimage.png' />");
                                }
                            }, 400);
                        });
                        var thumbPanel = document.getElementById("thumbPanel");
                        var thumbClosed = true;
                        document.getElementById("thumbClickableTag").addEventListener("click", function () {
                            if (thumbClosed) {
                                thumbClosed = false;
                                thumbPanel.style.webkitTransform = "translateX(0px)";
                                thumbPanel.style.transform = "translateX(0px)";
                            } else {
                                thumbClosed = true;
                                thumbPanel.style.webkitTransform = "translateX(240px)";
                                thumbPanel.style.transform = "translateX(240px)";
                            }
                        });
                        var hideThumbPanel = function () {
                            thumbClosed = true;
                            thumbPanel.style.webkitTransform = "translateX(279px)";
                            thumbPanel.style.transform = "translateX(279px)";
                            canvas.focus();
                        };
                        var openThumbPanel = function () {
                            thumbClosed = false;
                            thumbPanel.style.webkitTransform = "translateX(0px)";
                            thumbPanel.style.transform = "translateX(0px)";
                        };
                        var btnThumbPanel = function () {
                            thumbClosed = true;
                            thumbPanel.style.webkitTransform = "translateX(240px)";
                            thumbPanel.style.transform = "translateX(240px)";
                        };

Tone Mapping・パーティクル・モノトーン・セピアが写ってない 確認 The Car demo
これかも https://doc.babylonjs.com/how_to/how_to_use_postprocessrenderpipeline
検証中

Mirror ※

参考: Obtain Reflections and Refractions - Babylon.js Documentation
追加

                        // Mirror
                        var mirrorObject = [
                            { obj: "NoGI_window_glass01", alpha: 0.4, level: 1.0 },
                            { obj: "NoGI_window_glass02", alpha: 0.4, level: 0.8 },
                            { obj: "NoGI_window_glass03", alpha: 0.4, level: 0.8 },
                            { obj: "NoGI_window_glass04", alpha: 0.2, level: 0.8 }
                        ]
                        var targetObject = [
                            "armchair1",
                            "armchair2",
                            "background2",
                            "bed",
                            "bed_cloth1",
                            "bed_cloth2",
                            "carpet",
                            "ceiling",
                            "curtain",
                            "door_03",
                            "fireplace",
                            "fireplace_deck",
                            "lamp_01",
                            "lamp_02",
                            "leg",
                            "painting",
                            "pillow1",
                            "pillow2",
                            "table",
                            "walls",
                            "window_frame"
                        ];
                        var myRenderList = [];
                        for (var j = 0; j < targetObject.length; j++) {
                            myRenderList.push(scene.getMeshByName(targetObject[j]));
                        }
                        if (!parser.device.type && !intelGPU && engine.webGLVersion == 2) {
                            for (var i = 0; i < mirrorObject.length; i++) {
                                var glass = scene.getMeshByName(mirrorObject[i].obj);
                                glass.computeWorldMatrix(true);
                                var glass_worldMatrix = glass.getWorldMatrix();
                                var glass_vertexData = glass.getVerticesData("normal");
                                var glassNormal = new BABYLON.Vector3(glass_vertexData[0], glass_vertexData[1], glass_vertexData[2]);
                                glassNormal = new BABYLON.Vector3.TransformNormal(glassNormal, glass_worldMatrix)
                                var reflector = new BABYLON.Plane.FromPositionAndNormal(glass.position, glassNormal.scale(-1));
                                var mirrorMaterial = new BABYLON.StandardMaterial("mirror", scene);
                                mirrorMaterial.reflectionTexture = new BABYLON.MirrorTexture("mirror", 1024, scene, true);
                                mirrorMaterial.reflectionTexture.mirrorPlane = reflector;
                                mirrorMaterial.reflectionTexture.renderList = myRenderList;
                                mirrorMaterial.reflectionTexture.level = mirrorObject[i].level;
                                glass.material = mirrorMaterial;
                                //glass.material.alphaMode = BABYLON.Engine.ALPHA_COMBINE;
                                glass.material.alpha = mirrorObject[i].alpha;
                            };
                        }

renderList = scene.meshesにするとエラー
targetObjectは反射面で目立つもの
iPhone XSでエラー
動作が重い Draw_Callが対処方法かも
ガラス面全てをmergeダメかも > 法線方向が同じものでデタッチ
Chrome 警告

GL_INVALID_OPERATION: It is undefined behaviour to have a used but unbound uniform buffer.

検証中

FOV ※

参考: https://doc.babylonjs.com/playground/?code=fov
参考: https://playground.babylonjs.com/#6FHKHC#17
追加

<button class="buttonControlPanel" id="resetCameras">Reset Position and Zoom</button>
                        var default_fov = 1.2;
                        document.getElementById("resetCameras").addEventListener("click", function () {
                            camera.fov = default_fov;
                        });
                        // FOV
                        //camera.fov = 1.2;
                        if (parser.device.type == "mobile") {
                            var orientation = window.orientation;
                            if (orientation === 0) {
                                // 縦画面
                                camera.fov = 1.4;
                            } else {
                                // 横画面
                                camera.fov = 0.8;
                            }
                            default_fov = camera.fov;
                        }
                        window.addEventListener("orientationchange", function () {
                            if (parser.device.type == "mobile") {
                                var orientation = window.orientation;
                                if (orientation === 0) {
                                    // 縦画面
                                    camera.fov = 1.4;
                                } else {
                                    // 横画面
                                    camera.fov = 0.8;
                                }
                            }
                            default_fov = camera.fov;
                        });
                        // ZOOM
                        scene.onPointerObservable.add((pointerInfo) => {
                            var event = pointerInfo.event;
                            var delta = 0;
                            if (event.deltaY) {
                                delta = event.deltaY;
                            }
                            else if (event.detail) {
                                delta = -event.detail;
                            }
                            if (delta) {
                                if (delta < 0)
                                    camera.fov += 0.04;
                                else
                                    camera.fov -= 0.04;
                            }
                        }, BABYLON.PointerEventTypes.POINTERWHEEL);

カメラ変えると動かない
検証中

iOS13対応

参考: iOS 12.2で半ば終わったWebVRとWebARがiOS 13でどうなったか - Qiita
追加

                        // iOS
                        document.getElementById("deviceOrientationCamera").addEventListener("click", function () {
                            if (
                                DeviceMotionEvent &&
                                DeviceMotionEvent.requestPermission &&
                                typeof DeviceMotionEvent.requestPermission === 'function'
                            ) {
                                DeviceMotionEvent.requestPermission();
                            }
                            if (
                                DeviceOrientationEvent &&
                                DeviceOrientationEvent.requestPermission &&
                                typeof DeviceOrientationEvent.requestPermission === 'function'
                            ) {
                                DeviceOrientationEvent.requestPermission();
                            }
                        });

iOS12.2を含める場合
参考: IOS 13 deviceorientation

ノッチ対応

iPhoneノッチ対応
追加 viewport-fit=cover

    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, shrink-to-fit=no, user-scalable=no, viewport-fit=cover">

PWA対応

Loading Anim

シーン切り替え

WebVR

参考: Use the WebVR Camera - Babylon.js Documentation
参考: Use the WebVR experience helper - Babylon.js Documentation

WebGL機能追加 適宜

3D Sound

参考: Play Sounds and Music - Babylon.js Documentation
追加

                        // 3D Sound
                        var music = new BABYLON.Sound("music", "fireplace.mp3",
                            scene, null, {
                            loop: true,
                            autoplay: true,
                            spatialSound: true,
                            distanceModel: "linear",
                            maxDistance: 5
                        });
                        music.setPosition(new BABYLON.Vector3(1.76, 0.47, 0));

カスタマイズ
ドメイン間移動の?Chromeのstatus判別が変
参考: https://doc.babylonjs.com/api/classes/babylon.audioengine
参考: https://doc.babylonjs.com/how_to/observables#add-an-observer
ドメイン間移動の?Observableが発火しない
参考: https://developers.google.com/web/updates/2017/09/autoplay-policy-changes
autoplay: falseで対処

            <button class="buttonControlPanel" id="3dSound">3D Sound</button>
                        // 3D Sound
                        if (BABYLON.Engine.audioEngine.canUseWebAudio) {
                            var music = new BABYLON.Sound("music", "fireplace.mp3", scene, null,
                                {
                                    loop: true,
                                    autoplay: false,
                                    spatialSound: true,
                                    distanceModel: "linear",
                                    maxDistance: 5
                                }
                            );
                            var nowPlaying = false;
                            document.getElementById("3dSound").addEventListener("click", function () {
                                if (!nowPlaying) {
                                    scene.audioEnabled = true;
                                    music.play();
                                    nowPlaying = true;
                                    document.getElementById("3dSound").className = "buttonControlPanel pushed";
                                } else {
                                    scene.audioEnabled = false;
                                    music.stop();
                                    nowPlaying = false;
                                    document.getElementById("3dSound").className = "buttonControlPanel";
                                }
                            });
                        } else {
                            $("#3dSound").remove();
                        };

Rain

参考: Use the Particle Helper - Babylon.js Documentation

Snow

参考: Particles - Babylon.js Documentation
scenesディレクトリに設置

https://dz.plala.jp/wiki_data/babylon04/scenes/snow.png

ボックスエミッタ
追加

                        // Snow
                        var particleSystem = new BABYLON.ParticleSystem("particles", 4000, scene);
                        particleSystem.particleTexture = new BABYLON.Texture("scenes/snow.png", scene);
                        particleSystem.emitter = BABYLON.Vector3.Zero();
                        particleSystem.worldOffset = new BABYLON.Vector3(2.5, 3, -4);
                        particleSystem.color1 = new BABYLON.Color4(1.0, 1.0, 1.0, 1.0);
                        particleSystem.colorDead = new BABYLON.Color4(1.0, 1.0, 1.0, 0.0);
                        particleSystem.minSize = 0.015;
                        particleSystem.maxSize = 0.025;
                        particleSystem.minLifeTime = 2.0;
                        particleSystem.maxLifeTime = 4.0;
                        particleSystem.emitRate = 4000;
                        particleSystem.createBoxEmitter(
                            new BABYLON.Vector3(0, -2, 0),
                            new BABYLON.Vector3(0, 0, -0.5),
                            new BABYLON.Vector3(0, 0, 0.5),
                            new BABYLON.Vector3(2, 2, 10)
                        );
                        particleSystem.minEmitPower = 1.2;
                        particleSystem.maxEmitPower = 1.5;
                        particleSystem.updateSpeed = 0.004;
                        particleSystem.preWarmCycles = 100;
                        particleSystem.preWarmStepOffset = 5;
                        particleSystem.start();

Fire

参考: Fire - Babylon.js Documentation
scenesディレクトリに設置

https://dz.plala.jp/wiki_data/babylon04/scenes/fire_diffuse.png
https://dz.plala.jp/wiki_data/babylon04/scenes/fire_distortion.png
https://dz.plala.jp/wiki_data/babylon04/scenes/fire_opacity.png

scriptsディレクトリに設置

https://raw.githubusercontent.com/BabylonJS/Babylon.js/master/dist/preview%20release/materialsLibrary/babylon.fireMaterial.js

追加

<script type="text/javascript" src="scripts/babylon.fireMaterial.js"></script>
                        // Fire
                        var fire = new BABYLON.FireMaterial("fire", scene);
                        fire.diffuseTexture = new BABYLON.Texture("scenes/fire_diffuse.png", scene);
                        fire.distortionTexture = new BABYLON.Texture("scenes/fire_distortion.png", scene);
                        fire.opacityTexture = new BABYLON.Texture("scenes/fire_opacity.png", scene);
                        fire.speed = 3.0;
                        var plane = BABYLON.MeshBuilder.CreatePlane("fireplane", { width: 0.45, height: 0.45 }, scene);
                        plane.position = new BABYLON.Vector3(1.77, 0.44, 0.03);
                        plane.billboardMode = BABYLON.Mesh.BILLBOARDMODE_Y;
                        plane.material = fire;

炎から漏れる光
参考: Animations - Babylon.js Documentation
参考: Sequence Animations - Babylon.js Documentation

確認
Unityのポイントライトは"Point Light"
Javascriptでは気持ち悪い

for (var i = 0; i < scene.lights.length; i++) {
    console.log(scene.lights[i].name);
}
Point Light (1)
Point Light (2)
Directional Light
Point Light
Ambient Light

Unityと同名を使用してる
追加

                        // Fire Light
                        var lightnum = 0;
                        for (var i = 0; i < scene.lights.length; i++) {
                            if (scene.lights[i].name == "Point Light") {
                                lightnum = i;
                            }
                        }
                         BABYLON.Animation.AllowMatricesInterpolation = true;
                        var lightDimmer = new BABYLON.Animation(
                            "dimmer",
                            "intensity",
                            60,
                            BABYLON.Animation.ANIMATIONTYPE_FLOAT,
                            BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE
                        );
                        var light_keys = [
                            {
                                frame: 0,
                                value: 0
                            },
                            {
                                frame: 50,
                                value: 0
                            },
                            {
                                frame: 100,
                                value: 1.2
                            },
                            {
                                frame: 150,
                                value: 0
                            },
                            {
                                frame: 200,
                                value: 0
                            }
                        ];
                        lightDimmer.setKeys(light_keys);
                        scene.lights[lightnum].animations = [];
                        scene.lights[lightnum].animations.push(lightDimmer);
                        scene.beginAnimation(scene.lights[lightnum], 0, 200, true);

Fog

参考: Use particle to simulate volumetric fog
追加

                        // Fog
                        var fountain = BABYLON.Mesh.CreateBox("foutain", .01, scene);
                        fountain.visibility = 0;
                        var particleSystem2;
                        var useGPUVersion = false;
                        var fogTexture = new BABYLON.Texture("https://raw.githubusercontent.com/aWeirdo/Babylon.js/master/smoke_15.png", scene);
                        if (particleSystem2) {
                            particleSystem2.dispose();
                        }
                        if (useGPUVersion && BABYLON.GPUParticleSystem.IsSupported) {
                            particleSystem2 = new BABYLON.GPUParticleSystem("particles", { capacity: 2500 }, scene);
                            particleSystem2.activeParticleCount = 1500;
                            particleSystem2.manualEmitCount = particleSystem2.activeParticleCount;
                            particleSystem2.minEmitBox = new BABYLON.Vector3(-20, 2, -20); // Starting all from
                            particleSystem2.maxEmitBox = new BABYLON.Vector3(20, 2, 20); // To..
                        } else {
                            particleSystem2 = new BABYLON.ParticleSystem("particles", 1250, scene);
                            particleSystem2.manualEmitCount = particleSystem2.getCapacity();
                            particleSystem2.minEmitBox = new BABYLON.Vector3(-20, 2, -20); // Starting all from
                            particleSystem2.maxEmitBox = new BABYLON.Vector3(20, 2, 20); // To...
                        }
                        particleSystem2.particleTexture = fogTexture.clone();
                        particleSystem2.emitter = fountain;
                        particleSystem2.worldOffset = new BABYLON.Vector3(5, 3, 0);
                        particleSystem.color1 = new BABYLON.Color4(0.8, 0.8, 0.8, 0.01);
                        particleSystem.color2 = new BABYLON.Color4(.95, .95, .95, 0.03);
                        particleSystem.colorDead = new BABYLON.Color4(0.9, 0.9, 0.9, 0.02);
                        particleSystem2.minSize = 1;
                        particleSystem2.maxSize = 3;
                        particleSystem2.minLifeTime = Number.MAX_SAFE_INTEGER;
                        particleSystem2.emitRate = 1250;
                        particleSystem2.blendMode = BABYLON.ParticleSystem.BLENDMODE_STANDARD;
                        particleSystem2.gravity = new BABYLON.Vector3(0, 0, 0);
                        particleSystem2.direction1 = new BABYLON.Vector3(0, 0, 0);
                        particleSystem2.direction2 = new BABYLON.Vector3(0, 0, 0);
                        particleSystem2.minAngularSpeed = -2;
                        particleSystem2.maxAngularSpeed = 2;
                        particleSystem2.minEmitPower = .5;
                        particleSystem2.maxEmitPower = 1;
                        particleSystem2.updateSpeed = 0.005;
                        particleSystem2.start();

Clock

参考: I NEED HELP IN Clock time Function in babylon js 3d configurator
確認
Javascriptはscene.meshesで配列取得
Unityはsceneにあたる親階層が無い
Unityの親階層に部屋と時計を置きJavascriptはscene.meshesで取得できるの?

親子孫階層と他のオブジェクト階層もscene.meshesの配列に入る
回転軸をUnityの空Objectに設定しても反応しない 回転させるGameObjectの回転軸に原点を移動させ対応(3dsMax操作)
親階層の空ObjectのScale変更はBabylon.jsにも引き継ぐ
座標系はUnity=Babylon.jsに見える 都合いい
arrayOfMeshes[i].freezeWorldMatrix();をコメントアウトしないと動かない
追加

                        // Clock
                        var snum = 0, mnum = 0, hnum = 0;
                        for (var i = 0; i < scene.meshes.length; i++) {
                            if (scene.meshes[i].name == "clock_s") {
                                snum = i;
                            }
                            if (scene.meshes[i].name == "clock_m") {
                                mnum = i;
                            }
                            if (scene.meshes[i].name == "clock_h") {
                                hnum = i;
                            }
                        };
                        scene.registerBeforeRender(function () {
                            var date = new Date();
                            var hour = date.getHours() % 12;
                            var minute = date.getMinutes();
                            var second = date.getSeconds();
                            scene.meshes[snum].rotation.z = (second / 60) * 360 * Math.PI / 180;
                            scene.meshes[mnum].rotation.z = (minute / 60) * 360 * Math.PI / 180;
                            scene.meshes[hnum].rotation.z = (hour / 12) * 360 * Math.PI / 180 + ((minute / 60) * 360 * Math.PI / 180) / 10;
                        });

ローカルファイル

参考: FilesInput - Babylon.js Documentation

Video

参考: Add Video Texture - Babylon.js Documentation

材質変更

参考: Use Actions - Babylon.js Documentation

ナビマップ

参考: Extensions/canvas2D at master · BabylonJS/Extensions · GitHub
古いかも

家具追加・移動

デモモード

参考: Babylon.js - Sponza demo
オートプレイモード

リトルプラネット

レンズフレア

参考: Use Lens Flares - Babylon.js Documentation

ボリュームライト

参考: Use the Volumetric LightScattering post-process - Babylon.js Documentation

風とカーテン

ラグのファー

参考: Fur - Babylon.js Documentation
または日向ぼっこ中、寝てるネコ

鳥・チョウチョ

参考: Crowd agents - Babylon.js Documentation

車・自転車

人物・群衆

更新履歴

  • 2019.08.03 公開