Comienza a usar Three.js

Introducción

Usé Three.js para algunos de mis experimentos y hace un gran trabajo al evitar las molestias de comenzar a trabajar con 3D en el navegador. Con él, puedes crear cámaras, objetos, luces, materiales y mucho más, y puedes elegir un procesador, lo que significa que puedes decidir si quieres que tu escena se dibuje con el lienzo de HTML5, WebGL o SVG. Y como es de código abierto, incluso podrías involucrarte en el proyecto. Pero ahora me centraré en lo que aprendí jugando con él como motor y explicaré algunos conceptos básicos.

A pesar de todo lo genial de Three.js, hay ocasiones en las que podrías tener dificultades. Por lo general, tendrás que dedicar mucho tiempo a los ejemplos, aplicar ingeniería inversa y, en mi caso, sin dudas, buscar funcionalidades específicas y, en ocasiones, hacer preguntas a través de GitHub. Si tienes preguntas, descubrí que Mr. doob y AlteredQualia son sumamente útiles.

1. Conceptos básicos

Supongo que tienes, al menos, conocimientos básicos sobre 3D y que tienes un dominio razonable de JavaScript. De lo contrario, puede valer la pena aprender un poco antes de intentar hacerlo, ya que puede resultar un poco confuso.

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

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

Por supuesto que puedes hacer cosas interesantes, y espero que continúes haciéndolo y comiences a experimentar con 3D en tu navegador.

2. Asistencia

Esta es una nota breve sobre la compatibilidad con los navegadores. Según mi experiencia, el navegador Chrome de Google es el mejor para trabajar en cuanto a los procesadores compatibles y la velocidad del motor de JavaScript subyacente. Chrome es compatible con Canvas, WebGL y SVG, y es increíblemente rápido. Firefox es en segundo lugar, 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 son compatibles con Canvas. Internet Explorer (versión 9 y versiones posteriores) solo admite el renderizado de lienzo, y no conozco nada de que Microsoft planifique agregar capacidades de WebGL.

3. Configura la escena

Supongamos que elegiste un navegador compatible con todas las tecnologías de renderización y que deseas renderizarlos con Canvas o WebGL, ya que son las opciones más estándar. El lienzo 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 la CPU puede concentrarse en otras tareas que no son de renderización, como cualquier física o interacción del usuario que intentes hacer.

Independientemente del procesador que elijas, debes tener en cuenta que JavaScript deberá optimizarse para mejorar el rendimiento. 3D no es una tarea simple para un navegador (y es genial que también sea posible), así que asegúrate de comprender dónde se encuentran los cuellos de botella en tu código y quítalos si puedes.

Dicho esto, en el supuesto de que descargaste e incluiste tres.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 complicado, en serio.

4. Cómo hacer una malla

Tenemos una escena, una cámara y un procesador (opté por uno de WebGL en mi código de muestra), pero no tenemos nada para dibujar. En realidad, Three.js es compatible con la carga de algunos tipos de archivos estándar diferentes, lo cual es excelente si generas modelos de Blender, Maya, Cinema4D o cualquier otro. Para que sea sencillo (después de todo, se trata de empezar). 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 para la esfera? En el código, usamos una variable sphereMaterial, pero aún no la definimos. Primero tenemos que 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 prácticos) para aplicar a las mallas:

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

Hay más, pero por cuestiones de simplicidad, te dejaré que las descubras por tu cuenta. En el caso de WebGL, en particular, estos materiales pueden ser útiles. ¿Por qué? Porque en WebGL debes escribir sombreadores para todo lo que se renderiza. Los sombreadores son un tema enorme en sí mismos, pero, para resumir, están escritos en GLSL (OpenGL Shader Language), que le indica a la GPU cómo debería verse algo. Esto significa que debes imitar los cálculos de la iluminación, la reflexión, etcétera. Puede volverse muy complicado en muy poco tiempo. Gracias a Three.js, no tienes que hacer esto si no deseas hacerlo porque lo abstrae. Sin embargo, si deseas escribir sombreadores, también puedes hacerlo con MeshShaderMaterial, por lo que es una configuración flexible.

Sin embargo, 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
});

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

6. ¡Luces!

Si renderizas la escena ahora mismo, verás un círculo rojo. Aunque se aplicó un material 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 la coloración plana. Solucionémoslo 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

Sorprendentemente, ahora tenemos todo configurado para renderizar. Pero, en realidad, debemos continuar y hacer precisamente eso:

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

Es probable que quieras renderizar los datos más de una vez, por lo que si vas a hacer un bucle, deberías usar requestAnimationFrame, ya que es la forma más inteligente de controlar la animación en el navegador. Todavía no es totalmente compatible, por lo que te recomiendo que revises la corrección de compatibilidad de Paul Ireland.

8. Propiedades comunes de los objetos

Si te tomas el tiempo para revisar el código de Three.js, verás muchos objetos “heredados” de Object3D. Este es un objeto base que contiene algunas propiedades muy útiles, como la información de position, rotation y scale. En particular, nuestra esfera es una malla que hereda de Object3D, a la que le agrega sus propias propiedades: geometría y materiales. ¿Por qué las menciono? 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. Pequeños secretos sucios

Solo quería señalar rápidamente un inconveniente para Three.js: si modificas, por ejemplo, los vértices de una malla, notarás que nada cambia en el bucle de renderización. ¿Por qué? Pues porque Three.js (por lo que puedo asegurar) almacena en caché los datos de una malla como una optimización. En realidad, lo que 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;

Hay más, pero estos son los más útiles. Obviamente, solo debes marcar los aspectos 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 mejor que ensuciarte las manos y probar algo, y no puedo recomendarlo lo suficiente. La ejecución en 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 contenido genial. Para ayudarte, uní el código fuente en este artículo de este lab con el objetivo de que puedas usarlo como referencia. Si te gustó el proceso, cuéntame a través de Twitter. Siempre es bueno poder saludarlo.