Cómo renderizar texto en WebVR

En detalle

Visita el sitio

Dentro de (https://with.in/) hay una plataforma para narrar historias en realidad virtual. Cuando el equipo se enteró de WebVR en En 2015, nos interesó inmediatamente su potencial. Hoy en día, ese interés se manifiesta en un subdominio único de nuestra plataforma web, https://vr.with.in/. Cualquier persona con un navegador compatible con RV puede visita el sitio, haz clic en un botón y ponte auriculares para sumergirte en nuestra de películas en RV.

Actualmente, esto incluye, entre otros, a Chrome en Daydream View. Para información del dispositivo y la pantalla de realidad virtual https://webvr.info/.

Al igual que otros entornos de renderización específicos de realidad virtual, la Web se basa principalmente en una representación tridimensional de una escena. Esta tiene una cámara, tu perspectiva y cualquier cantidad de objetos. Para ayudar a administrar escena, cámara y objetos. Usamos una biblioteca llamada Three.js, que aprovecha el elemento <canvas> para arrojar renderizado en la GPU de tu computadora. Existen muchos complementos útiles de Three.js para permite que tu escena se pueda ver en WebVR. Los dos principales son THREE.VREffect para crear una ventana de visualización para cada ojo y THREE.VRControls para trasladar la perspectiva (por ejemplo, la rotación y la posición de la montado en la cabeza) de manera convincente a tu escena. Hay muchos ejemplos de cómo implementar esto. Consulta la Ejemplos de WebVR de Three.js para conocer formas de comenzar.

A medida que avanzamos en la exploración de WebVR, tuvimos un problema. Si miramos en los contenidos de la web, el texto es una parte integral. Si bien la mayoría de nuestro contenido se basa en videos. El texto Dentro del sitio rodea el contenido. la interfaz de usuario y la información adicional sobre una película o películas relacionadas se construido con texto. Además, todo este texto se crea en el DOM. Nuestro Las exploraciones de WebVR y https://vr.with.in/ están en <canvas>

Texto usado en WebVR Texto usado en WebVR
Texto usado en WebVR para vr.with.in

¿Cuáles son mis opciones?

Por suerte, estamos trabajando para que esto sea posible. De hecho, en nuestra investigación encontramos una serie de formas efectivas de renderizar el texto de forma tridimensional entorno en un elemento <canvas>. A continuación, se muestra una matriz de algunas marcarse con pros y contras para cada una:

Independiente de la resolución Atributos tipográficos Rendimiento Facilidad de implementación
Texto de lienzo en 2D
Texto de vector triangulado
Texto 3D extruido
Texto del mapa de bits del campo de distancia firmada

Nuestra decisión: Fuente del mapa de bits de SDF

El lienzo 2D con ctx.fillText() puede ajustar texto, espacios entre letras y líneas. alto, pero el desbordamiento se corta y el texto se ve borroso si acercas mucho hasta ahora. Podrías aumentar el tamaño de la textura del lienzo, pero podrías alcanzar un límite en el tamaño o el rendimiento de la textura podría verse afectada si la textura es demasiado grande.

El texto 3D extruido es básicamente lo mismo que el texto vectorial triangulado, pero con de profundidad y, posiblemente, un bisel, para que tenga al menos el doble de geometría. Cualquiera de podrían funcionar en pequeñas dosis para los títulos o logotipos, pero no funcionarían tan bien sirve para grandes cantidades de texto y ninguno tiene características tipográficas.

Flujo de trabajo de fuente a mapa de bits de SDF
Flujo de trabajo de fuente a mapa de bits de SDF

Las fuentes del mapa de bits usan un cuadrante (dos triángulos) por carácter, por lo que usan menos geometría y funcionar mejor que vectores triangulados. Todavía están basados en tramas, ya que usan un objeto de mapa de texturas, pero con un SDF. básicamente dependen de la resolución, por lo que se ven más bonitos que un 2D textura de lienzo. Matt DesLauriers tres-bmfont-text también incluye características tipográficas confiables para el ajuste de texto, el espaciado entre letras, la altura de línea y la alineación. El desbordamiento no se corta. Fuente el tamaño se controla a través de la escala. Elegimos esta ruta porque nos dio la las mejores opciones de diseño sin sacrificar el rendimiento. Por desgracia, no fue tan fáciles de implementar, así que repasaremos los pasos con la esperanza de ayudar a otras personas desarrolladores que trabajan en WebVR.

1. Genera una fuente de mapa de bits (.png + .fnt)

Interfaz de Hiero
Interfaz de Hiero
Salida de Hiero (mapa de bits PNG y archivo .fnt) Salida de Hiero (mapa de bits PNG y archivo .fnt)
Resultado de Hiero (mapa de bits PNG y archivo .fnt)

Hiero es un empaquetado de fuentes de mapa de bits. que se ejecuta con Java. En la documentación de Hiero, no se explica para ejecutarla sin tener que realizar un proceso de compilación complicado. Primero, instala Java si que todavía no tienes. Entonces, si haces doble clic en runnable-hiero.jar no abre Hiero, intenta ejecutarlo con este comando en la consola:

java -jar runnable-hiero.jar

Cuando se ejecute Hiero, abre una fuente de escritorio .ttf u .otf, y escribe caracteres que quieras incluir, cambia la renderización a Java para habilitar los efectos, aumentar el tamaño para que los caracteres ocupen todo el cuadrado de caché del glifo agregar un efecto de campo de distancia, ajustar la escala del campo de distancia y El el valor de escala es como una resolución. Cuanto más alta sea, menos borroso estará, pero cuanto más tiempo tarde Hiero en renderizarla. Luego, guarda tu fuente de mapa de bits. Genera una fuente de mapa de bits que consiste en una imagen .png y una Archivo de descripción de la fuente AngelCode .fnt.

2. Convierte AngelCode en JSON

Ahora que se generó la fuente del mapa de bits, debemos cargarla en nuestro App de JavaScript con Matt DesLauriers load-bmfont npm package.

Podemos usar el navegador load-bmfont y usar load-bmfont en el frontend, pero, en su lugar, se ejecutará load-bmfont.js con Nodo para convertir y guardar el AngelCode .fnt de Hiero en un Archivo.json:

npm install
node load-bmfont.js
Ejemplo de JSON de salida
Ejemplo de JSON de salida

Ahora podemos omitir load-bmfont y simplemente hacer una solicitud XHR (XMLHttpRequest) en el Archivo de fuente .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. Cómo usar Browserify con tres bmfont-text

Una vez que carguemos la fuente, el texto con 3 bmfont-text de Matt se encargará del el resto. Como no usamos Node para nuestra propia app, usaremos Navegador three-bmfont-text.js en un formato utilizable three-bmfont-text-bundle.js

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

4. Sombreador de SDF

Activa los controles deslizantes de afwidth y threshold. vr.with.in/archive/text-sdf-bitmap/ para ver el efecto del sombreador de campos de distancia con firma.

5. Uso

Para mayor comodidad, creé un Clase de wrapper TextBitmap para el navegador con tres bmfont-text.

Text-sdf-bitmap en acción
Text-sdf-bitmap en acción
<script src="three-bmfont-text-bundle.js"></script>
<script src="sdf-shader.js"></script>
<script src="text-bitmap.js"></script>

Crea una solicitud XHR para el archivo de fuente .json y crea un objeto de texto en el archivo devolución de llamada:

var bmtext = new TextBitmap({ options });

Para cambiar el texto, haz lo siguiente:

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

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

El .png de la fuente del mapa de bits se carga con THREE.TextureLoader en text-bitmap.js.

TextBitmap también incluye una caja de colisiones invisible para la interacción de raycast tres.js. con un mouse, una cámara o controladores de movimiento seguidos a mano, como Oculus Touch o los controladores de Vive. El tamaño de la caja de colisiones se actualiza automáticamente cuando cambias el texto opciones de estado.

Se agregó bmtext.group a la escena tres.js. Si necesitas acceder a la cuenta / Object3D, el gráfico de escena para el texto se ve así:

Diagrama del sistema de archivos

6. Unminifica JSON y modifica xoffsets

GIF dentro del texto

Si el interletraje se ve desviado, es posible que debas editar los xoffsets en el archivo json. Pegar el archivo json a Jsbeautifier.org para obtener una versión sin reducir del archivo.

En esencia, el xoffset es el interletraje global de un carácter. La función de recorte es para dos caracteres específicos que aparecen uno al lado del otro. Los valores predeterminados en realidad no marcan ninguna diferencia, y sería muy tedioso edit, por lo que puedes vaciar ese array para disminuir el tamaño del archivo json. Después editar los xoffsets para el interletraje.

Primero, tienes que averiguar qué caracteres van con cada ID de carácter en la JSON. En three-bmfont-text-bundle.js, inserta console.log después de la línea 240:

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

Luego, escribe en el campo de texto dat.gui en https://vr.with.in/archive/text-sdf-bitmap/ y revisa la consola para encontrar el ID correspondiente de un carácter.

Por ejemplo, en nuestra fuente de mapa de bits, "j" está constantemente demasiado a la derecha. Es el ID de carácter es 106. Busca "id": 106 en el JSON y cambia su xoffset de -1 a -10.

7. Diseño

Si tienes varios bloques de texto y quieres que fluya de arriba hacia abajo, HTML, todo se debe posicionar manualmente, similar al posicionamiento absoluto cada elemento dom por tu cuenta con CSS. ¿Te imaginas haciéndolo en CSS?

    * { position: absolute; }

Así es como es el diseño de texto en 3D. En la vista de detalles: título, autor, descripción y duración son cada uno un nuevo objeto TextBitmap con su propio estilos, color, escala, etc.:

Diseño 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;

Esto supone que el origen local de cada grupo TextBitmap es vertical alineado con la parte superior de la malla TextBitmap (consulta cómo centrar en text-bitmap.js actualizar). Si luego cambias el texto de cualquiera de esos objetos y la altura de ese objeto, también tendrás que volver a calcular esas posiciones. Toma solo se modifica la posición Y del texto, pero hay una oportunidad de trabajar en en 3D es que podemos empujar y extraer el texto en la dirección z, así como rotarlo alrededor de los ejes x, y y z.

Conclusión

El texto y el diseño en WebVR tienen un largo camino por recorrer antes de ser tan fáciles y tan simples más usados como HTML y CSS. Pero existen soluciones de trabajo y puedes hacer mucho más en WebVR que en una página web HTML tradicional. WebVR existe en la actualidad. Es probable que mañana haya mejores herramientas. Hasta entonces, pruébalo y experimento. Desarrollar sin un framework omnipresente lleva a una proyectos, y eso es emocionante.