在 WebVR 中呈现文本

详情内

查看网站

Fitbit (https://with.in/) 是一个用于讲故事的平台, 虚拟现实。我们的团队听说了 WebVR, 2015 年,我们立即对其潜力产生了兴趣。如今,这种兴趣 复制到我们网络平台的唯一子网域中, https://vr.with.in/.任何拥有支持 VR 的浏览器的用户都可以 访问该网站,点击按钮并戴上头戴设备,即可身临其境地 一系列 VR 电影。

目前这包括但不限于 Daydream View 上的 Chrome。对于 有关您的设备和头戴式显示器的信息,请查看 https://webvr.info/.

就像其他虚拟实境的渲染环境一样, 主要依赖于场景的三维表现形式。这个 具有镜头、您的视角和任意数量的对象。帮助管理 我们使用名为 Three.js,利用 <canvas> 元素抛出 渲染到计算机的 GPU 上。我们提供了许多实用的 Three.js 插件 让您的场景在 WebVR 中可见。其中主要有两项 THREE.VREffect 分别为每个眼睛创建一个视口 THREE.VRControls (例如,旋转角度和位置) 。这里有很多 如何实现这一点。请查看 Three.js WebVR 示例 了解如何开始使用。

随着我们对 WebVR 的进一步探索,出现了一个问题。如果我们查看 在网页内容中,文本是不可或缺的一部分。虽然大多数 的内容都是视频形式 网站内:内容周围有文字; 与电影或相关电影有关的额外信息 以文本格式构建而成。此外,所有这些文本都是在 DOM 中创建。我们的 WebVR 探索和 https://vr.with.in/ 均已包含 <canvas>

<ph type="x-smartling-placeholder">
</ph> WebVR 中使用的文字 WebVR 中使用的文字
WebVR 中针对 vr.with.in 使用的文本

我可以选择哪些选项?

幸运的是,要实现这个目标,还有很多工作要做。事实上,我们的研究显示, 我们发现,可以通过多种有效方法将文本渲染为 为 <canvas> 元素指定环境。下方是我们发现的 并标注了各自的优缺点:

与分辨率无关 排版功能 性能 实施的难易程度
2D 画布文本
三角矢量文本
拉伸的 3D 文本
有符号距离字段位图文本

我们的决定:SDF 位图字体

使用 ctx.fillText() 的 2D 画布可以进行文本换行、字母间距和行线 但如果放大,文字就会被截断,而且文字会变得模糊 远。您可以增加画布纹理的大小,但可能会超出 纹理尺寸或性能方面的限制

拉伸的 3D 文本与三角矢量文本本质上相同,但带有 以及倾斜的角度,使其至少具有两倍的几何体。两者之一 在标题或徽标中,如果试得少,效果就不如 非常适合大量文本,而且都没有排版特征。

<ph type="x-smartling-placeholder">
</ph> 字体转换为 SDF 位图的工作流程
字体转换为 SDF 位图的工作流程

位图字体每个字符使用一个四边形(两个三角形),因此使用较少 而且其性能优于 三角矢量: 它们仍基于光栅,因为它们使用的是纹理贴图精灵,但使用 SDF 着色器基本上与分辨率无关,因此它们看起来比 2D 画布纹理。 Matt DesLauriers third-bmfont-text 还包括可靠的文字换行功能, 字母间距、行高和对齐方式。溢出内容不会被截断。字体 都是通过缩放来控制大小我们选择这条路线,是因为它提供了 最佳设计方案,同时保持高性能。很遗憾, 所以我们将逐步介绍这些步骤 在 WebVR 任职的开发者。

1. 生成位图字体 (.png + .fnt)

<ph type="x-smartling-placeholder">
</ph> Hiero 接口
Hiero 接口
<ph type="x-smartling-placeholder">
</ph> Hiero 输出(位图 PNG 和 .fnt 文件) Hiero 输出(位图 PNG 和 .fnt 文件)
Hiero 输出(位图 PNG 和 .fnt 文件)

Hiero 是一种位图字体打包 使用 Java 运行的工具Hiero 文档并未真正说明如何 无需经过复杂的构建流程即可运行您的应用。首先,如果存在以下情况,请安装 Java 。然后,如果双击 runnable-hiero.jar 打开 Hiero,请尝试在控制台中使用以下命令运行它:

java -jar runnable-hiero.jar

Hiero 运行后,打开 .ttf 或 .otf 桌面字体,输入任何额外的字体。 想要包含想要包含的字符,将呈现方式更改为 Java 以启用效果, 增大字形,使字符填满整个字形缓存方形 添加距离字段效果,调整距离字段的比例和展开。通过 scale 值类似于分辨率。图像的分辨率越高,模糊度就越低 但 Hiero 呈现预览所需的时间越长。然后保存您的 位图字体。它可以生成一个位图字体,该字体由 .png 图像和 AngelCode .fnt 字体描述文件。

2. 将 AngelCode 转换为 JSON

现在位图字体已经生成,我们必须将其加载到 Matt DesLauriers 的 JavaScript 应用 load-bmfont npm 软件包

我们可以对 load-bmfont 进行浏览器化,并在前端使用它, CANNOT TRANSLATE load-bmfont.js 用于将 Hiero 的 AngelCode .fnt 转换为 .json 文件

npm install
node load-bmfont.js
输出 JSON 示例
输出 JSON 示例

现在我们可以绕过 load-bmfont,只对 .json 字体文件。

var r = new XMLHttpRequest();
r.open('GET', 'fonts/roboto/bitmap/roboto-bold.json');

r.onreadystatechange = function() {
    if (r.readyState === 4 && r.status === 200) {
    setup(JSON.parse(r.responseText));
    }
};

r.send();

function setup(font) {
    // pass font into TextBitmap object
}

3. 浏览器化 3-bmfont-文字

字体加载完毕后,Matt 的 3-bmfont-text 负责处理 。由于我们没有在自己的应用中使用 Node,因此我们将 browserify three-bmfont-text.js 转换为可用的three-bmfont-text-bundle.js

npm install -g browserify
browserify three-bmfont-text.js -o three-bmfont-text-bundle.js

4. SDF 着色器

调整 afwidththreshold 滑块开启 vr.with.in/archive/text-sdf-bitmap/ 以了解带符号距离字段着色器的影响。

5. 用法

为方便起见,我创建了一个 TextBitmap 封装容器类 用于浏览器化的 3-bmfont-text。

<ph type="x-smartling-placeholder">
</ph> 文本 sdf 位图的实际应用
文本 sdf-bitmap 的实际运用
<script src="three-bmfont-text-bundle.js"></script>
<script src="sdf-shader.js"></script>
<script src="text-bitmap.js"></script>

创建针对 .json 字体文件的 XHR 请求,并在 回调:

var bmtext = new TextBitmap({ options });

如需更改文字,请执行以下操作:

bmtext.text = 'The quick brown fox jumps over the lazy dog.';

scene.add( bmtext.group );
hitBoxes.push( bmtext.hitBox );

位图字体的 .png 是使用 text-bitmap.js 中的 THREE.TextureLoader 加载的

TextBitmap 还包含一个用于 three.js 光线投射互动的不可见碰撞框 通过鼠标、相机或手跟踪的运动控制器(如 Oculus Touch 或 Vive 控制器碰撞框的大小会在您更改文本时自动更新 选项。

将 Bmtext.group 添加到了 three.js 场景中。如果您需要访问 / Object3D 中,文本的场景图如下所示:

文件系统示意图

6. 取消缩减 json 并修改 xoffset

在文字 GIF 中

如果字距调整有误,您可能需要修改 JSON 中的 xoffset。粘贴 将 JSON 输入 Jsbeautifier.org 以获取 非精简版文件。

xoffset 本质上是一个字符的全局字距调整。字数为二 每个字符相邻。默认情况下, 字距调整数组实际上并没有什么不同, 修改,所以您可以清空该数组以减小 JSON 的文件大小。然后 修改字距调整的 Xoffsets。

首先,您必须确定哪些字符与 json。在 three-bmfont-text-bundle.js 中, 在第 240 行后插入 console.log

    var id = text.charCodeAt(i)
    // console.log(id);

然后在 dat.gui 文本字段中键入 https://vr.with.in/archive/text-sdf-bitmap/ 然后查看控制台以查找字符的对应 ID。

例如,在我们的位图字体中,总是太靠右其 字符 ID 为 106。因此,请在 json 中找到 "id": 106 并将其 xoffset 从 -1 更改为 1。 调整为 -10。

7. 布局

如果您有多个文本块,并且希望它从上到下流动, 与绝对定位类似,在 HTML 中,所有内容都必须手动定位 自定义每个 DOM 元素。您能想像在 CSS 中这样做吗?

    * { position: absolute; }

这就是 3D 文本布局的样子。在详细信息视图中:书名、作者、 说明和时长都是一个新的 TextBitmap 对象,每个对象都有自己的 样式、颜色、比例等:

3D 布局
author.group.position.y = title.group.position.y - title.height - padding;
description.group.position.y = author.group.position.y - author.height - padding;
duration.group.position.y = description.group.position.y - description.height - padding;

此示例假设每个 TextBitmap 组的本地原点都是垂直的 与 TextBitmap 网格的顶部对齐(请参见 text-bitmap.js 更新)。如果您稍后更改了其中任何对象的文本, 您也需要重新计算这些位置。在这里, 只修改了文本的 y 轴位置, 我们可以沿 z 轴方向推拉文字 围绕 x 轴、y 轴和 z 轴

总结

WebVR 中的文本和布局经过很长的路要走,才能变得简单 广泛用作 HTML 和 CSS 格式但切实有效的解决方案确实存在,您可以执行更多操作 与传统 HTML 网页相比,更加难以实现。WebVR 如今已经存在。 未来可能会推出更好的工具。在此之前,请尝试 实验。在没有通用框架的情况下进行开发会带来更加独特的 这令人激动不已