在 WebVR 中轉譯文字

詳細資料

瀏覽網站

在 (https://with.in/) 是虛擬實境中述說故事的平台。因此,當團隊在 2015 年聽說 WebVR 時,便立即瞭解這項技術的潛力。但現在,該興趣資訊清單會收錄至我們網路平台的專屬子網域 https://vr.with.in/。任何人都可以使用支援 VR 的瀏覽器前往該網站,按一下按鈕並將頭戴式裝置擺在頭戴式裝置上,沉浸在我們的 VR 電影系列中。

目前的這項功能包括但不限於 Daydream View 上的 Chrome。如需裝置和頭戴式螢幕的相關資訊,請參閱 https://webvr.info/

如同其他虛擬實境專屬的算繪環境,網路主要仰賴 3D 呈現場景。這個場景有相機、你的視角和任意數量的物件。為協助管理這個情境、相機和物件,我們使用名為 Three.js 的程式庫,該程式庫會利用 <canvas> 元素將算繪結果擲回到電腦的 GPU。您可以透過許多實用的 Three.js 外掛程式,在 WebVR 中看見您的場景。其中主要分為兩種:THREE.VREffect 用於建立每個眼睛的可視區域,THREE.VRControls 用於將視角轉譯 (例如:將場景旋轉並裝入頭頂顯示器)。有很多例子可以說明實作方式。如要瞭解如何開始使用,請參閱 Three.js WebVR 範例

我們也在深入探索 WebVR 時,發現了一項問題。如果要尋找網路上的內容,文字就是其中不可或缺的一部分。雖然我們大部分的內容都是以影片為基礎,但如果您前往「現場」使用的文字圍繞著內容,使用者介面或相關電影的額外資訊都以文字建構。此外,這段文字也在 DOM 中建立。我們的 WebVR 探索和 https://vr.with.in/ 都位於 <canvas>

WebVR 中使用的文字 WebVR 中使用的文字
vr.with.in
在 WebVR 中使用的文字

我的選項是什麼?

幸好,必須努力達成這個目標。事實上,我們的研究發現,許多方式都能在 <canvas> 元素上的 3D 環境中顯示文字。下列矩陣是幾個 我們分別標示為優缺點的矩陣:

獨立解析度 字體排版功能 效能 導入難易度
2D 畫布文字
傾斜的向量文字
顯示在 3D 文字的誇大文字
已簽署的距離欄位點陣圖文字

我們的決定:SDF 點陣圖字型

ctx.fillText() 的 2D 畫布可處理文字換行、字母間距和行高,但溢位會遭到截斷,如果放大畫面的話,文字也會模糊不清。您可以增加畫布紋理的大小,但如果紋理過大,可能會達到紋理大小上限或效能不佳。

凸起的 3D 文字本質上與三角形的向量文字相同,但深度和也許是鐵絲,因此該文字的幾何圖形至少為兩倍。這兩種方法都只能用小幅度增加標題或標誌,但針對大量文字時效能不彰,也沒有字體圖形功能。

字型到 SDF 點陣圖工作流程
SDF 點陣圖工作流程

點陣圖字型每個字元一個四方 (兩個三角形),因此使用的幾何圖形較少,效能也優於三角形向量。由於這些它們使用紋理貼圖 Sprite,因此仍以光柵化,但 SDF 著色器基本上與解析度無關,因此看起來比 2D 畫布紋理更出色。Matt DesLauriers 敬上 3bm 字型文字的可靠字體圖形功能,可以為文字換行、字母間距、行高和對齊方式提供可靠的字體排版功能。溢位無法截斷 字型大小是以縮放方式控制我們之所以選擇這個做法,是因為它能提供最佳設計選項 同時維持高效能。但實作方式不易,因此我們將逐步示範,希望幫助其他開發人員在 WebVR 中工作。

1. 產生點陣圖字型 (.png + .fnt)

Hiero 介面
Hiero 介面
Hiero 輸出 (點陣圖 PNG 和 .fnt 檔案) Hiero 輸出 (點陣圖 PNG 和 .fnt 檔案)
Hiero output (Bitmap PNG 和 .fnt 檔案)

Hiero 是透過 Java 執行的點陣圖字型封裝工具。Hiero 說明文件並未逐步說明如何在沒有複雜的建構程序的情況下執行。請先安裝 Java (如果尚未安裝)。接著,如果按兩下 runnable-hiero.jar 並未開啟 Hiero,請在主控台中使用下列指令執行:

java -jar runnable-hiero.jar

執行 Hiero 後,開啟 .ttf 或 .otf 電腦字型,輸入想要加入的所有額外字元,將轉譯成 Java 以啟用效果,加大尺寸讓字元填滿整個字符快取正方形,新增距離欄位效果,調整距離欄位的縮放比例並分散。規模值就像解析度一樣。值越高,模糊程度就會越少,但 Hiero 顯示預覽畫面所需的時間就越長。然後儲存點陣圖字型它會產生點陣圖字型,其中包含 .png 圖片和 AngelCode .fnt 字型說明檔案。

2. 將 AngelCode 轉換為 JSON

點陣圖字型已產生完畢,因此我們必須使用 Matt DesLauriers 的 load-bmfont npm 套件將其載入 JavaScript 應用程式。

我們可以 Browserify load-bmfont 並在前端使用,但是我們要改用 Node 執行 load-bmfont.js 來轉換 Hiero 的 AngelCode .fnt 並儲存至 .json 檔案

npm install
node load-bmfont.js
輸出 JSON 範例
輸出 JSON 範例

現在,我們可略過 load-bmfont,只需在 .json 字型檔案中執行 XHR (XMLHttpRequest) 要求。

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. Browserify 三下字型文字

字型載入完畢後,Matt 的三 bmfont-文字就會處理其餘部分。由於我們不會在自己的應用程式中使用 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 著色器

調整 vr.with.in/archive/text-sdf-bitmap/ 上的「afwidth」和「threshold」滑桿,瞭解已簽署距離欄位著色器的影響。

5. 使用方法

為了方便起見,我針對瀏覽器化的三 bmfont-text 建立了 TextBitmap 包裝函式類別

實際使用 Text-sdf-bitmap
Text-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 也包含用於透過滑鼠、相機或手追蹤動作控制器 (例如 Oculus Touch 或 Vive 控制器) 進行 3.js 光播互動的隱形命中箱。變更文字選項時,命中方塊的大小自動更新。

Bmtext.group 已新增至 Three.js 場景。如果您需要存取子項/物件 3D,文字的場景圖看起來會像這樣:

檔案系統圖表

6. 統合 JSON 並修改 xoffset

在文字 GIF 中

如果在模擬功能關閉後,您可能需要編輯 JSON 中的 xoffset。請將 JSON 貼至 Jsbeautifier.org,即可取得檔案未經修改的版本。

Xoffset 基本上是為單一角色在全球遊戲中奮鬥,Kerning 是指兩個彼此相鄰的特定字元。核心陣列中的預設值實際上並不會造成影響,而且編輯作業會過於繁瑣,因此您可以清空該陣列,減少 JSON 的檔案大小。然後編輯核心的 Xoffset。

首先,您必須找出 JSON 中哪些字元的字元 ID。在 three-bmfont-text-bundle.js 中,在第 240 行之後插入 console.log

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

然後在 https://vr.with.in/archive/text-sdf-bitmap/ 上輸入 dat.gui 文字欄位,並查看主控台,找出某個字元的對應 ID。

例如,在我們點陣圖的字型中,「j」始終不固定。其字元 ID 為 106。因此,請在 JSON 中找出 "id": 106,並將其 xoffset 從 -1 變更為 -10。

7. 版面配置

如果您有多個文字區塊,且希望文字從上往下流動 (例如 HTML),則所有內容都必須手動放置,這與透過 CSS 自行設定每個隨機元素的絕對定位類似。您能想像在 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 軸位置,但在 3D 中處理的一個機會就是,我們可以在 Z 方向推送和提取文字,也可以繞 x、y 和 z 軸旋轉。

結語

WebVR 中的文字和版面配置,比以往簡單且廣泛用於 HTML 和 CSS。不過,現有解決方案確實存在,而且在 WebVR 中,您可以採取的效益比傳統 HTML 網頁更多。WebVR 現已推出。 而且明天有可能會更適合的工具。在此之前,請試試看並實驗。在沒有廣泛的架構下進行開發時,開發過程會更加獨特,這真是令人興奮。