Comienza a usar Three.js

Introducción

Usé Three.js para algunos de mis experimentos y hace un gran trabajo a la hora de abstraer los dolores de cabeza de comenzar a usar 3D en el navegador. Con él, puedes crear cámaras, objetos, luces, materiales y mucho más, y puedes elegir el renderizador, lo que significa que puedes decidir si quieres que tu escena se dibuje con el lienzo de HTML 5, WebGL o SVG. Y como es código abierto, incluso podrías participar en el proyecto. Pero ahora, me enfocaré en lo que aprendí jugando con él como motor y te contaré algunos de los conceptos básicos.

A pesar de lo genial que es Three.js, puede haber momentos en los que tengas dificultades. Por lo general, deberás dedicar bastante tiempo a los ejemplos, la ingeniería inversa y (en mi caso, sin duda) la búsqueda de funciones específicas y, ocasionalmente, hacer preguntas a través de GitHub. Por cierto, si tienes preguntas, descubrí que Mr. doob y AlteredQualia son muy útiles.

1. Conceptos básicos

Supondré que tienes al menos un conocimiento básico de 3D y un nivel de competencia razonable con JavaScript. Si no es así, te recomendamos que aprendas un poco antes de intentar jugar con este tipo de contenido, ya que puede ser un poco confuso.

En nuestro mundo 3D, tendremos algunos de los siguientes elementos, que te guiaré a través del proceso de creación:

  1. Una escena
  2. Un renderizador
  3. Una cámara
  4. Uno o dos objetos (con materiales)

Por supuesto, puedes hacer cosas interesantes, y espero que lo hagas y comiences a experimentar con el 3D en tu navegador.

2. Asistencia

Ten en cuenta que la compatibilidad con los navegadores es limitada. En mi experiencia, el navegador Chrome de Google es el mejor navegador con el que trabajar en términos de los renderizadores compatibles y la velocidad del motor de JavaScript subyacente. Chrome admite Canvas, WebGL y SVG, y es increíblemente rápido. Firefox ocupa el segundo lugar, con el advenimiento de la versión 4. Su motor JavaScript parece ser un poco más lento que el de Chrome, pero, una vez más, su compatibilidad con las tecnologías de renderización es excelente. Opera y Safari están en proceso de agregar compatibilidad con WebGL, pero sus versiones actuales solo admiten lienzo. Internet Explorer (versión 9 y posteriores) solo admite la renderización de lienzo, y no he escuchado que Microsoft planee agregar capacidades de WebGL.

3. Crea un escenario

Supongamos que elegiste un navegador que admite todas las tecnologías de renderización y que deseas renderizar con lienzo o WebGL, ya que son las opciones más estándar. Canvas es más compatible que WebGL, pero vale la pena señalar que WebGL se ejecuta en la GPU de tu tarjeta gráfica, lo que significa que tu CPU puede concentrarse en otras tareas que no son de renderización, como cualquier interacción física o del usuario que intentes realizar.

Independientemente del renderizador que elijas, debes tener en cuenta que el código JavaScript se deberá optimizar para mejorar el rendimiento. La realidad 3D no es una tarea liviana para un navegador (y es increíble que incluso sea posible), así que ten cuidado de comprender dónde se encuentran los cuellos de botella en tu código y quítalos si puedes.

Dicho esto, y suponiendo que descargaste e incluiste three.js en tu archivo HTML, ¿cómo configurarías una escena? Para ello, puedes escribir lo siguiente:

// set the scene size
var WIDTH = 400,
HEIGHT = 300;

// set some camera attributes
var VIEW_ANGLE = 45,
ASPECT = WIDTH / HEIGHT,
NEAR = 0.1,
FAR = 10000;

// get the DOM element to attach to
// - assume we've got jQuery to hand
var $container = $('#container');

// create a WebGL renderer, camera
// and a scene
var renderer = new THREE.WebGLRenderer();
var camera = new THREE.PerspectiveCamera(
                VIEW_ANGLE,
                ASPECT,
                NEAR,
                FAR );

var scene = new THREE.Scene();

// the camera starts at 0,0,0 so pull it back
camera.position.z = 300;

// start the renderer
renderer.setSize(WIDTH, HEIGHT);

// attach the render-supplied DOM element
$container.append(renderer.domElement);

No es tan complicado.

4. Cómo crear una malla

Por lo tanto, tenemos una escena, una cámara y un renderizador (opté por uno de WebGL en mi código de muestra), pero no tenemos nada para dibujar. Three.js incluye compatibilidad para cargar algunos tipos de archivos estándar diferentes, lo que es excelente si exportas modelos de Blender, Maya, Cinema4D o cualquier otro. Para mantener la simplicidad (después de todo, se trata de comenzar), Hablaré de las primitivas. Las primitivas son mallas geométricas, relativamente básicas, como esferas, planos, cubos y cilindros. Three.js te permite crear estos tipos de primitivas con facilidad:

// set up the sphere vars
var radius = 50, segments = 16, rings = 16;

// create a new mesh with sphere geometry -
// we will cover the sphereMaterial next!
var sphere = new THREE.Mesh(
new THREE.SphereGeometry(radius,
segments,
rings),

sphereMaterial);

