WebXR Depth Sensing Moduleについて調査
WebXR Depth APIについてのページ
いつの間にかWebXR Incubationがdefaultの状態でも実行できるようになっていた
しかもCPUもGPUも使える。そうだったんだなぁ
Chromium90~ってことは前からすでに実行できていたのかな?
W3Cのspecificationはこちら
こっちのほうがAPIの使い方など詳細に書いてあるイメージ
dataフォーマット
ushortかfloat32か選べるらしい
ushort(uint16)の場合はGPUの場合Alphaチャンネルの値
float32だとrチャネルに値が書き込まれているらしい
とくにGPUでの処理に興味がある
WebGLBindingsからWebGLTextureを取ってくる仕様はraw camera accessでも見ましたね
久しぶりに再開する
いったん"depth-sensing"をrequiredFeaturesに入れて、scene.createDefaultXRExperience
してみた
これにのっとって
すると、やはりdepthのセンシングをどうやるのか、どのフォーマットをサポートするのかを渡さないといけないらしい
ごり押しでcreateDefaultXRExperience({})の中のuiOptionsに
depthSensingの情報を入れてみたが、うまくいかないみたい
理由はEnterXRの時点で、optionの情報がoptionalFeaturesとrequiredFeaturesだけに削られているからみたいだ
つまりcreatedefaultXRExperienceから有効化するのは無理っぽい
enterXRを自分で呼び出す方法でも上記の問題が発生するのと、なぜかuserのアクティベーションが必要だよというエラーメッセージが表示される
webxrFeatureManager.enableFeature()を使うことで、オプションと一緒にfeatureを有効化できる気がする
ただ、ここで有効化できるのはfeatureManagerにaddFeatureされたものであり、
featureはIWebXRFeatureをインターフェースを実装しているクラスである必要がある
つまりdepth sensingなどというfeatureはまだ実装されていないためenableできない
なのでWebXRDepthSensingというfeatureを実装するおkとにした
本当にできるのかという疑問は残るが、実装さえすれば有効化できそうである
depthSensingディクショナリを追加してくれっていうエラーが出るということは、すくなくともdepthSensing系の実装が考慮されているということなので、これさえ乗り越えて有効化しさえすればなんとか動かせるのでは
そういえば試しにこんな感じで書いてみる
するとこうなる
undefinedではない
Depth Sensingが有効であれば使えるなこれは
ちなみにWebXR Incubationがdefaultでも同じ表記になったので、これは仏のChrome for ancroidでも使えそうな気配
5時間くらい粘ったらBabylon.jsでWebXR Depth Sensing Moduleを有効にできた
次のコードで実現可能、だが
ここまでの流れを見ればこれだけではできなきことはもうわかっている
webxrEnterExitUI.js
の_enterXRWithButtonIndexのコードを直接編集している
ここはもともと、最後のoptionsは
{
requiredFeature:this.options.requiredFeatures,
optinalFeatures:this.options.optionalFeatres
}
といった具合になぜか絞り込みが行われていて、そのせいでdepthSensing
オプションが省かれてしまっていたため、うまくdepth Sensingが有効にならなかったということだ
そういえば、自分の環境では
- cpu-optimized
- luminance-alpha
しか動作しなかった
GPUやfloat32ではdepthUsageなどがエラーになるという感じ
あれ、GPU前に動作しなかったっけなぁと思ってGoogleが出してるProposalのサンプル見て見たら
GPUとか言っていながらcpu-optimized使ってたわ()
これ、現状はcreateDefaultXRExperienceを使うから起きていると思うので、
XR系の初期化処理を自分で何とかすれば回避できるかもしれない
現行のBabylon.jsではcreateDefaultXRExperienceを使うとdepth-sensingが使えないことが分かった
ということは逆にcreate~~でやっている処理の最後に呼び出されているenterXRAsyncを呼び出せばdepth-sensingを起動した状態でWebXRモードを起動できるよねという結論になって実装したコードが以下
const xrHelper = await WebXRExperienceHelper.CreateAsync(this.scene);
enterExitButton.onPointerDownObservable.add(() => {
const handler = async (): Promise<void> => {
// user activationのために待機
await new Promise((resolve) => setTimeout(resolve, 100));
await xrHelper.enterXRAsync('immersive-ar', 'unbounded', undefined, {
requiredFeatures: ['depth-sensing'],
depthSensing: {
usagePreference: ['cpu-optimized'],
dataFormatPreference: ['luminance-alpha'],
},
} as any);
};
handler().catch(null);
enterExitButton.isVisible = false;
});
xrHelper.sessionManager.onXRSessionEnded.add(() => {
enterExitButton.isVisible = true;
});
enterExitButtonはBabylonjs のGUIボタンであり、それを押すとXRモードに移行するんだけど、
WebXRモードの起動みたいな、全画面表示をするとかそういう
ユーザの操作性に関わる処理にはuser activationなるものが必要らしい
これはユーザが少なくとも1回以上は画面にタッチしたりインタラクションをした状態でないと
全画面モードに移行はできないよということらしい
これをクリアするために、ユーザのタッチイベントによってuser activationをさせてからWebXRモードに移行する必要があるため、待機してる
詳しくは以下
サンプルに載っているコードを参考にすれば、距離の測定はすぐにできた
取り急ぎ画面中央部分のdepth推定を反映するデモを作成
やっぱりdepth推定だったらdepth画像表示したいよね......という欲があった
色々試行錯誤したので時間がかかったけど、なんとかリアルタイムでdepth画像を表示することに成功!!!
こういう画が欲しかったので満足です
あとはドキュメントとコードを整えてGithub公開したいですね
WebXRでdepth推定によるオクルージョンとか実現出来たらかなりアツいよねぇ~という感じではあるんだけど、
個人的に未来では、「オクルージョンとか普通でしょ?だってARオブジェクトが常に手前に表示されたらおかしいじゃん」みたいな世界観になってほしいね
そういう未来を作れるように一歩一歩着実に歩んでいかねば
ツイーヨ
GitHubも公開できたので、クローズ