ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Babylon.js+WebXR(一)WebXR介绍

2021-07-09 16:34:44  阅读:392  来源: 互联网

标签:WebVR Babylon scene WebXR var new js BABYLON


WebXR

前言

W3C出了一套包括但不限于WebVR/WebAR的规范。这个W3C组织名叫Immersive Web,即沉浸式网络,非常确切的概括了WebXR想要实现的效果。组织的目标是通过API将高性能虚拟现实(VR)和增强现实(AR)(统称为XR)引入开放式Web,以便与Web中的传感器和XR设备进行交互。

当前状态

WebXR W3C提案目前处于草案阶段。 然而,它已经在 Chrome 中实现了(查看 caniuse.com 可了解其他浏览器的WebXR实现情况)。 从Chrome的79版本开始,WebVR已被弃用,默认情况下启用WebXR。 早期的Chrome浏览器版本在配置选项里有WebXR选项,可选择打开。 其目标之一是弃用WebVR和其他AR实现,并提供单一的VR和AR API。

由于WebXR API还在不断变化和更新中,所以babylon.js很难跟上其功能和特性的变化。最新的chrome浏览器金丝雀版本(canary)是目前XR功能最完整的浏览器,而且谷歌也在不断持续的更新WebXR新功能。 这是我们引入功能管理器(Features Manager)的主要原因,它允许Babylon.js通过内部版本控制功能去实现WebXR最新版本的官方功能,而不会破坏向后兼容性。

请注意,大多数时候当我们说WebXR时,我们实际上是指VR沉浸式模式(VR immersive mode)下的WebXR。 这是目前WebXR最常用的模式。

设备和浏览器支持

PC

所有微软的混合现实设备使用的windows系统的Chrome 79版本浏览器都官方支持WebXR。 非官方的,WebXR 与 oculus SDK(Rift、Rift S 和 Quest with Link)配合良好。 在撰写本文时,对Oculus的官方支持仍未公布。

手机和Quest

Google Daydream设备使用Chrome浏览器可支持WebXR。

Android 的 Chrome 浏览器(Stable 和 Canary版本)上的 WebXR AR 功能可以在 chrome://flags 打开相应的功能配置标志后启用,包括平面检测、命中测试和锚点等 AR 功能。 请注意,AR功能的架构在不断变化,因此预计不同版本的结果会有所不同。

Oculus Quest设备在最新的oculus浏览器中支持 WebXR(在 VR 模式下)。 Babylon.js的规范实现在quest设备中运行良好。

目前没有正式的 iOS/iPhone 支持计划。 Mozilla 已经构建了一个在IOS系统能够运行的WebXR浏览器(WebXR iOS Viewer),这是一个(非常)受限的面向 AR 的浏览器。

Polyfill

对于支持 WebVR 但不支持 WebXR 的旧浏览器,您可以使用 WebXR Polyfill,它是使用WebXR API接口去实现了WebVR的功能 。 某些功能将无法运行(或将直接返回而不进行任何操作),但基本功能运行OK。

Babylon.js不打算将 polyfill 集成到框架本身或Playground中。 我们鼓励开发人员向那些不使用支持 WebXR 的浏览器的用户提供 polyfill。

要在 Playground 中使用 polyfill,请将以下内容添加到您的 Playground中(在 'createScene'函数之前):

1 const xrPolyfillPromise = new Promise((resolve) => {
2   if (navigator.xr) {
3     return resolve();
4   }
5   define("polyfill", ["https://cdn.jsdelivr.net/npm/webxr-polyfill@latest/build/webxr-polyfill.js"], (polyfill) => {
6     new polyfill();
7     resolve();
8   });
9 });

 然后,确保在初始化 WebXR 之前等待该函数执行完成:

const xrPolyfillPromise = new Promise((resolve) => {
  if (navigator.xr) {
    return resolve();
  }
  define("polyfill", ["https://cdn.jsdelivr.net/npm/webxr-polyfill@latest/build/webxr-polyfill.js"], (polyfill) => {
    new polyfill();
    resolve();
  });
});

