3D 内容容器
现有 HTML 元素都只能在 2D 平面中显示内容,即使是基于 WebGL 的 <canvas> 元素和新的 <model> 元素,都只能在平面画布中渲染 3D 内容,从空间计算的角度来说,它们仍然都是 2D 内容的一部分。
WebXR API 虽然能用 WebGL 在 3D 空间中渲染有体积的 3D 内容,但这些内容只能在 WebXR session 中显示,无法作为 3D HTML 元素参与 HTML/CSS 体系、在 Web App 里直接显示。
WebSpatial API 在现有 HTML 标准基础上新增了两种真正的 3D HTML 元素,这些元素都是空间化 HTML 元素,作为空间中悬浮的 2D 面片使用,继续参与 HTML/CSS 布局系统,跟空间化的 2D HTML 元素具备相同能力和用法,但除此之外,还能在 2D 面片前方的局部空间中,用 3D 开发范式实现有真正体积的 3D 内容,支持统一渲染,让 3D 内容能跟 2D 内容融合共存。
3D 容器元素除了能基于现有 Web 标准决定 2D 面片的宽和高,还能用 WebSpatial API 新增的 CSS 属性设置 2D 面片前方局部 3D 空间的深度,可以用新增的 DOM API 查询当前的深度。
WebSpatial SDK 以 React 组件的形式提供这两种 3D 容器元素。
静态 3D 容器
第一种 3D 容器元素是 <Model>,它在 2D 面片前方的局部空间中用预制好的 3D 模型文件渲染静态 3D 内容,「静态」是指这种 3D 内容虽然能用 API 控制模型文件内置动画的播放,也能通过 API 改变模型文件在这个局部空间中的渲染方式,但无法在应用运行过程中用代码动态渲染任意的 3D 内容。
动态 3D 容器
第二种 3D 容器元素是 <Reality>,它在 2D 面片前方的局部空间中可以用支持统一渲染的 3D Engine API 动态渲染任意 3D 内容。
3D 引擎 API
为了让空间计算操作系统和 Spatial Runtime 能理解动态 3D 容器中的 3D 内容,能把它们跟空间中其他 2D/3D 内容一起做统一渲染,不能在动态 3D 容器的内容中直接使用 WebGL/WebGPU 和基于这些底层 3D 图形 API 的任意 Web 3D 引擎。
WebSpatial API 中内置了一套结合了 ECS 风格和 HTML 风格的声明式 3D 引擎 API,支持统一渲染。
这套 API 用 HTML 元素的形式提供各种开箱即用的 3D Entity,这些 Entity 的底层实现中基于 ECS 架构内置了不同的 Component 能力(ECS 的概念,不是指 UI Component),这些 Component 能力可以通过 HTML 属性使用,比如可以引用提前声明好的 3D 资产、设置几何物体的尺寸等。
这些 HTML 元素只能在动态 3D 容器中作为 Scene Graph 根节点的 <World> 中使用,不支持 CSS 和 2D 布局系统,而是采用 3D 引擎体系中的 Transform 属性在 3D 坐标系中渲染。
这些 3D Entity 不仅可以通过动态 3D 容器融入到 2D 布局体系和 HTML/CSS 内容中,还可以在 Entity 上附着 HTML/CSS 内容,让 2D 内容也能进入 3D 渲染体系。
这些在 <Reality> 内部使用的 HTML 元素在 WebSpatial SDK 中同样以 React 组件的形式提供。
2D 包含 3D
3D 容器元素就像桥梁,能把容器外基于 CSS 的 2D 布局系统,和容器内基于 3D 引擎的 3D 渲染体系,融合到一起,实现「2D 包含 3D」的新范式: 整个 WebSpatial App 可以默认作为 2D Web App 来开发,使用主流的 2D Web 框架(比如 React)和基于 HTML/CSS 的主流 Web API。只在应用中真正需要 3D 内容的局部区域,按需使用 3D 引擎体系的开发范式。且 3D 引擎的渲染能融入 2D 渲染体系中(WebSpatial SDK 提供的 HTML 风格 3D 引擎 API,能基于 React 的渲染机制做 3D 内容的初始化和更新)。
WebSpatial App 中的 Spatial Scene、空间化 HTML 元素(包括元素上触发的空间事件的结果)、基于 HTML/CSS 的 2D 内容,都属于 2D 开发范式,采用左手坐标系,原点都位于 2D 面片的左上角,Y 轴向下,Z 轴朝向用户,长度单位默认用面向 GUI 的 point 单位(px)。
3D 容器元素中的 3D 内容,则采用 3D 开发范式,采用右手坐标系,原点在容器对应的局部 3D 空间的中心点,Y 轴朝上,Z 轴朝向用户,长度单位默认用面向现实世界物体的物理单位(m)。
由于这些内容都由 Spatial Runtime 做统一渲染,因此可以在这些坐标系和长度之间任意转换,让 2D 范式的内容能跟 3D 范式的内容互相结合,比如在空间中对齐位置、自动跟随、彼此联动等。