Renderização de texto na WebVR

No detalhe

Acessar o site

O (https://with.in/) inclui uma plataforma para contar histórias em realidade virtual. Então, quando a equipe ouviu falar da WebVR em desde 2015, nos interessamos imediatamente pelo potencial dele. Hoje, esse interesse em um subdomínio exclusivo da nossa plataforma da Web, https://vr.with.in/. Qualquer pessoa com um navegador compatível com RV pode acesse o site, clique em um botão e use um fone de ouvido para ficar imerso na nossa portfólio de filmes em RV.

Atualmente, isso inclui o Chrome no Daydream View, entre outros. Para informações no seu dispositivo e óculos de realidade virtual confira https://webvr.info/.

Assim como outros ambientes de renderização específicos de realidade virtual, a Web depende predominantemente de uma representação tridimensional de uma cena. Isso a cena tem uma câmera, sua perspectiva e qualquer número de objetos. Para ajudar a gerenciar cena, câmera e objetos, usamos uma biblioteca chamada Three.js, que aproveita o elemento <canvas> para gerar renderização na GPU do computador. Existem muitos complementos úteis do Three.js para tornar sua cena visível na WebVR. As duas principais são THREE.VREffect para criar uma janela de visualização para cada olho e THREE.VRControls para traduzir a perspectiva (por exemplo, a rotação e a posição do de cabeça) de forma convincente em sua cena. Há muitos exemplos de como implementar isso. Consulte o Exemplos da WebVR do three.js (em inglês) para saber como começar.

Conforme avançamos na WebVR, encontramos um problema. Se procurarmos no conteúdo da web, o texto é parte integrante dele. A maioria do nosso conteúdo é baseado em vídeo. Se você acessar No site: um texto que envolve o conteúdo. a interface do usuário e informações adicionais sobre um filme ou filmes relacionados são construídos com texto. Além disso, todo esse texto é criado no DOM. Nossos As análises detalhadas da WebVR e https://vr.with.in/ estão disponíveis <canvas>

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

Quais são minhas opções?

Felizmente, ainda há muito trabalho a ser feito para tornar isso possível. Na verdade, em nossa pesquisa encontramos várias formas eficazes de renderizar texto tridimensional em um elemento <canvas>. Abaixo está uma matriz com algumas das que encontramos marcado com prós e contras para cada:

Independente de resolução Atributos tipográficos Desempenho Facilidade de implementação
Texto em tela 2D Sim Sim Sim
Texto vetorial triangular Sim Sim
Texto 3D deslocado Sim
Texto de bitmap do campo de distância assinada Sim Sim Sim

Nossa decisão: fonte de bitmap SDF

A tela 2D com ctx.fillText() pode ajustar o texto, o espaçamento entre letras e as linhas mas o estouro é cortado, e o texto fica desfocado se você aumentar o zoom longe. Você pode aumentar o tamanho da textura da tela, mas pode atingir uma parte superior o limite de tamanho ou desempenho da textura pode ser afetado se a textura for muito grande.

O texto 3D deslocado é basicamente o mesmo que texto vetorial triangulado, mas com profundidade e possivelmente um chanfro, para que tenha ao menos duas vezes mais geometria. Qualquer um dos podem funcionar em pequenas doses para títulos ou logotipos, mas não teriam um desempenho bom para grandes quantidades de texto e nenhum dos dois tem características tipográficas.

Fonte para fluxo de trabalho de bitmap do SDF
Fluxo de trabalho de fonte para bitmap em SDF

As fontes de bitmap usam um quad (dois triângulos) por caractere, então usam menos geometria e têm um desempenho melhor vetores triangulados. Eles ainda são rasterizados, porque usam um sprite de mapa de textura, mas com um SDF. Eles não dependem da resolução e são melhores do que um sombreador 2D textura da tela. Matt DesLauriers três-bmfont-text também inclui recursos tipográficos confiáveis para ajustar o texto, espaçamento entre letras, altura e alinhamento da linha. O estouro não é cortado. Fonte o tamanho é controlado por escala. Escolhemos essa rota porque ela nos deu melhores opções de design sem perder o desempenho. Infelizmente, não foi tão fáceis de implementar. Então, passaremos pelas etapas na esperança de ajudar outros desenvolvedores que trabalham com a WebVR.

1. Gerar uma fonte de bitmap (.png + .fnt)

Interface Hiero
Interface Hiero
Saída hiero (arquivo PNG e .fnt em bitmap) Saída hiero (arquivo PNG e .fnt em bitmap)
Saída hiero (arquivo PNG e .fnt em bitmap)

O Hiero é um empacotamento de fontes de bitmap que é executada com Java. A documentação do Hiero não explica como executá-lo sem precisar de um processo de compilação complicado. Primeiro, instale o Java se que você ainda não fez. Então, se clicar duas vezes no runnable-hiero.jar não abra o Hiero, tente executá-lo com este comando no console:

java -jar runnable-hiero.jar

Quando o Hiero estiver em execução, abra uma fonte para computador .ttf ou .otf, insira caracteres que deseja incluir, altere a renderização para Java a fim de ativar os efeitos, aumente o tamanho para que seus caracteres preencham todo o quadrado do cache de glifo, adicionar um efeito de campo de distância, ajustar a escala e a propagação do campo de distância. A escala é como uma resolução. Quanto maior ela for, menos borrada ela será, mas mais tempo levará para o Hiero renderizar a visualização. Depois, salve fonte de bitmap. Ele gera uma fonte de bitmap que consiste em uma imagem .png e um Arquivo de descrição da fonte AngelCode .fnt.

2. Converter AngelCode em JSON

Agora que a fonte de bitmap foi gerada, temos que carregá-la em nosso app JavaScript com Matt DesLauriers' pacote npm load-bmfont.

Nós poderíamos usar um navegador para o load-bmfont e usá-lo no front-end, mas em vez disso vamos executar load-bmfont.js com Nó para converter e salvar o AngelCode .fnt do Hiero em um Arquivo.json:

npm install
node load-bmfont.js
Exemplo de saída JSON
Exemplo de JSON de saída

Agora podemos ignorar load-bmfont e apenas fazer uma solicitação XHR (XMLHttpRequest) no arquivo de fontes .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. Navegador para texto de três bmfonts

Assim que a fonte estiver carregada, o texto de três bmfonts de Matt cuidará da descansar. Como não estamos usando o Node para nosso próprio app, vamos browserify (link em inglês) three-bmfont-text.js em um three-bmfont-text-bundle.js utilizável

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

4. Sombreador de SDF

Ative os controles deslizantes afwidth e threshold vr.with.in/archive/text-sdf-bitmap/ para conferir o efeito do sombreador de campo de distância assinado.

5. Uso

Para facilitar, criei um Classe wrapper TextBitmap para o texto de três bmfonts.

Text-sdf-bitmap em ação
Text-sdf-bitmap em ação
<script src="three-bmfont-text-bundle.js"></script>
<script src="sdf-shader.js"></script>
<script src="text-bitmap.js"></script>

Crie uma solicitação XHR para o arquivo de fonte .json e crie um objeto de texto no callback:

var bmtext = new TextBitmap({ options });

Para alterar o texto:

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

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

O .png da fonte de bitmap é carregado com THREE.TextureLoader em text-bitmap.js.

O TextBitmap também inclui uma hitbox invisível para a interação do raycast do three.js. por meio de mouse, câmera ou controladores de movimento monitorados manualmente, como Oculus Touch ou os controles do Vive. O tamanho da hitbox é atualizado automaticamente quando você altera o texto .

Bmtext.group é adicionado à cena three.js. Se você precisar acessar os filhos / Object3D, o gráfico de cena para o texto ficará assim:

Diagrama do sistema de arquivos

6. Descompactar o JSON e modificar xoffsets

No gif de texto

Caso seu kerning esteja deslocado, pode ser necessário editar os xoffsets no json. Colar o JSON em Jsbeautifier.org para receber versão não reduzida do arquivo.

O xoffset é essencialmente kerning global para um caractere. Kerning é para casais caracteres específicos que aparecem lado a lado. Os valores padrão na matriz de kerning não faz diferença, e seria muito tedioso editar para que você possa esvaziar a matriz para diminuir o tamanho do arquivo do JSON. Depois, editar os deslocamentos de x para kerning.

Primeiro, você terá que descobrir quais caracteres vão com qual ID de caractere na JSON Em three-bmfont-text-bundle.js, insira console.log depois da linha 240:

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

Depois, digite no campo de texto dat.gui https://vr.with.in/archive/text-sdf-bitmap/ e consulte o console para encontrar o ID de um caractere.

Por exemplo, em nossa fonte de bitmap, "j" está consistentemente muito longe para a direita. Seu o ID do caractere é 106. Então, encontre "id": 106 no JSON e mude o xoffset de -1. a -10.

7. Layout

Se você tem vários blocos de texto e quer que ele flua de cima para baixo, como HTML, tudo precisa ser posicionado manualmente, semelhante ao posicionamento absoluto cada elemento DOM com CSS. Você consegue imaginar como fazer isso no CSS?

    * { position: absolute; }

É assim que o layout de texto em 3D é. Na visualização de detalhes: título, autor, descrição e duração são um novo objeto TextBitmap com suas próprias estilos, cor, escala etc.:

layout 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;

Isso pressupõe que a origem local de cada grupo TextBitmap é verticalmente alinhado com o topo da malha TextBitmap (consulte centralizando em text-bitmap.js atualizar). Se você alterar o texto de qualquer um desses objetos posteriormente, e a altura desse objeto, você também terá que recalcular essas posições. Aqui, somente a posição y do texto é modificada, mas uma oportunidade de se trabalhar 3D é que podemos empurrar e puxar o texto na direção z, bem como girar em torno dos eixos x, y e z.

Conclusão

O texto e o layout na WebVR ainda precisam evoluir muito antes de se tornarem tão fáceis e amplamente usadas como HTML e CSS. Mas existem soluções de trabalho e você pode fazer muito mais na WebVR do que em uma página HTML tradicional. A WebVR existe hoje. Provavelmente haverá ferramentas melhores amanhã. Até lá, experimente e experimento. O desenvolvimento sem uma estrutura universal gera resultados projetos, e isso é empolgante.