var createScene = async function () {
  // wait for the polyfill to kick in
  await xrPolyfillPromise;
  console.log(navigator.xr); // should be there!
  console.log(await BABYLON.WebXRSessionManager.IsSessionSupportedAsync("immersive-vr")); // should be true
  // create your scene
  var scene = new BABYLON.Scene(engine);
  var camera = new BABYLON.DeviceOrientationCamera("DevOr_camera", new BABYLON.Vector3(-30, -30, -30), scene);
  camera.setTarget(BABYLON.Vector3.Zero());
  camera.attachControl(canvas, true);
  var light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 0, 0), scene);
  scale = 100;
  // initialize XR
  var xr = await scene.createDefaultXRExperienceAsync();

  return scene;
};

 如果在使用 polyfill 时遇到低分辨率,需要将画布大小调整为更高的分辨率。 这是WebVR的限制(需要调整画布大小),我们集成的WebXR没有这个限制 。

WebXR模拟器

如果您正在开发并且不想经常在真实设备上进行测试,请使用 mozilla 的 WebXR 模拟器,它适用于 chrome 和 firefox浏览器。 我们支持它并在开发过程中实际使用了它。 强烈推荐!

快速入门

最简单的入门方法是使用支持 WebXR 的浏览器并将一行代码添加到您的场景中:

const xr = scene.createDefaultXRExperienceAsync();

这将在 VR 沉浸式模式下(VR immersive mode)启用 WebXR,包括会话初始化、输入源、相机、隐形传态和场景交互。 全部使用我们的 WebXR 默认体验助手(WebXR Default Experience Helper)。

请注意, xr 变量是一个 Promise。 使用 async/await 模式会更简单、更直观。 定义地板网格(floor meshes)也很有意义,这样我们就可以定义我们的地面并在上面移动。 这是 XR 中的一个球体:

var createScene = async function () {
  var scene = new BABYLON.Scene(engine);
  var camera = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3(0, 5, -10), scene);
  camera.setTarget(BABYLON.Vector3.Zero());
  camera.attachControl(canvas, true);
  var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);
  light.intensity = 0.7;
  var sphere = BABYLON.Mesh.CreateSphere("sphere1", 16, 2, scene);
  sphere.position.y = 1;

  const env = scene.createDefaultEnvironment();

  // here we add XR support
  const xr = await scene.createDefaultXRExperienceAsync({
    floorMeshes: [env.ground],
  });

  return scene;
};

 Demo链接

这样就可以了,是不是很简单?

请务必阅读有关WebXR Experience Helper的更多信息以获取更多提示和技巧,并查看我们的演示和示例

从WebVR迁移到WebXR

 WebVR 已被弃用,并且将很快在大多数浏览器中结束其生命周期。 强烈建议将所有 WebVR 实现移植到 WebXR。

从VR Experience helper迁移

如果您使用了我们的 VR 体验助手(WebVR experience helper),请移除 VR 初始化程序并添加 XR 体验助手(WebXR experience helper)。 所以代码由:

var scene = new BABYLON.Scene(engine);
var vrHelper = scene.createDefaultVRExperience();

转变成:

var scene = new BABYLON.Scene(engine);
var xrHelper = scene.createDefaultXRExperienceAsync();

默认情况下,WebXR助手具有完整的控制器支持,包括与场景网格、指针事件等的交互。 阅读有关WebXR体验助手的更多信息。

迁移控制器支持

由于 WebXR 控制器不再被视为游戏手柄,因此架构略有不同。

添加的最重要的功能是对控制器的完整指针事件支持。 控制器支持所有指针事件,因此您可以使用指针交互(Pointer interactions),就像在场景中控制鼠标交互一样。

同样需要注意的是,现在可以查询控制器具有哪些功能及其相关的操作。

