Post on 24-Oct-2015
Introducción a Three.js, la librería 3D número uno para
HTML5
Comentarios 5
Me gusta 0
Three.js es una librería bastante liviana y muy eficiente para generar y animar gráficos en
3D dentro del navegador, aprovechando las grandes novedades que nos ofrece HTML5
para la generación de contenidos multimedia. Aprovecha tanto las capacidades de HTML5
que es capaz de generar escenas 3D con WebGL, Canvas (2D) y SVG.
Su código está disponible en GitHub y en su web podemos encontrar ejemplos
alucinantes de lo que se puede a llegar a hacer con Three.js.
Posibilidades de diseño
Three.js no es popular solo porque es simple a la hora de usarlo a través de JavaScript,
sino porque tiene un equilibrio perfecto entre el diseño y la programación.
Permite, entre otras cosas, importar archivos 3D a partir de Blender o Maya, pudiendo
generar terrenos u objetos totalmente complejos y de gran calidad.
La librería también incorpora potentísimos shaders que se pueden personalizar
con OpenGL Shading Language (GLSL). Y sin duda incorpora todo lo necesario para
crear escenas 3D, como son la posibilidad de manipular luces, cámaras, animar objetos,
perspectivas, control de visualizaciones y mucho más.
Conceptos básicos
Antes de empezar, vemos el siguiente ejemplo simple que podremos realizar fácilmente
tras haber visto los conceptos básicos.
Lo primero que tenemos que tener es nuestro archivo HTML listo para insertar la ventana
donde se visualizará todo el 3D, de una forma muy simple, ya que el objeto del Canvas
nos los genera Three.js.
Lo primero es descargar la librería para poderla usar, que pesa unos 300kb. Para realizar
la prueba haremos que la visualización ocupe toda el espacio del navegador y lo haremos
mediante CSS.
<!DOCTYPE html>
<html>
<head>
<script src="lib/three.min.js"></script>
<style>
canvas {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
</style>
</head>
<body>
<script src="script/main.js"></script>
</body>
</html>
Creando la escena
Para interactuar con Three.js lo haremos a través del objeto THREE, que nos brinda todos
los elementos necesarios.
Lo primero de todo es generar el renderizador, que en este caso usaremos el de WebGL,
que es el más completo. Posteriormente le daremos las dimensiones de la pantalla y lo
añadiremos al documento. Al igual que ahora lo añadimos directamente al body y con las
dimensiones de la página, podríamos añadirlo en cualquier lugar y con cualquier
dimensión.
WIDTH = window.innerWidth; // Ancho de pantalla
HEIGHT = window.innerHeight; // Alto de pantalla
// Lienzo u objeto encargado del renderizado
var lienzo = new THREE.WebGLRenderer();
// Establecemos las dimensiones del lienzo
lienzo.setSize(
WIDTH,
HEIGHT
);
// Añadimos el lienzo a la página
document.body.appendChild(lienzo.domElement);
Y ahora tenemos que crear la propia escena, que se encarga de almacenar todos los
elementos que posteriormente visualizaremos.
// Creamos la escena
var escena = new THREE.Scene;
Añadiendo objetos
Ahora que ya tenemos lo básico creado añadiremos un elemento básico a la escena, en
este caso un cubo o prisma. Pero la forma de tratar los objetos es muy similar, por lo que
podríamos crear una esfera de la misma forma prácticamente.
Primero crearemos un objeto CubeGeometry al que le daremos un tamaño, y solo sirve
como forma para generar el prisma. Posteriormente crearemos un material
con MeshLambertMaterial, que podría contener texturas, pero en este caso será de
color lila.
// Creamos un prisma
var geometriaCubo = new THREE.CubeGeometry(
100, // Dimensiones en eje X
140, // Dimensiones en eje Y
100 // Dimensiones en eje Z
);
// Creamos una apariencia (de lila claro)
var aparienciaLila = new THREE.MeshLambertMaterial({
color: 0x9999FF // Color hexadecimal
});
// Generamos el prisma y le aplicamos la apariencia
var cubo = new THREE.Mesh(geometriaCubo, aparienciaLila);
Lo último, cuando creamos cualquier elemento, es añadirlo a la propia escena que
habíamos creado.
// Añadimos el cubo a la escena
escena.add(cubo);
Cámara
Para poder visualizar una escena debemos de tener una cámara que nos de la visión de
los elementos. En la práctica no es mucho más diferente que cualquier otro elemento, ya
que lo podemos mover y rotar igual que podemos hacer con un prisma, por ejemplo.
Three.js dispone de distintos tipos de cámara, pero la que hace la visualización más
realista esPerspectiveCamera, por lo que no tendríamos que necesitar mucho las
demás.
La cámara nos permite establecer el ángulo de visión (estando entre los 40º y 50º un
ángulo natural), la relación entre el ancho y el alto y el rango de alcance de la vista (si un
elemento está más lejos de eso desaparecerá).
// Generamos la cámara
var camara = new THREE.PerspectiveCamera(
45, // Campo de visión
(WIDTH / HEIGHT), // Proporcion
0.1,
10000 // Campo de visión
);
// Situamos la cámara
camara.position.y = 160; // Elevamos la cámara
camara.position.z = 400; // Alejamos la cámara
También la cámara dispone de un método para centrar su visión a un objeto, y es lo que
haremos para ver claramente el prisma. También añadimos la cámara a la escena.
// Centramos la vista en el cubo
camara.lookAt(cubo.position);
// Añadimos la cámara a la escena
escena.add(camara);
Ahora ya podríamos visualizar la escena a través de la ventana o renderizador que ya
creamos al principio. Aunque en el código final no se visualiza en este paso, esta sería la
forma.
// Renderizamos la escena
lienzo.render(escena, camara);
Simplemente le hemos pasado la escena y la cámara con la que vamos a ver la escena.
También se podría usar otra cámara o mostrar dos vistas distintas de la misma escena
con mucha facilidad.
El resultado, antes de aplicar las luces es el siguiente.
Iluminación
Para poder ver con claridad los colores de la escena necesitamos añadirle luz, que actúa
de forma similar a una cámara, pero en lugar de darle parámetros de visualización le
pasaremos un número (en hexadecimal, pero numérico). También tenemos que darle una
posición, al igual que con la cámara (aunque en este caso por el método directo) y
añadirla a la escena.
En este ejemplo voy a añadir dos luces, una rojiza y otra azulada.
// Creamos una par de focos de luz
var luz1 = new THREE.PointLight(0xff0044); // Rojizo
luz1.position.set(
120, // Posición en eje X
260, // Posición en eje Y
100 // Posición en eje Z
);
var luz2 = new THREE.PointLight(0x4499ff); // Azulado
luz2.position.set(
-100, // Posición en eje X
100, // Posición en eje Y
200 // Posición en eje Z
);
// Añadimos las luces
escena.add(luz1);
escena.add(luz2);
Tras añadir las luces si le enviamos la imagen al render veríamos lo siguiente.
Animar la escena
Three.js nos facilita una función para ejecutar de forma correcta la escena, creando un
nuevo fotograma cuando está disponible el equipo. Es decir, si se pilla la ejecución o se
ralentiza el equipo no se animará el siguiente fotograma, lo que ayuda a mejorar la
estabilidad (de nada sirve sobrecargar la página si ya esta pillada).
Esta acción la haremos con requestAnimationFrame que funciona de forma similar a
unsetTimeout, al que le tenemos que pasar una función y el tiempo lo determina solo.
En este ejemplo que estamos realizando haremos rotar a nuestro prisma (en el eje Z de
forma continua y en el eje Y oscilando).
Al final de mover los elementos hacemos la petición de nuevo
con requestAnimationFrame.
x=0; // Lo usamos para la oscilación
function renderizar(){
// Rotamos el cubo
cubo.rotation.y += Math.PI * 0.5 / 180; // Ángulo en radianes
cubo.rotation.z += Math.PI * Math.cos(x++ / 50) / 180;
// Renderizamos la escena
lienzo.render(escena, camara);
// Volvemos a renderizar
requestAnimationFrame(renderizar);
}
// Empezamos a renderizar
renderizar();
El resultado final es el siguiente y podéis consultar el código completo en GitHub.
Resumen
Esto es solo la punta del iceberg, tras Three.js hay un mundo con infinitas posibilidades y
que cada día está dejando ver mejores ejemplos de uso. Y sin duda deja la puerta abierta
a los videojuegosserios e indies para hacerse un hueco en todas las plataformas de un
plumazo.