Comienza a usar Three.js

Introducción

Usé Three.js para algunos de mis experimentos, y hace un gran trabajo para abstraer los dolores de cabeza de comenzar con 3D en el navegador. Con ella, 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 de código abierto, incluso podrías participar en el proyecto. Pero, ahora mismo, me enfocaré en lo que aprendí jugando con él como motor y te explicaré algunos de los conceptos básicos.

A pesar de lo increíble que es Three.js, puede haber momentos en los que tengas dificultades. Por lo general, tendrás que dedicar mucho tiempo a los ejemplos, la ingeniería inversa y (en mi caso, sin duda) la búsqueda de funciones específicas y, en ocasiones, hacer preguntas a través de GitHub. Por cierto, si tienes que hacer preguntas, Mr. doob y AlteredQualia son de gran ayuda.

1. Conceptos básicos

Supondremos que tienes, al menos, un conocimiento básico de 3D y un dominio razonable de JavaScript. Si no es así, puede ser útil aprender un poco antes de intentar jugar con esto, ya que puede ser un poco confuso.

En nuestro mundo en 3D, tendremos algunos de los siguientes elementos, que te guiaré para crear:

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

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

2. Asistencia

Una breve nota sobre la compatibilidad en los navegadores. En mi experiencia, el navegador Chrome de Google es el mejor para 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 le sigue de cerca, con la llegada de la versión 4. Su motor de JavaScript parece ser un poco más lento que el de Chrome, pero, de nuevo, 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 canvas. Internet Explorer (versión 9 y posteriores) solo admite la renderización de lienzo, y no hemos recibido ninguna noticia de que Microsoft planee agregar funciones de WebGL.

3. ¡A la tarima!

Supondremos que elegiste un navegador que admite todas las tecnologías de renderización y que quieres renderizar con canvas o WebGL, ya que son las opciones más estándar. Canvas tiene una compatibilidad más amplia 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 sean 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 deberá optimizarse para mejorar el rendimiento. El 3D no es una tarea liviana para un navegador (y es increíble que sea posible), así que ten cuidado de comprender dónde están 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 configuras 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 muy difícil, de verdad.

4. Crea una malla

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 genial si exportas modelos de Blender, Maya, Cinema4D o cualquier otro programa. Para que sea sencillo (después de todo, se trata de comenzar), Hablaré sobre 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é pasa con el 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. Proporciona una serie de materiales comunes (y muy útiles) para aplicar a tus mallas:

  1. "Basic", que solo significa que se renderiza "sin iluminación"
  2. Lambert
  3. Phong

Hay más, pero, para simplificar, dejaré que las descubras por tu cuenta. En el caso de WebGL, en particular, estos materiales pueden ser de gran ayuda. ¿Por qué? Porque en WebGL tienes que escribir sombreadores para todo lo que se renderiza. Los sombreadores son un tema muy amplio, pero, en resumen, se escriben en GLSL (lenguaje de sombreado de OpenGL), que le indica a la GPU cómo debe verse un elemento. Esto significa que debes imitar las matemáticas de la iluminación, el reflejo, etcétera. Puede volverse muy complicado muy rápido. Gracias a Three.js, no tienes que hacer esto 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 de 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 el suavizado o los mapas de entorno. Deberías consultar la página de Wiki para conocer las distintas propiedades que puedes establecer en los materiales y, de hecho, en cualquier objeto que proporcione el motor. También surgió recientemente threejs.org, que ofrece una vista más atractiva de la API.

6. ¡Luces!

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

// 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, sorprendentemente, tenemos todo configurado para renderizar. Pero, en realidad, debemos seguir adelante y hacer precisamente eso:

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

Sin embargo, es probable que quieras renderizar más de una vez, por lo que, si vas a realizar un bucle, deberías usar requestAnimationFrame; es, por mucho, la forma más inteligente de controlar la animación en el navegador. Aún no es totalmente compatible, por lo que te recomiendo que eches un vistazo al shim de Paul Irish.

8. Propiedades comunes de los 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 vale la pena investigar estas propiedades, 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. Secretos sucios

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

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

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

Hay más, pero estos dos son los más útiles. Obviamente, 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 poner manos a la obra y probar algo, y lo recomiendo encarecidamente. La ejecución de 3D de forma nativa en el navegador es muy divertida, y el uso de un motor como Three.js te quita muchos dolores de cabeza y te permite crear cosas realmente geniales. Para ayudarte un poco, incluí el código fuente en este artículo del lab, de modo que puedas usarlo como referencia. Si te gustó este video, dímelo en Twitter. Siempre es bueno saludar.