以下是 VR 控制器最常用的功能,以及如何让它们在 XR 中工作:

 1 // On new controller attached:
 2 
 3 // WebVR:
 4 webvrCamera.onControllersAttached = (vrController) => {
 5   // fun with the new controller, which is a gamepad!
 6 };
 7 
 8 // WebXR:
 9 const webXRInput = xr.input; // if using the experience helper, otherwise, an instance of WebXRInput
10 input.onControllerAddedObservable.add((xrController /* WebXRInputSource instance */) => {
11   // more fun with the new controller, since we are in XR!
12   inputSource.onMotionControllerInitObservable.add((motionController) => {
13     // get the motionController, which is similar to but NOT a gamepad:
14   });
15   // xr supports all types of inputs, so some won't have a motion controller
16   if (!xrController.gamepad) {
17     // using touch, hands, gaze, something else?
18   }
19 });
20 
21 // From this point we assume we have two variables: vrController and xrController.
22 // We also assume motionController is present!
23 
24 // main button
25 
26 // WebVR:
27 controller.onMainButtonStateChangedObservable.add((newState /* ExtendedGamepadButton */) => {
28   // is the button pressed?
29   if (newState.pressed) {
30     // Do something
31   }
32 });
33 
34 // WebXR:
35 // get the main component (decided by the controller's vendor!)
36 const mainComponent = xrController.motionController.getMainComponent();
37 // or get the trigger component, if present:
38 const mainTrigger = xrController.motionController.getComponent(WebXRControllerComponent.TRIGGER);
39 mainComponent.onButtonStateChanged.add((component /* WebXRControllerComponent */) => {
40   // check for changes:
41   // pressed changed?
42   if (component.changes.pressed) {
43     // is it pressed?
44     if (component.changes.pressed.current === true) {
45       // pressed
46     }
47     // or a different way:
48     if (component.pressed) {
49       // component is pressed.
50     }
51   }
52 });
53 
54 // thumbpad / touchpad
55 
56 // in WebVR - you had to check what controller is being used, but in general this would work:
57 vrController.onPadValuesChangedObservable.add(function (stateObject) {
58   console.log(stateObject); // {x: 0.1, y: -0.3}
59 });
60 
61 // in webXR you can check if it is present and work accordingly:
62 const thumbstick = xrController.motionController.getComponent(WebXRControllerComponent.THUMBSTICK);
63 if (thumbstick) {
64   // Huzza! we have a thumbstick:
65   thumbstick.onButtonStateChanged; // will trigger when the thumbstick is PRESSED or touched!
66 
67   thumbstick.onAxisValueChanged; // will trigger when axes of the thumbstick changed
68 }
69 
70 // touchpad
71 
72 // in WebVR we had "pad" concept which was for both thumbstick and touchpad
73 controller.onPadValuesChangedObservable.add(function (stateObject) {
74   console.log(stateObject); // {x: 0.1, y: -0.3}
75 });
76 
77 // in WebXR, it is much much better:
78 const touchpad = xrController.motionController.getComponent(WebXRControllerComponent.TOUCHPAD);
79 if (touchpad) {
80   // Finally, a controller with a touchpad
81   touchpad.onButtonStateChanged; // will trigger when the touchpad is touched or pressed
82 
83   touchpad.onAxisValueChanged; // will trigger when axes of the touchpad changed
84 }

阅读有关XR 控制器系统的更多信息。

兼容性支持

 我们始终鼓励向后兼容,我们建议直接使用 WebXR 并停止使用 WebVR 体验助手(WebVR experience helper)。

当然:

最新的 WebVR 体验助手在其初始化选项中有一个新标志 - useXR。 这将检查是否支持WebXR,如果支持,则会在WebXR中启动VR会话。

一个工作示例参见WebVR demo

