Es un Framework Javascript desarrollado por programadores de Microsoft para la creación de Juegos 3D con HTML5 y WebGL que cuenta con una serie de características como el manejo de luces, materiales, cámaras, sprites, capas, mallas, motor de colisiones, texturas, motor de animaciones, sistemas de partículas, conversión de archivos de modelado 3D como .OBJ, .FBX y .MXB, entre otras.
Iniciando con Babylon.js
De una manera rápida podemos descargarnos desde GitHub el archivo sin minimizar que se encuentra en la raíz del repositorio e importarlo en nuestra página Web.
Index.html
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="utf-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <title></title>
- <meta name="description" content="">
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <script src="babylon.1.14.js"></script>
- <style>
- html, body {
- width: 100%;
- height: 100%;
- padding: 0;
- margin: 0;
- overflow: hidden;
- }
-
- #renderCanvas {
- width: 100%;
- height: 100%;
- }
- </style>
- </head>
- <body>
- <canvas id="renderCanvas"></canvas>
- <script type="text/javascript" src="main.js"></script>
- </body>
- </html>
Como podemos ver estamos creando un canvas que será el lienzo que utilizará Babylon.js para dibujar las escenas mediante WebGL. En nuestro archivo main.js es donde pondremos nuestro código para añadir mallas (Los objetos 3D), las luces, las cámaras, los materiales, etc.
main.js
- if (BABYLON.Engine.isSupported()) {
- var canvas = document.getElementById("renderCanvas");
- //Motor que se encarga de trabajar con WebGL
- var engine = new BABYLON.Engine(canvas, true);
- //Contenedor para todas las entidades, que trabajando juntas crearan la imagen en 3D
- //Luces, camara y mallas
- var scene = new BABYLON.Scene(engine);
-
- var renderloop = function () {
- scene.render();
- };
- //Definimos un ciclo para el renderizado
- engine.runRenderLoop(renderloop);
-
- //Nuestro codigo...
- //Babylonjs viene con una libreria matematica completa para manejar vectores, matrices, colores, rayas, etc
- var camera = new BABYLON.FreeCamera("Camera", new BABYLON.Vector3(0, 0, -10), scene);
- var light0 = new BABYLON.PointLight("Omni0", new BABYLON.Vector3(0, 100, 100), scene);
- var sphere = BABYLON.Mesh.CreateSphere("Sphere", 16, 3, scene);
- }
- else {
- alert("El Navegador debe de soportar WebGL");
- }
Babylon.js nos deja saber si el navegador soporta WebGL o por el contrario debemos mostrarle al usuario que se necesita un navegador más moderno. Luego instanciamos el motor que se encargará de mostrarnos todo en el lienzo que creamos previamente y podemos empezar a crear escenas en las cuales crearemos nuestros objetos. Para que constantemente se este actualizando nuestro canvas definimos un ciclo para el renderizado de una forma muy fácil.
Materiales
Un material es un objeto que define la forma de la malla. Babylon.js provee un objeto llamado StandardMaterial el cual cuenta con las siguientes propiedades:
- diffuseColor y diffuseTexture: Definir el color base de la malla (Es el color como tal del objeto).
- ambientColor y ambientTexture: Definir el color ambiente de la malla (Color de un objeto que se encuentra en la sombra, color que se refleja cuando es iluminado por la luz ambiente en lugar de la luz directa).
- specularColor y specularTexture: Definir el color especular de la malla (Color de la luz de una reflexión especular, reflexión que es característica de la luz reflejada de una superficie brillante).
- emissiveColor y emissiveTexture: Definir el color emitido por la malla (Color que tiene el objeto sin luz).
- opacityTexture: Definir la transparencia de la malla.
- reflectionTexture: Definir el color de reflexión recibida por la malla.
- bumpTexture: Definir el nivel de protuberancia de la malla sobre una base por pixel (Básicamente nos permite cambiar el aspecto de la superficie de los objetos sin cambiar su geometría).
- alpha: Definir la transparencia global de la malla.
- //Materiales
- //Objeto que define la forma de la malla
- var material = new BABYLON.StandardMaterial("default", scene);
- material.diffuseColor = new BABYLON.Color3(1, 0, 0);
- material.emissiveColor = new BABYLON.Color3(0.2, 0.2, 0.2);
- material.specularColor = new BABYLON.Color3(1, 1, 1);
- sphere.material = material;
Para entender más sobre los materiales puedes ver los siguientes enlaces:
- http://blogs.msdn.com/b/eternalcoding/archive/2013/07/01/babylon-js-unleash-the-standardmaterial-for-your-babylon-js-game.aspx
- http://blogs.msdn.com/b/eternalcoding/archive/2013/07/10/babylon-js-using-multi-materials.aspx
Luces
Babylon.js cuenta con 4 tipos de luces diferentes (Puedes crear tantas luces como quieras pero el StandardMaterial sólo puede tener en cuenta hasta 4 luces simultáneamente):
-
PointLight: Emite luz en todas las direcciones desde una posición específica como el sol.
-
DirectionalLight: Emite luz desde el infinito hacia una dirección específica.
-
SpotLight: Emite luz desde una posición a una dirección, como si fuera dentro de un cono.
-
HemisphericLight: Luz ambiental especial basada en una dirección para determinar si el color de la luz viene desde el suelo o desde el cielo.
Las luces tienen 3 propiedades principales:
-
diffuse: Color difuso que determina la parte reflejada de la luz.
-
specular: Color especular.
-
position: posición/dirección.
Spot Lights también cuentan con:
Hemispheric Lights también cuentan con:
Para entender más sobre las luces: http://blogs.msdn.com/b/eternalcoding/archive/2013/07/08/babylon-js-using-lights-in-your-babylon-js-game.aspx
Cámaras
Babylon.js soporta varios tipos de cámaras (Puedes crear tantas cámaras como quieras pero solo una puede estar activa al tiempo, se pueden activar varias cámaras solo si usas multi-ventanas):
-
FreeCamera: Cámara FPS que se puede controlar con las teclas y el mouse (Cámara en primera persona).
-
TouchCamera: Cámara controlada con eventos táctiles (Require hand.js para trabajar).
-
ArcRotateCamera: Cámara que gira alrededor de un pivote dado, se puede controlar con los eventos del ratón o toque (Require hand.js para trabajar).
-
DeviceOrientationCamera: Cámara que reacciona a los eventos de orientación del dispositivo, es decir cuando giras el dispositivo móvil.
-
FollowCamera: Cámara diseñada para seguir cualquier elemento de la escena desde cualquier ángulo.
-
VirtualJoysticksCamera: Cámara que reacciona a los eventos de un Joystick virtual, el cual es dibujado en el canvas mediante gráficos 2D para controlar las cámaras y otros elementos del escenario.
-
OculusCamera: Cámara de doble vista que reacciona a los eventos generados por el Oculus Rift (Casco de realidad virtual).
-
AnaglyphCamera: Cámara para gafas 3D de colores rojo y cian, que utiliza técnicas de filtrado de post-procesamiento.
-
GamepadCamera: Cámara para trabajar con gamepads.
Todas las cámaras pueden manejar automáticamente las entradas del canvas llamando a la función attachControl, se puede revocar mediante el uso de detachControl.
Mallas
Son las entidades las cuales cuentan con muchas propiedades y que se pueden crear a partir de formas básicas o de lista de vértices y caras. Las formas básicas son el Cubo, la Esfera, el Plano, el Cilindro, el Toro y el Nudo.
- //Nombre de la caja, capacidad y escena
- var box = BABYLON.Mesh.CreateBox("box", 6.0, scene);
- //Nombre de la esfera, segmentos, diametro y escena
- var sphere = BABYLON.Mesh.CreateSphere("sphere", 10.0, 10.0, scene);
- //Nombre del plano, capacidad y escena
- var plane = BABYLON.Mesh.CreatePlane("plane", 10.0, scene);
- //Nombre del cilindro, altura, diametro superior, diametro inferior, teselado, [altura opcional de las subdivs], escena y si es actualizable
- var cylinder = BABYLON.Mesh.CreateCylinder("cylinder", 3, 3, 3, 6, 1, scene, false);
- //Nombre del toro, diametro, espesor, teselado, escena y si es actualizable
- var torus = BABYLON.Mesh.CreateTorus("torus", 5, 1, 10, scene, false);
- //Nombre del nudo, tubo, segmentos radiales, segmentos tubulares, p, q, escena y si es actualizable
- var knot = BABYLON.Mesh.CreateTorusKnot("knot", 2, 0.5, 128, 64, 2, 3, scene);
También se pueden crear mallas a partir de líneas, vértices e índices. Luego de creada la malla esta se puede modificar mediante las propiedades de posición, rotación y escala.
- box.position = new BABYLON.Vector3(0, 5, 0);
- box.rotation.z = 0.5;
- box.scaling.x = 4;
Un punto muy interesante es que se tiene la opción de poder establecer jerarquía entre las mallas, de esta forma todas las transformaciones en cuanto a la posición, rotación y escala del padre afectarán a los hijos.
- var cylinder = BABYLON.Mesh.CreateBox("Box" , 1.0, scene);
- cylinder.position = new BABYLON.Vector3(0, 2, 2);
- cylinder.parent = plane;
Otras propiedades con que contamos para la activación y la visibilidad de las mallas son:
- StandardMaterial permite controlar la opacidad de un objeto con: La propiedad alpha para controlar la transparencia por malla, el canal alfa de diffuseTexture que hará que babylon.js active pruebas alfa para descartar todos los pixeles con valor alfa < 0.5 y la propiedad opacityTexture para definir la mezcla alfa por píxel.
- La propiedad visibility para controlar la transparencia por malla directamente sin usar un material.
- La propiedad isVisible para activar la renderización de la malla. La malla se mantiene en la escena para otras operaciones y esta no es transmitida a los hijos.
- La función setEnabled para desactivar una malla y todos sus descendientes.
Colisiones
Babylon.js cuenta con un sistema de colisiones completo y muy fácil de utilizar. Para configurarlo hay que realizar los siguientes pasos:
- Activar las colisiones en la escena a nivel mundial y definir la gravedad
- scene.collisionsEnabled = true;
- scene.gravity = new BABYLON.Vector3(0, -9, 0);
- Configurar la cámara que se utilizará para las colisiones (El motor de colisiones considera la cámara como un elipsoide, una especie de capsula). También se puede crear una cámara volando para que no se aplique la gravedad a esta.
- camera.checkCollisions = true;
- camera.applyGravity = true;
- camera.ellipsoid = new BABYLON.Vector3(0.5, 1, 0.5);
- Se definen las mallas que van a colisionar
- plane.checkCollisions = true;
- sphere.checkCollisions = true;
- intersectsMesh: Podemos detectar si hay colisión entre objetos.
- intersectsPoint: Podemos detectar si hay colisión con un vector en el espacio, es decir puntos específicos.
Sistemas de partículas
Mediante un sistema de partículas podemos añadir muy fácilmente efectos impresionantes en nuestras escenas como explosiones, impactos, efectos mágicos, etc. Crear un sistema de partículas es tan simple como:
- //Nombre, cantidad maxima de particulas activas simultaneamente y escena
- var particleSystem = new BABYLON.ParticleSystem("boom", 2000, scene);
Los sistemas de partículas cuentan con un gran listado de propiedades:
- particleTexture: Define la textura asociada con cada partícula.
- minAngularSpeed/maxAngularSpeed: El rango de la velocidad de rotación angular de cada partícula.
- minSize/maxSize: El rango de tamaños de cada partícula.
- minLifeTime/maxLifeTime: El rango de vidas de cada partícula.
- minEmitPower/maxEmitPower: El rango de velocidad de emisión de cada partícula.
- minEmitBox/maxEmitBox: La caja desde donde cada partícula es creada o un punto si el valor mínimo y máximo son el mismo.
- direction1/direction2: El rango de direcciones de cada partícula.
- color1/color2: El rango de colores de cada partícula.
- colorDead: El color de una partícula muerta (Babylon.js interpolará el color de las partículas a este color).
- deadAlpha: El alfa de una partícula muerta (Babylon.js interpolará el alfa de la partícula para finalizar con el alfa especificado).
- textureMask: Una mascara usada para filtrar que parte de la textura se utiliza para cada partícula.
- blendMode: Modo de fusión Alfa (BLENDMODE_ONEONE para agregar el color actual y el color de la partícula o BLENDMODE_STANDARD para mezclar el color actual y el color de la partícula usando el alfa de las partículas).
- emitter: Un Vector3 define la posición del sistema de partículas. También se puede utilizar una malla y en este caso el sistema de partículas utilizará la posición de la malla.
- emitRate: La cantidad de partículas que se pueden emitir en cada fotograma.
- manualEmitCount: Al especificar un valor >= 0 deshabilitará emitRate, permitiendo controlar manualmente la cantidad de partículas emitidas.
- updateSpeed: Velocidad global del Sistema.
- gravity: La gravedad que se aplica a las partículas.
- targetStopDuration: Detiene el sistema de partículas después de una duración especifica.
- disposeOnStop: Determina la parada del sistema de partículas (Útil para un sistema de partículas de un disparo con un específico targetStopDuration).
Nota: Un sistema de partículas se controla mediante las funciones start y stop.
Sprites y Capas
Babylon.js esta diseñado para utilizar WebGL para el desarrollo de aplicaciones y juegos. Babylon.js por lo tanto soporta sprites y capas 2D para el desarrollo de juegos 2D.
A una malla se le puede definir la propiedad billboardMode para alinearlo con la cámara para simular un objeto 2D:
- plane.billboardMode = BABYLON.Mesh.BILLBOARDMODE_ALL;
Un sprite es definido por una textura que contiene todos sus estados de animación
El estado actual se define mediante la propiedad cellIndex, la cual se puede manipular por código o usar la función playAnimation para dejar que Babylon.js controle esta propiedad.
Para optimizar el uso de los recursos varios sprites pueden utilizar la misma textura mediante un SpriteManager.
- //Nombre del sprite, ubicacion, capacidad de movimientos, tamao y escena
- var spriteManager = new BABYLON.SpriteManager("Enemy", "Enemies.png", 100, 64, scene);
- var enemy1 = new BABYLON.Sprite("enemy1", spriteManager);
- var enemy2 = new BABYLON.Sprite("enemy2", spriteManager);
- enemy1.position.y = enemy2.position.y = 0;
- enemy1.position.z = 20;
- enemy2.position.z = 100;
- enemy1.position.x = enemy2.position.x = 50;
- enemy2.invertU = true;//Invierte horizontalmente la textura
- //Donde inicia, donde termina, si es ciclica y la velocidad
- enemy1.playAnimation(0, 9, true, 100);
- enemy2.playAnimation(0, 9, true, 100);
Babylon.js es compatible con capas 2D con el fin de añadir fondos o poner en primer plano.
- //Nombre, archivo, escena y si la capa es de fondo
- var background0 = new BABYLON.Layer("back0", "Layer0.png", scene);
- var background1 = new BABYLON.Layer("back1", "Layer1.png", scene);
- var foreground = new BABYLON.Layer("fore0", "Layer2.png", scene, false);
Animaciones
La animación es básicamente el cambio de estado de un objeto mediante las transformaciones como la traslación, la rotación y la escala.
Las animaciones en Babylon.js las podemos realizar nosotros mismos utilizando Javascript con lo que se ha visto anteriormente en este artículo o se pueden realizar utilizando el motor de animaciones. El motor de animaciones se basa en objetos llamados Animation, una animación se define por tanto por las propiedades y una colección de claves (Cada una representa la animación en un momento dado) y después de creada se puede añadir a la propiedad animations de un objeto.
- //Nombre de la animacion, propiedad a animar, fotogramas por segundo, tipo de animacion y ciclos de la animacion
- var animation = new BABYLON.Animation("animation", "scaling.x", 30, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);
- animation.setKeys([
- { frame: 0, value: 1 },
- { frame: 50, value: 0.2 },
- { frame: 100, value: 1 }
- ]);
- box.animations.push(animation);
Las animaciones pueden trabajar con varios tipos:
- Float (BABYLON.Animation.ANIMATIONTYPE_FLOAT).
- Vector3 (BABYLON.Animation.ANIMATIONTYPE_VECTOR3).
- Quaternion (BABYLON.Animation.ANIMATIONTYPE_QUATERNION).
Y pueden tener diferentes comportamientos cuando llegan al límite de la animación:
- Incrementar utilizando los valores anteriores (BABYLON.Animation.ANIMATIONLOOPMODE_RELATIVE).
- Reiniciar al valor inicial (BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE).
- Mantener el valor final (BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT).
Y para iniciar la animación solo basta con llamar la siguiente función
- //Objeto, Clave inicial, Clave final y si es un ciclo
- scene.beginAnimation(box, 0, 100, true);
Permiten elegir todo en cada fotograma de la animación. Se utiliza la función registerBeforeRender porque nos es útil cuando deseamos mover en función de muchos parámetros.
- scene.registerBeforeRender(function () {
- sphere.rotation.x += 1;
- });
Texturas avanzadas
Las texturas pueden ser basadas en imágenes pero con Babylon.js se puede utilizar funciones avanzadas para generar texturas en tiempo de ejecución.
- Texturas Dinámicas: Utiliza un lienzo para generar su contenido. Para crearla y modificarla es muy sencillo:
- var dynamicTexture = new BABYLON.DynamicTexture("textura dinamica", 512, scene, true);
- dynamicTexture.hasAlpha = true;
- material.diffuseTexture = dynamicTexture;
Después de creada puedes actualizarla cuando quieras
- var count = 0;
- scene.beforeRender = function () {
- // Dynamic
- var textureContext = dynamicTexture.getContext();
- var size = dynamicTexture.getSize();
- var text = count.toString();
-
- textureContext.save();
- textureContext.fillStyle = "red";
- textureContext.fillRect(0, 0, size.width, size.height);
-
- textureContext.font = "bold 120px Calibri";
- var textSize = textureContext.measureText(text);
- textureContext.fillStyle = "white";
- textureContext.fillText(text, (size.width - textSize.width) / 2, (size.height - 120) / 2);
-
- textureContext.restore();
-
- dynamicTexture.update();
- count++;
- };
El getContext devuelve el contexto de un verdadero canvas, así que todo lo que se puede hacer en un canvas esta disponible en una textura dinámica.
- Texturas de vídeo: Puedes utilizar texturas en donde la fuente del contenido es un vídeo.
- var ecran = scene.getMeshByName("Ecran");
- //Nombre, un arreglo de diferentes codecs del vdeo, capacidad, escena y si se desea utilizar mipmaps
- ecran.material.diffuseTexture = new BABYLON.VideoTexture("video",
- ["Scenes/Flat2009/babylonjs.mp4", "Scenes/Flat2009/babylonjs.webm"], 256, scene, true);
Para controlar el estado del vídeo (play/pause/stop) se puede utilizar la propiedad VideoTexture.video la cual da acceso al objeto interno en el DOM del vídeo.
Son otro tipo de texturas dinámicas que utiliza Babylon.js para simular “Espejos” mediante la reflexión y llenar la textura con los resultados. Estos se pueden configurar mediante el canal reflectionTexture de un standardMaterial
- var mirror = BABYLON.Mesh.createBox("Espejo", 1.0, scene);
- mirror.material = new BABYLON.StandardMaterial("espejo", scene);
- mirror.material.diffuseColor = new BABYLON.Color3(0.4, 0, 0);
- mirror.material.reflectionTexture = new BABYLON.MirrorTexture("espejo", 512, scene, true);
- mirror.material.reflectionTexture.mirrorPlane = new BABYLON.Plane(0, -1.0, 0, -2.0);//El plano de reflexion
- mirror.material.reflectionTexture.renderList = [box, sphere];//Objetos que se renderizaran
Babylon.js puede cargar escenas desde un formato de archivo .babylon. Este formato de archivo de basa en JSON y contiene todos los datos necesarios para crear una escena completa.
Babylon Export
Un archivo .babylon puede ser creado mediante una herramienta personalizada la cual puede ser descargada desde GitHub https://github.com/BabylonJS/Babylon.js/tree/master/Exporters (BabylonExporter.zip). Aquí encontrarán un ejecutable que les permitirá exportar mediante la línea de comandos un archivo .babylon desde varios formatos de archivo:
- .FBX
- .OBJ
- .MXB
- BabylonExport.exe /i:"C:\Archivo.obj" /o:"C:\CarpetaDestino"
Blender
Nosotros podemos producir archivos .babylon desde Blender, para estos debemos primeramente descargar el script desde GitHub https://github.com/BabylonJS/Babylon.js/tree/master/Exporters/Blender
Luego de descargado abrimos Blender y nos vamos para File/User Preferences… y damos Click en Install From File, aquí debemos de seleccionar el script
Y para activar este complemento en User Preferences nos ubicamos en Addons, seleccionamos la categoría Import-Export y buscamos Babylon.js para habilitarlo
Y para guardar los cambios damos Click en Save User Settings.
Ya luego podemos crear nuestra Escena en Blender con lo que aprendimos en artículos anteriores y por último exportarla a un archivo .babylon
Para cargar nuestra escena fácilmente en nuestra página web Babylon.js nos provee una función Load mediante el objeto BABYLON.SceneLoader
- if (BABYLON.Engine.isSupported()) {
- var canvas = document.getElementById("renderCanvas");
- var engine = new BABYLON.Engine(canvas, true);
-
- BABYLON.SceneLoader.Load("", "demo.babylon", engine, function (newScene) {
- newScene.executeWhenReady(function () {
- engine.runRenderLoop(function () {
- newScene.render();
- });
- });
- }, function (progress) {
- console.log(progress);
- });
- window.addEventListener("resize", function () {
- engine.resize();
- });
- }
También otra opción muy útil con que contamos es poder cargar uno o más objetos desde otra escena
- //(Nombre de la malla[si esta vacia carga todas], la carpeta donde se encuentra el archivo, el archivo .babylon, la escena a la que se importa la malla y el callback cuando ya se haya importado)
- BABYLON.SceneLoader.ImportMesh("", "", "guantes.babylon", newScene, function (newMeshes) {
- guantes = newMeshes;
- });
Los siguientes modelos 3D (Archivos .OBJ) son creados por mi buen amigo Esteban Velaren