Cree una experiencia audiovisual de realidad virtual con A-Frame y Tone.js

Hola Habr! Les presento la traducción del artículo "Creación de una experiencia audiovisual / visual de realidad virtual en la Web con A-Frame y Tone.js" de Sean Sullivan.

Realidad de Firefox en Oculus Go

A-Frame es un marco para crear realidad virtual en la web. Usando solo un enlace, cualquier persona con un casco VR o un teléfono inteligente habilitado para VR puede sumergirse en el espacio 3D. Tone.js es una biblioteca de JavaScript para crear sonidos. Veamos qué pasa si se combinan.

Para empezar, crearemos un entorno, con A-frame es muy simple. Usando solo HTML básico, podemos crear un espacio 3D completo, para esto necesitamos un componente de entorno de marco . A continuación se muestra el marcado básico para nuestros propósitos.

<!DOCTYPE html>
<html>
<head>
  <title>Basic Scene with Environment - A-Frame</title>
  <meta name="description" content="Basic Scene with Environment - A-Frame">
  <script src="https://aframe.io/releases/1.0.4/aframe.min.js">  </script>
  <script src="https://unpkg.com/aframe-environment-component@1.1.0/dist/aframe-environment-component.min.js"></script>
</head>
<body>
  <a-scene environment="preset: starry">
    <a-camera>
      <a-entity cursor="fuse: true; fuseTimeout: 500"
            position="0 0 -1"
            geometry="primitive: ring; radiusInner: 0.02; radiusOuter: 0.03"
            material="color: black; shader: flat">
      </a-entity>    
    </a-camera>
  </a-scene>
</body>
</html>

Presta atención al elemento:
<a-entity cursor>
Está dentro de nuestra celda. Un poco más tarde, él te permitirá comunicarte con nuestro sintetizador. Pero antes de comenzar, debe asegurarse de que el proyecto se cargue correctamente.

Al abrir la página, debería ver un cielo tridimensional, estrellas y una cuadrícula en la tierra. Todo esto fue creado por aframe-environment-component cuando definimos el entorno:

<a-scene environment=”preset: starry”>

Si lo desea, se puede cambiar el entorno, simplemente agregue otra plantilla. Al momento de escribir este artículo, hay 16 plantillas de entorno diferentes de su elección.

Cielo estrellado

Me gusta que nuestro sintetizador esté en el espacio, el espacio es genial. Hagamos que nuestro medio ambiente se parezca más a la superficie de un planeta.

Primero, eliminaremos la cuadrícula y agregaremos la textura de la tierra, cambiando:

<a-scene environment="preset: starry">

sobre el

<a-scene environment="preset: starry; grid: none; groundTexture: walkernoise">

Al abrir la página ahora, veremos que nuestro planeta aún está demasiado oscuro para ver algo en la tierra. Solucione esto agregando una fuente de luz a nuestra escena.

<a-entity light="type: ambient; color: #CCC"></a-entity>

Con ella, la escena debería verse así:

Escena con luz

ahora que hemos descubierto los alrededores, comencemos a desarrollar un sintetizador.

Creación de componentes


A-Frame se basa en un sistema de componente de entidad . Le permite crear componentes y agregarlos a entidades en nuestra escena. Creemos

un archivo synth.js para nuestro componente.

AFRAME.registerComponent('synth', {
  schema: {
    //   .
  },

  init: function () {
    //     .
  },

  update: function () {
    //     .
  },

  remove: function () {
    //       .
  },
  tick: function (time, timeDelta) {
    //     ()  .
  }
});

Como puede ver, los métodos de ciclo de vida están integrados en A-Frame, lo que facilita agregar interactividad a nuestros proyectos WebVR. La base del componente está lista, echemos un vistazo al proceso de creación de un sintetizador con Tone.js.

Tone.js


Tone.js: un marco para crear música interactiva en un navegador, es un contenedor para la API de audio web. Crear un sintetizador con tone.js es simple: solo escriba una línea:

var synth = new Tone.Synth().toMaster()

Pero crearemos un oscilador y agregaremos varios parámetros para simplificar aún más la personalización:

const synth = new Tone.Synth({
  volume: -15, // -15dB
  oscillator: {
    type: 'triangle' //   -  ""
  },
  envelope: {
    attack: 0.05, //  -  
    release: 2 //   - 
  }
}).toMaster()