源代码如下:

 1 var createScene = function () {
 2   // Create scene
 3   var scene = new BABYLON.Scene(engine);
 4 
 5   // Create simple sphere
 6   var sphere = BABYLON.Mesh.CreateIcoSphere(
 7     "sphere",
 8     {
 9       radius: 0.2,
10       flat: true,
11       subdivisions: 1,
12     },
13     scene,
14   );
15   sphere.position.y = 3;
16   sphere.material = new BABYLON.StandardMaterial("sphere material", scene);
17 
18   // Lights and camera
19   var light = new BABYLON.DirectionalLight("light", new BABYLON.Vector3(0, -0.5, 1.0), scene);
20   light.position = new BABYLON.Vector3(0, 5, -2);
21   var camera = new BABYLON.ArcRotateCamera("camera", -Math.PI / 2, Math.PI / 4, 3, new BABYLON.Vector3(0, 3, 0), scene);
22   camera.attachControl(canvas, true);
23   scene.activeCamera.beta += 0.8;
24 
25   // Default Environment
26   var environment = scene.createDefaultEnvironment({
27     enableGroundShadow: true,
28     groundYBias: 2.8,
29   });
30   environment.setMainColor(BABYLON.Color3.FromHexString("#74b9ff"));
31 
32   // Shadows
33   var shadowGenerator = new BABYLON.ShadowGenerator(1024, light);
34   shadowGenerator.useBlurExponentialShadowMap = true;
35   shadowGenerator.blurKernel = 32;
36   shadowGenerator.addShadowCaster(sphere, true);
37 
38   // Enable VR, use XR when possible
39   var vrHelper = scene.createDefaultVRExperience({
40     createDeviceOrientationCamera: false,
41     useXR: true, // This will enable XR if supported
42     floorMeshes: [environment.ground],
43   });
44 
45   // Runs every frame to rotate the sphere
46   scene.onBeforeRenderObservable.add(() => {
47     sphere.rotation.y += 0.0001 * scene.getEngine().getDeltaTime();
48     sphere.rotation.x += 0.0001 * scene.getEngine().getDeltaTime();
49   });
50 
51   // GUI
52   var plane = BABYLON.Mesh.CreatePlane("plane", 1);
53   plane.position = new BABYLON.Vector3(0.4, 4, 0.4);
54   var advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateForMesh(plane);
55   var panel = new BABYLON.GUI.StackPanel();
56   advancedTexture.addControl(panel);
57   var header = new BABYLON.GUI.TextBlock();
58   header.text = "Color GUI";
59   header.height = "100px";
60   header.color = "white";
61   header.textHorizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER;
62   header.fontSize = "120";
63   panel.addControl(header);
64   var picker = new BABYLON.GUI.ColorPicker();
65   picker.value = sphere.material.diffuseColor;
66   picker.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER;
67   picker.height = "350px";
68   picker.width = "350px";
69   // This will work in XR, since we are using native pointer events!
70   picker.onValueChangedObservable.add(function (value) {
71     sphere.material.diffuseColor.copyFrom(value);
72   });
73   panel.addControl(picker);
74 
75   vrHelper.onAfterEnteringVRObservable.add(() => {
76     // This callback will still work! Would be better to use the XR native observables.
77   });
78 
79   return scene;
80 };

颜色选择器(The color picker)使用指针架构(The pointer architecture)来工作,用户点击(point)不同颜色区域,可以选择不用的颜色。 如果存在 XR,则将使用 XR。 否则,它将使用 WebVR 作为后备。

请注意,WebVR的某些功能将无法正常工作或根本无法工作。 例如,相机凝视(camera gaze)功能根本不起作用。 控制器可以工作,但由于交互架构不同,您很可能需要调整一些观察者(observers)才能使其工作,特别是专门针对VR的控制器回调。

我们建议在不支持WebXR的浏览器中,使用WebXR polyfill代替WebVR 体验助手(WebVR experience helper)进行WebVR开发

PS:

1)本文翻译自babylon.js官方WebXR文档,翻译用于自学和巩固知识,也希望能给有需要的人一点帮助;

2)阅读本文,需要具备一定的Web JavaScript,babylon.js,以及WebVR开发基础。

翻译若有不当之处,请指正。

 

标签:WebVR,Babylon,scene,WebXR,var,new,js,BABYLON
来源: https://www.cnblogs.com/muliublog/p/14982660.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有