// add the sphere to the scene
scene.add(sphere);

Todo bien, pero ¿qué hay del material de la esfera? En el código, usamos una variable sphereMaterial, pero aún no la definimos. Primero, debemos hablar de los materiales con un poco más de detalle.

5. Materiales

Sin duda, esta es una de las partes más útiles de Three.js. Te proporciona una serie de materiales comunes (y muy útiles) para aplicar a tus mallas:

  1. "Básica", lo que significa que se renderiza sin iluminación.
  2. Lambert
  3. Phong

Hay más, pero, nuevamente, por motivos de simplicidad, te dejaré descubrirlos por tu cuenta. En el caso de WebGL, estos materiales pueden ser un gran apoyo. ¿Por qué? Bueno, porque en WebGL debes escribir sombreadores para todo lo que se renderiza. Los sombreadores son un tema muy amplio en sí mismos, pero, en resumen, se escriben en GLSL (OpenGL Shader Language), que le indica a la GPU cómo debe verse algo. Esto significa que debes imitar las matemáticas de la iluminación, la reflexión, etcétera. Puede complicarse muy rápido. Gracias a Three.js, no tienes que hacerlo si no quieres, ya que lo abstrae por ti. Sin embargo, si quieres escribir sombreadores, también puedes hacerlo con un MeshShaderMaterial, por lo que es una configuración flexible.

Por ahora, apliquemos un material Lambert a la esfera:

// create the sphere's material
var sphereMaterial = new THREE.MeshLambertMaterial(
{
// a gorgeous red.
color: 0xCC0000
});

También vale la pena señalar que hay otras propiedades que puedes especificar cuando creas un material además del color, como mapas de suavizado o de entorno. Debes consultar la página de la Wiki para ver las diferentes propiedades que puedes configurar en los materiales y, de hecho, en cualquier objeto que te proporcione el motor. Recientemente, también surgió threejs.org, que ofrece una vista más atractiva de la API.

6. ¡Luces!

Si renderizaras la escena en este momento, verías un círculo rojo. Aunque tenemos un material Lambert aplicado, no hay luz en la escena, por lo que, de forma predeterminada, Three.js volverá a una luz ambiental completa, que es lo mismo que el color plano. Corrijamos eso con un simple punto de luz:

// create a point light
var pointLight = new THREE.PointLight( 0xFFFFFF );

// set its position
pointLight.position.x = 10;
pointLight.position.y = 50;
pointLight.position.z = 130;

// add to the scene
scene.add(pointLight);

7. Renderizar

Ahora tenemos todo configurado para renderizar, de manera notable. Pero, en realidad, debemos hacer lo siguiente:

// draw!
renderer.render(scene, camera);

Sin embargo, es probable que quieras renderizar más de una vez, por lo que, si vas a hacer un bucle, debes usar requestAnimationFrame. Es, con mucho, la forma más inteligente de controlar la animación en el navegador. Aún no es compatible por completo, por lo que te recomiendo que mires el empalmador de Paul Irish.

8. Propiedades comunes de objetos

Si te tomas el tiempo de revisar el código de Three.js, verás que muchos objetos “heredan” de Object3D. Este es un objeto base que contiene algunas propiedades muy útiles, como la información de posición, rotación y escala. En particular, nuestra esfera es una malla que hereda de Object3D, a la que agrega sus propias propiedades: geometría y materiales. ¿Por qué menciono esto? Es poco probable que quieras tener una esfera en la pantalla que no haga nada, y estas propiedades vale la pena investigarlas, ya que te permiten manipular los detalles subyacentes de las mallas y los materiales sobre la marcha.

// sphere geometry
sphere.geometry

// which contains the vertices and faces
sphere.geometry.vertices // an array
sphere.geometry.faces // also an array

// its position
sphere.position // has x, y and z properties
sphere.rotation // same
sphere.scale // ... same

9. Dirty Little Secrets

Solo quería señalar rápidamente un problema con Three.js, que es que, si modificas, por ejemplo, los vértices de una malla, notarás en el bucle de renderización que no cambia nada. ¿Por qué? Bueno, porque Three.js (hasta donde sé) almacena en caché los datos de una malla como una optimización. Lo que realmente debes hacer es marcar a Three.js que algo cambió para que pueda volver a calcular lo que sea necesario. Para ello, sigue estos pasos:

// changes to the vertices
sphere.geometry.__dirtyVertices = true;

// changes to the normals
sphere.geometry.__dirtyNormals = true;

Una vez más, hay más, pero los dos que encontré son los más útiles. Por supuesto, solo debes marcar los elementos que cambiaron para evitar cálculos innecesarios.

Conclusión

Espero que esta breve introducción a Three.js te haya resultado útil. No hay nada como ensuciarse las manos y probar algo, y te lo recomiendo mucho. El 3D que se ejecuta de forma nativa en el navegador es muy divertido, y usar un motor como Three.js te quita muchos dolores de cabeza y te permite crear contenido muy interesante. Para ayudarte un poco, uní el código fuente en este artículo del lab, de modo que puedas usarlo como referencia. Si te gustó, avísame por Twitter. ¡Siempre es bueno saludar!