Agregue este código directamente encima de nuestro componente en el archivo synth.js . Ahora tenemos un sintetizador, pero necesitamos proporcionar a nuestro componente una forma de acceder a él. ¿Recuerdas el <cursor de una entidad> que agregamos a la cámara? Este cursor tiene un parámetro fusible = "verdadero" . Esto nos permitirá realizar un seguimiento de cómo interactúa el cursor con las entidades. Agregue un EventListener al componente para fusible.

Crearemos un EventListener en el método init del ciclo de vida y crearemos un nuevo método llamado trigger que dispara Tone.js.

...
init: function () {
  //  EventListener     fuse
  this.el.addEventListener('fusing', this.trigger.bind(this))
},
//  ,  tone.js
trigger: function () {
  //tone.js ,     
  synth.triggerAttackRelease(this.data.note, this.data.duration)
},
...

Agregue un componente de sintetizador a la escena.


Creamos el componente, es hora de agregarlo a la escena A-Frame.

Para comenzar, agregué Tone.js y un componente de sintetizador a nuestro marcado. Preste atención al orden de los archivos de conexión: synth.js se carga después de Tone.js.

...
<script src="https://unpkg.com/tone@13.8.25/build/Tone.js"></script>
<script src="synth.js"></script>
</head>
...

También necesitamos varias entidades a las que adjuntaremos el componente. Agregue algunas formas estándar de marco en A para usar en nuestra escena.

<a-scene>
...
<a-box synth="note: E4" position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9"></a-box>
<a-sphere synth="note: C4" position="0 1.25 -5" radius="1.25" color="#EF2D5E"></a-sphere>
<a-cylinder synth="note: G4" position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D"></a-cylinder>
...

Tenga en cuenta el atributo de sintetizador . Este es el componente que creamos. 'Sintetizador' es el nombre con el que nos registramos
AFRAME.registerComponent ('synth', {})
y declaramos "nota" en el diagrama del componente. También hay una propiedad de "duración": podemos usarla para cambiar la duración de una nota. Por ejemplo:
sintetizador = "nota: E4; duración: 8n »
tocará 1/8 de toda la nota, no el estándar 1/4.

Ahora, después de abrir la escena en el navegador, veremos nuestras figuras, y cuando pase el mouse sobre ellas, se debe reproducir la nota de nuestro componente de sintetizador.

Figuras musicales

Uso del controlador Oculus Go


Ahora nuestra escena funciona así: el cursor está fijo en el centro de la pantalla. En los cascos VR, esto se llama control "visual". Al girar la cabeza, el cursor se moverá en la dirección del movimiento del usuario. Esta es una experiencia absolutamente normal y funciona bien para muchos proyectos. Pero, ¿qué pasa si queremos controlar el sintetizador usando un controlador VR? Mover los brazos y hacer que la música suene divertida, así que cambiemos nuestra escena para usar el controlador Oculus Go.

Primero, agregue algunas entidades a nuestra escena: el controlador y el emisor de rayos.

...
<a-entity oculus-go-controls>
<a-entity laser-controls raycaster="far: 200; interval: 100"></a-entity>
...

Aquí tenemos nuestra propia entidad para controlar Oculus Go, así como una para raycaster, que se ejecutará cada 100 milisegundos.

Ahora modifiquemos el componente del sintetizador para controlar Oculus. Hacemos esto agregando raycaster dependiendo de nuestro componente.

AFRAME.registerComponent('synth', {
  dependencies: ['raycaster'],
...

Luego, en el método init , cambie EventListener; debería rastrear el evento:
Raycaster-intersection


init: function () {
  this.el.addEventListener('raycaster-intersection', this.trigger.bind(this))
},
...

El comienzo de la escena en Oculus Go ahora debería mostrar su controlador, y el control láser debería comenzar a tocar las notas del sintetizador cuando pasa el cursor sobre las figuras.

Oculus go

Si desea ver más de cerca el proyecto, puede ejecutarlo y ver el código fuente aquí: glitch.com/~space-synth-vr

En custodia


Ahora tenemos una escena simple con un sintetizador de realidad virtual y hay una gran cantidad de oportunidades para mejorarlo. Podemos agregar más objetos para la interacción, más sintetizadores y efectos para el componente. Podemos animar objetos basados ​​en algunos eventos. A medida que crece la escena, debes pensar en el rendimiento. Afortunadamente, A-Frame tiene muchas características integradas que pueden ayudar con este problema.

Aquí hay algunos enlaces útiles Raycaster

Components Interaction and Control Código fuente del proyecto Tone.js Gracias por leer.






All Articles