How to Add Custom Fonts on React VR Project

Samuli Hakoniemi
5 min readNov 15, 2017

Recently, I started playing with React VR by learning the basic concepts of WebVR APIs and the beautiful concept of virtual reality as such. And soon I was sitting in a gondola in Venice with my HTC Vive. As a React Native (and React) developer it was quite easy to familiarise myself with the concept of React VR.

My initial project, “Bottlist”, which is an alcohol beverages catalogue observed through virtual world has an UI which is missing many things. And what I’ve learned from my design colleagues is that also fonts and the overall readability are playing a major part of good UX.

However, it turned out that adding custom fonts in VR project isn’t easy at all. Therefore I decided to share this knowledge with you, hoping to help you out to add some eye-candy to your next virtual reality project.

This post was inspired by Valentin Radulescu and his great findings about bringing fonts into React VR project.

What’s the problem?

A font isn’t considered as a plain text object like normally. Everything is rendered through Three.js. And even though it’s using <Text> component with React VR, it still is always rendered into canvas element.

In order to implement our custom font to React VR project, we need to take several steps before we actually can start using it.

Step #1: Setup Fontue

Fontue is a tool for building SDF (Signed Distance Field) format fonts which can be used together with WebVR.

The easiest way to use Fontue is taking advantage from React VR Tools by:

1. cloning the repository: git clone git@github.com:facebook/react-vr.git

2 . navigating to the folder: react-vr/tools/fontue/

3. installing CMake and Freetype:

OSX:
$ brew install cmake
$ brew install freetype
WINDOWS:
https://cmake.org/download/
https://www.freetype.org/download.html

3.1. and a note for Windows users:

After downloading FreeType, the libraries must be compiled separately before building fontue.exe.

The FreeType library must then exist in ./freetype2 as
freetype2/lib/freetype.lib
freetype2/include

4. finally we build the Fontue tool:

$ cmake .
$ make

Also notice that running make on Windows you will probably need MinGW or some alternative.

Step #2: Generating SDF Font File

Next we’re going to generate SDF from an .otf font file. I’m not an expert on explaining all the parameters we need to provide for Fontue (you can browse docs if you’re interested in that).

With most fonts you’re good to go with:

./fontue <path_to_font_folder>/<font_name>.<font_ext> <path_to_font_folder>/<font_name> -co -0.01 -ts 1.0 -hpad 128 -vpad 128 -sdf 512 -1 -1 -ur 0x0010 0x00ff -ur 0x0370 0x03FF -ur 0x0100 0x017F -ur 0x0180 0x024F

But with Font Awesome, we need customise the unicode range a bit:

./fontue <path_to_font_folder>/FontAwesome.otf <path_to_font_folder>/FontAwesome -co -0.01 -ts 1.0 -hpad 128 -vpad 128 -sdf 512 -1 -1 -ur 0xf000 0xf2e0

Now you should see something like this populating to your console:

Fontue version 0.0
by Jonathan E. Wright
Copyright © 2014 by Oculus VR, LLC.

Portions of this software are copyright © 1996–2014 The FreeType
Project (www.freetype.org). All rights reserved.

Error loading fallback font droidsans.ttf.
Loaded font file /<path_to_font_file>/FontAwesome.otf.

Rendering 738 glyphs.

row n+1 of 1842

And after you’ve enjoyed a cup of coffee you should have following files:

FontAwesome.fnt
FontAwesome_sdf.png
FontAwesome_allcodepoints.txt

Step #3: Setting up the client

In order to load the fonts, we need to make changes into client.js:

import { VRInstance } from 'react-vr-web';
import * as OVRUI from 'ovrui';
function init(bundle, parent, options) {
return OVRUI.loadFont(
'../fonts/FontAwesome.fnt',
'../fonts/FontAwesome_sdf.png',
).then((font) => {
const vr = new VRInstance(bundle, 'ProjectName', parent, {
font,
...options,
});
vr.render = function() {
};
vr.start(); return vr;
});
}
window.ReactVR = { init };
  1. We import OVRUI to project, which is a framework to build WebVR applications. It contains the logic for text rendering by using SDF fonts,
  2. We wrap font loading in a Promise,
  3. Then we add loaded font(s) to the instance and proceed normally with the existing options and code declarations.

After these steps we’re ready to do the magic.

Step #4: Using Custom Font(s)

We’re almost there. In this example project we’re going to display Twitter icon + our Twitter handle.

We have to view our font data. This can be done e.g. with Font Book (OSX) or e.g. with Maintype (Windows). There we can see the actual reference to glyph:

Twitter glyph aka \uF081

So far, so good? Nope… now we have two problems:

There is no fontFamily style property in ReactVR. This means we have to use FontAwesome in the whole project…

…but because FontAwesome does not contain glyphs for latin letters, it throws following error for our Twitter handle:

Uncaught TypeError: Cannot read property ‘Height’ of undefined
at Object.measureText (SDFFont.js:297)
at RCTText.measure (Text.js:266)
at Text.js:82

Therefore we need to add the default fonts with support for latin letters and a “fallback font” for glyph icons. This is done in the client.js:

import { VRInstance } from 'react-vr-web';
import * as OVRUI from 'ovrui';
function init(bundle, parent, options) {
Promise.all([
OVRUI.loadFont(
'../fonts/Bitter-Regular.fnt',
'../fonts/Bitter-Regular_sdf.png'
),
OVRUI.loadFont(
'../static_assets/FontAwesome.fnt',
'../static_assets/FontAwesome_sdf.png'
)
])
.then(([font, fontAwesome]) => {
OVRUI.addFontFallback(font, fontAwesome);
const vr = new VRInstance(bundle, 'ProjectName', parent, {
font,
...options
});
vr.render = function() {};
vr.start();
return vr;
});
}
window.ReactVR = { init };

In brief:

  1. we wrap all the font loading promises in chain,
  2. we push FontAwesome as a fallback of our default font (“Bitter”), which contains the latin letters.

Step #5: Actual Result

What do we get after all of this? Well, I did something like this on the default project in React VR:

<Text style={{
backgroundColor: 'transparent',
color: '#6699CCE0',
fontSize: 1,
transform: [{translate: [-2, 0.5, -5]}]
}}>
{'\uF081 @zvona'}
</Text>

And here is the actual result:

My Twitter handle in Virtual Reality :)

Conclusion

Implementing custom fonts are more difficult in VR environment than in the “normal playground” also known as web and mobile. I don’t think there’s going to be changes in near future, so I sincerely hope this tutorial really helps you with the custom fonts.

Resources

--

--