Se você já usou a API WebXR Device, você já está quase lá.
A API WebXR Device foi lançada no outono passado no Chrome 79. Como mencionado, a implementação da API no Chrome está em desenvolvimento. O Chrome tem o prazer de anunciar que parte do trabalho foi concluído. No Chrome 81, dois novos recursos foram lançados:
Este artigo aborda a realidade aumentada. Se você já usou a API WebXR Device, vai ficar feliz em saber que há poucas novidades para aprender. A entrada em uma sessão do WebXR é basicamente a mesma. A execução de um loop de frame é basicamente a mesma. As diferenças estão nas configurações que permitem que o conteúdo seja mostrado de maneira adequada para a realidade aumentada. Se você não conhece os conceitos básicos do WebXR, leia minhas postagens anteriores sobre a API WebXR Device ou, pelo menos, conheça os tópicos abordados nelas. Você precisa saber como solicitar e entrar em uma sessão e como executar um loop de frame.
Para informações sobre testes de hit, consulte o artigo complementar Posicionar objetos virtuais em visualizações do mundo real. O código deste artigo é baseado no exemplo de sessão de RA imersiva (demonstração fonte) do exemplos da API WebXR Device do Grupo de Trabalho da Web imersiva.
Antes de mergulhar no código, use o exemplo de sessão de RA imersiva pelo menos uma vez. Você vai precisar de um smartphone Android moderno com o Chrome 81 ou versão mais recente.
Qual é a utilidade disso?
A realidade aumentada será um recurso valioso para muitas páginas da Web existentes ou novas, permitindo a implementação de casos de uso de RA sem sair do navegador. Por exemplo, ele pode ajudar as pessoas a aprender em sites educacionais e permitir que compradores em potencial visualizem objetos na casa enquanto fazem compras.
Considere o segundo caso de uso. Imagine como seria colocar uma representação em tamanho real de um objeto virtual em uma cena real. Depois de colocada, a imagem permanece na superfície selecionada, tem o tamanho que teria se o item real estivesse nessa superfície e permite que o usuário se mova para perto ou afaste-se dela. Isso oferece aos espectadores uma compreensão mais profunda do objeto do que é possível com uma imagem bidimensional.
Estou me adiantando um pouco. Para fazer o que eu descrevi, você precisa da funcionalidade de RA e de algumas formas de detectar superfícies. Este artigo aborda a primeira opção. O artigo em anexo na API WebXR Hit Test (link acima) abrange o último.
Como solicitar uma sessão
Solicitar uma sessão é muito parecido com o que você já viu antes. Primeiro, descubra
se o tipo de sessão que você quer está disponível no dispositivo atual chamando
xr.isSessionSupported()
. Em vez de solicitar 'immersive-vr'
como antes,
solicite 'immersive-ar'
.
if (navigator.xr) {
const supported = await navigator.xr.isSessionSupported('immersive-ar');
if (supported) {
xrButton.addEventListener('click', onButtonClicked);
xrButton.textContent = 'Enter AR';
xrButton.enabled = supported; // supported is Boolean
}
}
Como antes, isso ativa um botão "Entrar na RA". Quando o usuário clicar nele, chame
xr.requestSession()
, transmitindo também 'immersive-ar'
.
let xrSession = null;
function onButtonClicked() {
if (!xrSession) {
navigator.xr.requestSession('immersive-ar')
.then((session) => {
xrSession = session;
xrSession.isImmersive = true;
xrButton.textContent = 'Exit AR';
onSessionStarted(xrSession);
});
} else {
xrSession.end();
}
}
Uma propriedade de conveniência
Você provavelmente notou que destaquei duas linhas no último exemplo de código.
O objeto XRSession
parece ter uma propriedade chamada isImmersive
. Essa
é uma propriedade de conveniência que eu mesmo criei e não faz parte da especificação. Vou
usá-la mais tarde para decidir o que mostrar ao espectador. Por que essa
propriedade não faz parte da API? Como seu app pode precisar rastrear essa propriedade
de maneira diferente, os autores da especificação decidiram manter a API limpa.
Como entrar em uma sessão
Lembre-se de como onSessionStarted()
era no meu artigo anterior:
function onSessionStarted(xrSession) {
xrSession.addEventListener('end', onSessionEnded);
let canvas = document.createElement('canvas');
gl = canvas.getContext('webgl', { xrCompatible: true });
xrSession.updateRenderState({
baseLayer: new XRWebGLLayer(session, gl)
});
xrSession.requestReferenceSpace('local-floor')
.then((refSpace) => {
xrRefSpace = refSpace;
xrSession.requestAnimationFrame(onXRFrame);
});
}
Preciso adicionar algumas coisas para renderizar a realidade aumentada. Desative o plano de fundo. Primeiro, vou determinar se preciso do plano de fundo. Este é o primeiro lugar em que vou usar minha propriedade de conveniência.
function onSessionStarted(xrSession) {
xrSession.addEventListener('end', onSessionEnded);
if (session.isImmersive) {
removeBackground();
}
let canvas = document.createElement('canvas');
gl = canvas.getContext('webgl', { xrCompatible: true });
xrSession.updateRenderState({
baseLayer: new XRWebGLLayer(session, gl)
});
refSpaceType = xrSession.isImmersive ? 'local' : 'viewer';
xrSession.requestReferenceSpace(refSpaceType).then((refSpace) => {
xrSession.requestAnimationFrame(onXRFrame);
});
}
Espaços de referência
Meus artigos anteriores leram os espaços de referência. O exemplo que estou descrevendo usa dois deles, então é hora de corrigir essa omissão.
Um espaço de referência descreve a relação entre o mundo virtual e o ambiente físico do usuário. Para isso, ele:
- Especificação da origem do sistema de coordenadas usado para expressar posições no mundo virtual.
- Especifica se o usuário precisa se mover dentro desse sistema de coordenadas.
- Se esse sistema de coordenadas tem limites pré-estabelecidos. Os exemplos mostrados aqui não usam sistemas de coordenadas com limites pré-estabelecidos.
Para todos os espaços de referência, a coordenada X expressa esquerda e direita, a Y expressa para cima e para baixo, e a Z expressa para frente e para trás. Os valores positivos são direita, para cima e para trás, respectivamente.
As coordenadas retornadas por XRFrame.getViewerPose()
dependem do
tipo de espaço de referência solicitado.
Vamos falar mais sobre isso quando chegarmos ao loop de frames. Agora precisamos selecionar um
tipo de referência adequado para a realidade aumentada. Isso usa minha propriedade de conveniência.
let refSpaceType
function onSessionStarted(xrSession) {
xrSession.addEventListener('end', onSessionEnded);
if (session.isImmersive) {
removeBackground();
}
let canvas = document.createElement('canvas');
gl = canvas.getContext('webgl', { xrCompatible: true });
xrSession.updateRenderState({
baseLayer: new XRWebGLLayer(session, gl)
});
refSpaceType = xrSession.isImmersive ? 'local' : 'viewer';
xrSession.requestReferenceSpace(refSpaceType).then((refSpace) => {
xrSession.requestAnimationFrame(onXRFrame);
});
}
Se você acessou o Exemplo de sessão de RA imersiva, vai perceber que, inicialmente, a cena é estática, e não de realidade aumentada. Você pode arrastar e deslizar com o dedo para se mover pela cena. Se você clicar em "START AR", o plano de fundo será removido e você poderá se mover pela cena movendo o dispositivo. Os modos usam diferentes tipos de espaço de referência. O texto destacado acima mostra como isso é selecionado. Ele usa os seguintes tipos de referência:
local
: a origem está na posição do espectador no momento da criação da
sessão. Isso significa que a experiência não tem necessariamente um piso bem definido
e a posição exata da origem pode variar de acordo com a plataforma. Embora não
existam limites predefinidos para o espaço, espera-se que o conteúdo possa
ser visualizado sem nenhum movimento além da rotação. Como é possível observar no nosso exemplo de RA, é possível movimentar-se dentro do espaço.
viewer
: usado com mais frequência para conteúdo apresentado inline na página, esse
espaço segue o dispositivo de visualização. Quando transmitido para getViewerPose, ele não fornece
rastreamento e, portanto, sempre informa uma pose na origem, a menos que o aplicativo
a modifique com XRReferenceSpace.getOffsetReferenceSpace()
. No exemplo, ele é usado
para ativar a movimentação baseada em toque da câmera.
Como executar um loop de frame
Conceitualmente, nada muda do que fiz na sessão de RV descrita nos artigos
anteriores. Transmita o tipo de espaço de referência para XRFrame.getViewerPose()
.
O XRViewerPose
retornado será para o tipo de espaço de referência atual. O uso de
viewer
como padrão permite que uma página mostre visualizações de conteúdo antes que o consentimento
do usuário seja solicitado para RA ou RV. Isso ilustra um ponto importante: o
conteúdo inline usa o mesmo loop de frame que o conteúdo imersivo, reduzindo
a quantidade de código que precisa ser mantido.
function onXRFrame(hrTime, xrFrame) {
let xrSession = xrFrame.session;
xrSession.requestAnimationFrame(onXRFrame);
let xrViewerPose = xrFrame.getViewerPose(refSpaceType);
if (xrViewerPose) {
// Render based on the pose.
}
}
Conclusão
Esta série de artigos aborda apenas os conceitos básicos da implementação de conteúdo imersivo na Web. Muitos outros recursos e casos de uso são apresentados pelas amostras da API WebXR Device do Grupo de trabalho da Web imersiva. Também publicamos um artigo de teste de hit (link em inglês), que explica uma API para detectar superfícies e colocar itens virtuais em uma visualização de câmera real. Confira esses artigos e acompanhe o blog da web.dev para mais artigos no ano que vem.
Foto de David Grandmougin no Unsplash