Tabla de contenidos

Aprender WebGL y Babylon.js a su propio ritmo

no dude en visitar nuestra línea de golf en 3D con WebGL Programación y Babylon.js para principiantes en Zenva Academia. El curso cubre el marco Babylon.js y explica todo lo que necesita para empezar con el uso de esta fantástica biblioteca en proyectos nuevos o existentes.

Tutorial

Windows 8.1 añade el apoyo de WebGL para aplicaciones de Internet Explorer y JavaScript. Esta es una gran evolución, porque ahora estamos en condiciones de dar rienda suelta a la potencia bruta de la GPU, incluso con HTML5 y JavaScript!

Este poder puede ser difícil de dominar y es por eso que he creado babylon.js. Y su uso, el maravilloso mundo de acelerada 3D le dará la bienvenida.

Preparación del proyecto

Por ejemplo, yo siempre quería crear una aplicación para tener las estadísticas de mi blog en un solo vistazo.

Para ello, vamos a empezar con una aplicación de vacío de Windows 8.1 JavaScript.

imagen

Lo primero es para referencia babylon.js (y hand.js para apoyar eventos táctiles):

imagen

La página default.html debe cambiarse para agregar un lienzo y con la referencia babylon.js y hand.js
& Lt;! DOCTYPE html & gt; & lt; html & gt; & lt; head & gt; & Lt; meta charset = «UTF-8» / & gt; & Lt; title & gt; Chart3D & lt; título / & gt; & Lt;! – WinJS referencias – & gt; & Lt; link href = «// Microsoft.WinJS.2.0.Preview / css / ui-dark.css» rel = «stylesheet» / & gt; & Lt; script src = «// Microsoft.WinJS.2.0.Preview / JS / base.js» & gt; & lt; script / & gt; & Lt; script src = «// Microsoft.WinJS.2.0.Preview / JS / ui.js» & gt; & lt; script / & gt; & Lt;! – referencias Chart3D – & gt; & Lt; link href = «/ css / default.css» rel = «stylesheet» / & gt; & Lt; script src = «js / hand.minified-1.1.1.js» & gt; & lt; / script & gt; & Lt; script src = «JS / babylon.js» & gt; & lt; script / & gt; & Lt; script src = «/ JS / default.js» & gt; & lt; script / & gt; & lt; / head & gt; & lt; body & gt; & Lt; lona Identificación = «renderCanvas» & gt; & lt; / lienzo & gt; & lt; body / & gt; & lt; / html & gt; 123456789101112131415161718192021 & lt;! DOCTYPE html & gt; & lt; html & gt; & lt; head & gt; & lt; meta charset = «UTF-8» / & gt; & lt; title & gt; Chart3D & lt; título / & gt; & lt;! – WinJS referencias – & gt; & lt; link href = «// Microsoft.WinJS.2.0.Preview / css / ui-dark.css» rel = «stylesheet «/ & gt; & lt; script src =» // Microsoft.WinJS.2.0.Preview / JS / base.js «& gt; & lt; script / & gt; & lt; script src =» // Microsoft.WinJS.2.0.Preview / js referencias /ui.js»></script><!–Chart3D – & gt; & lt; link href = «/ css / default.css» rel = «stylesheet» / & gt; & lt; script src =» js / hand.minified-1.1.1.js «& gt; & lt; script / & gt; & lt; script src =» JS / babylon.js «& gt; & lt; script / & gt; & lt; script src =» / js / default.js «& gt; & lt; script / & gt; & lt; / head & gt; & lt; body & gt; & lt; lona id =» renderCanvas «& gt; & lt; / lienzo & gt; & lt; body / & gt; & lt; / html & gt;

Conexión babylon.js < / h3>

Como se puede haber visto en mis mensajes anteriores, babylon.js necesidades para conectar con el lienzo a través de la BABYLON.Engine objeto. Podemos hacer que justo después de la finalización de la Processall función:
args.setPromise (WinJS.UI.processAll () entonces (function () {lona var = document.getElementById ( «renderCanvas»);. motor var = new BABYLON.Engine (lienzo, true); 123args.setPromise (WinJS.UI .processAll () entonces (function () {document.getElementById (varcanvas = «renderCanvas»); varengine = newBABYLON.Engine (lienzo, true);

a continuación, tenemos que crear algunas entidades requeridas para generar una escena completa.:
escena var = new BABYLON.Scene (motor), la luz var = new BABYLON.DirectionalLight ( «dir01», nueva BABYLON.Vector3 (0, -0,5, 1,0), escena); cámara var = new BABYLON.ArcRotateCamera ( «Cámara» , 0, 0, 10, BABYLON.Vector3.Zero (), escena); camera.setPosition (nuevo BABYLON.Vector3 (20, 70, -100)); light.position = new BABYLON.Vector3 (0, 25, – 50); 12345varscene = newBABYLON.Scene (motor); varlight = newBABYLON.DirectionalLight ( «dir01», newBABYLON.Vector3 (0, -0.5,1.0), escena); varcamera = newBABYLON.ArcRotateCamera ( «cámara», 0,0 , 10, BABYLON.Vector3.Zero (), escena); camera.setPosition (newBABYLON.Vector3 (20,70, -100)); light.position = newBABYLON.Vector3 (0,25, -50);

la escena, una luz y una cámara para definir el punto de vista del usuario. Nada especial aquí.

Por último tenemos que conectar la cámara con el lienzo (para permitir que el usuario controle la cámara) y poner en marcha el bucle de render:
// Rendercamera.attachControl (lienzo); engine.runRenderLoop (function () {scene.render ();}); // Resizewindow.addEventListener ( «redimensionamiento», function () {engine.resize ();}); 1234567891011 // Rendercamera.attachControl (lona); engine.runRenderLoop (function () {scene.render ();}); // Resizewindow.addEventListener ( «cambio de tamaño», la función () {engine.resize ();}); < h3> Creación de la tierra y el fondo

Si lanzamos nuestra aplicación en este momento, será un poco vacía. De hecho, existe no para visualizar

Vamos a añadir el suelo y el fondo para crear algo como esto:


La planta se generará con BABYLON.Mesh.CreateGround (!!) y el fondo con BABYLON.Mesh.CreatePlane
var playgroundSize = 100; // Backgroundvar fondo = BABYLON.Mesh.CreatePlane ( «fondo», playgroundSize, escena, false); background.material = new BABYLON.StandardMaterial ( «fondo», escena); background.scaling.y = 0,5 ; background.position.z = playgroundSize / 2 – 0,5; background.position.y = playgroundSize / 4; var backgroundTexture = BABYLON.DynamicTexture nuevo ( «textura dinámica», 512, escena, true); background.material.diffuseTexture = backgroundTexture ; background.material.specularColor = nuevo BABYLON.Color3 (0, 0, 0); background.material.backFaceCulling = false; backgroundTexture.drawText ( «Eternalcoding», null, 80, «bold 70 píxeles Segoe interfaz de usuario», «blanco», «# 555555»); backgroundTexture.drawText ( «- – navegadores estadísticas», null, 250, «35px Segoe interfaz de usuario», «blanco», null); // planta var = BABYLON.Mesh.CreateGround suelo ( «tierra», playgroundSize, playgroundSize, 1, escena, false); var groundMaterial = new BABYLON.StandardMaterial ( «tierra», escena); groundMaterial.diffuseColor = new BABYLON.Color3 (0.5, 0.5, 0.5); gr oundMaterial.specularColor = new BABYLON.Color3 (0, 0, 0); ground.material = groundMaterial; ground.position.y = -0,1; 123456789101112131415161718192021222324varplaygroundSize = 100; // Backgroundvarbackground = BABYLON.Mesh.CreatePlane ( «fondo», playgroundSize , escena, false); background.material = newBABYLON.StandardMaterial ( «fondo», escena); background.scaling.y = 0,5; background.position.z = playgroundSize / 2-0.5; background.position.y = playgroundSize / 4 ; varbackgroundTexture = newBABYLON.DynamicTexture ( «textura dinámica», 512, escena, true); background.material.diffuseTexture = backgroundTexture; background.material.specularColor = newBABYLON.Color3 (0,0,0); background.material.backFaceCulling = falsa; backgroundTexture.drawText ( «Eternalcoding», null, 80, «negrita 70px Segoe interfaz de usuario», «blanco», «# 555555»); backgroundTexture.drawText ( «- – estadísticas navegadores», null, 250, «35px Segoe UI «, «blanco», null); // Ground varground = BABYLON.Mesh.CreateGround ( «tierra», playgroundSize, playgroundSize, 1, escena, false); vargroundMaterial = newBABYLON.StandardM aterial ( «tierra», escena); groundMaterial.diffuseColor = newBABYLON.Color3 (0.5,0.5,0.5); groundMaterial.specularColor = newBABYLON.Color3 (0,0,0); ground.material = groundMaterial; ground.position.y = -0.1;

el principal punto a tener en cuenta es el uso de un BABYLON.DynamicTexture : Este objeto le permite dibujar en una textura con un lienzo. También hay algunas funciones útiles como drawText para simplificar las tareas complejas. En lugar de utilizar drawText que podría haber escrito el siguiente código (por el simple hecho de comprensión ):
BABYLON.DynamicTexture.prototype.drawText = función (texto, x, y, fuente, color, clearColor, invertY) {tamaño var = this.getSize (); si (clearColor) {this._context.fillStyle = clearColor; this._context.fillRect (0, 0, Tamano.Width, size.height); } This._context.font = fuente; si (x === null) {var TEXTSIZE = this._context.measureText (texto); x = (Tamano.Width – textSize.width) / 2; } This._context.fillStyle = color; this._context.fillText (texto, x, y); this.update (invertY); }; 123456789101112131415161718BABYLON.DynamicTexture.prototype.drawText = función (texto, x, y, fuente, color, clearColor, invertY) {VARSIZE = this.getSize (); si (clearColor) {this._context.fillStyle = clearColor; esto. _context.fillRect (0,0, Tamano.Width, size.height);} this._context.font = fuente; si (x === null) {vartextSize = this._context.measureText (texto); x = (tamaño .width-textSize.width) / 2;} this._context.fillStyle = color; this._context.fillText (texto, x, y); this.update (invertY);};

Como se puede ver esto es un código 2D lona regular.

Adición de datos de la serie

Ahora es el momento de añadir algunos datos a la pantalla. Para no complicar las cosas, vamos a considerar datos estáticos pero, obviamente, que son libres de utilizar los datos dinámicos:
browsers_Series var = [{label: «IE», valor: 32, color: nuevo BABYLON.Color3 (0, 0, 1)}, {label: «Chrome», valor: 28, color: nuevo BABYLON.Color3 (1, 0, 0)}, {label: «Firefox», valor: 16, color: nuevo BABYLON.Color3 (1, 0, 1)}, {label: «Opera», valor: 14, color: nuevo BABYLON.Color3 ( 1, 1, 0)}, {label: «Safari», valor: 10, color: nuevo BABYLON.Color3 (0, 1, 1)}]; 1234567varbrowsers_Series = [{label: «IE», valor: 32, color : newBABYLON.Color3 (0,0,1)}, {label: «Chrome», valor: 28, color: newBABYLON.Color3 (1,0,0)}, {label: «Firefox», valor: 16, color : newBABYLON.Color3 (1,0,1)}, {label: «Opera», valor: 14, color: newBABYLON.Color3 (1,1,0)}, {label: «Safari», valor: 10, color :. newBABYLON.Color3 (0,1,1)}];

Cada entrada se compone de una etiqueta, un valor (que es un porcentaje) y un color

Para mostrarlos, tenemos que añadir una nueva función en nuestro código:
createSeries var = función (series) {margin var = 2; var offset = playgroundSize / (series.length) – margen; var x = -playgroundSize / 2 + offset / 2; para (índice var = 0; índice & lt; series.length; índice ++) {datos var = serie [Índice]; bar var = BABYLON.Mesh.CreateBox (data.label, 1,0, escena, false); bar.scaling = new BABYLON.Vector3 (offset / 2,0, data.value escala *, offset / 2,0); bar.position.x = x; bar.position.y = data.value * escala / 2,0; // material bar.material = new BABYLON.StandardMaterial (data.label + «mat», escena); bar.material.diffuseColor = data.color; bar.material.emissiveColor = data.color.scale (0,3); bar.material.specularColor = nuevo BABYLON.Color3 (0, 0, 0); // Going siguiente x + = OFFSET + margen; }}; 1234567891011121314151617181920212223varcreateSeries = función (series) {varmargin = 2; varoffset = playgroundSize / (series.length) -margin; varX = -playgroundSize / 2 + offset / 2; para (varindex = 0; índice & lt; series.length; índice ++ ) {Vardata = series [índice]; varbar = BABYLON.Mesh.CreateBox (data.label, 1,0, escena, false); bar.scaling = newBABYLON.Vector3 (offset / 2,0, data.value escala *, offset / 2,0) ; bar.position.x = x; bar.position.y = data.value * escala / 2,0; // Materialbar.material = newBABYLON.StandardMaterial (+ «mat», escena data.label); bar.material.diffuseColor = datos .color; bar.material.emissiveColor = data.color.scale (0,3); bar.material.specularColor = newBABYLON.Color3 (0,0,0); // ir nextx + = OFFSET + margen;}};

para cada entrada, creamos una caja asociada con un material de color. El cuadro se escala a continuación, dependiendo del valor de la entrada. El resultado es la siguiente pantalla:


Sombras

La pantalla anterior puede parecer un poco plana. Podemos mejorar las cosas mediante la adición de sombras dinámicas .

En tiempo real sombras son complejos para producir (lo que necesita para crear un mapa de sombras y luego utilizarlo en sus shaders). Pero con babylon.js, sólo hay que crear un BABYLON.ShadowGenerator y definir qué objetos sombras proyectadas y que los objetos reciben sombras:
// Shadowsvar shadowGenerator = new BABYLON.ShadowGenerator (1024, luz); ground.receiveShadows = true; background.receiveShadows = true; 1234 // ShadowsvarshadowGenerator = newBABYLON.ShadowGenerator (1024, luz); ground.receiveShadows = true; background.receiveShadows = true;

para las sombras proyectadas, las cajas deben ser añadidos a la shadowGenerator objeto:
. ShadowGenerator.getShadowMap () renderList.push (bar); 1shadowGenerator.getShadowMap () renderList.push (bar);.?

El resultado es más bonito, ¿verdad?


Adición de la leyenda

Hay un problema con nuestra carta: nadie puede decir el valor y la etiqueta asociada de cada caja. Por eso tenemos que añadir una leyenda.

Cada cuadro se asocia con un pequeño avión con una textura dinámica llena de la etiqueta y el valor de la entrada actual:


Para ello, tenemos que actualizar nuestro createSeries función con el fin de generar una leyenda para cada entrada:
// Legendvar barLegend = BABYLON.Mesh.CreateGround (data.label + «Legend», playgroundSize / 2, offset * 2, 1, escena, false); barLegend.position.x = x; barLegend.position.z = -playgroundSize / 4; barLegend.rotation.y = Math.PI / 2; barLegend.material = new BABYLON.StandardMaterial (data.label + «LegendMat», escena); var barLegendTexture = BABYLON.DynamicTexture nuevo ( «textura dinámica», 512, escena, true); barLegendTexture.hasAlpha = true; barLegend.material.diffuseTexture = barLegendTexture; barLegend.material.emissiveColor = new BABYLON.Color3 (0.4, 0.4, 0.4); tamaño var = barLegendTexture.getSize (); barLegendTexture.drawText ( data.label + «(» + data.value + «%)», 80, size.height / 2 + 30, «bold 50px Segoe interfaz de usuario», «blanco», «transparente», false); 123456789101112131415 // LegendvarbarLegend = BABYLON.Mesh.CreateGround (data.label + «Legend», playgroundSize / 2, offset * 2,1, escena, false); barLegend.position.x = x; barLegend.position.z = -playgroundSize / 4; barLegend.rotation .y = Math.PI / 2; barLegend.material = newBABYLON.StandardMater ial (data.label + «LegendMat», escena); varbarLegendTexture = newBABYLON.DynamicTexture ( «textura dinámica», 512, escena, true); barLegendTexture.hasAlpha = true; barLegend.material.diffuseTexture = barLegendTexture; barLegend.material.emissiveColor = newBABYLON.Color3 (0.4,0.4,0.4); VARSIZE = barLegendTexture.getSize (); barLegendTexture.drawText (data.label + «( «+ data.value +» %)», 80, size.height / 2 + 30, «bold 50px Segoe interfaz de usuario», «blanco», «transparente», false);

aspersión de un poco de animaciones

Finalmente, para el efecto “waoouh”, sugiero que podemos animar las cajas: Se comenzará con una altura de 0 y crecerán hasta su valor efectivo:
bar var = BABYLON.Mesh.CreateBox (data.label, 1,0, escena, false); bar.scaling = new BABYLON.Vector3 (offset / 2,0, 0, offset / 2,0); bar.position.x = x; bar. position.y = 0; // animar una animación bitvar = new BABYLON.Animation ( «anim», «ampliación», 30, BABYLON.Animation.ANIMATIONTYPE_VECTOR3); animation.setKeys ([{frame: 0, valor: nueva Babilonia. Vector3 (offset / 2,0, 0, offset / 2,0)}, {frame: 100, valor: nuevo BABYLON.Vector3 (offset / 2,0, data.value escala *, offset / 2,0)}]); bar.animations.push ( animación); animación = new BABYLON.Animation ( «anim2», «position.y», 30, BABYLON.Animation.ANIMATIONTYPE_FLOAT); animation.setKeys ([{frame: 0, valor: 0}, {frame: 100, valor : (data.value escala *) / 2}]); bar.animations.push (animación); scene.beginAnimation (bar, 0, 100, falso, 2,0); 123456789101112131415161718varbar = BABYLON.Mesh.CreateBox (data.label, 1,0, escena, false); bar.scaling = newBABYLON.Vector3 (offset / 2.0,0, offset / 2,0); bar.position.x = x; bar.position.y = 0; // animar un bitvaranimation = newBABYLON. animación ( «una nim», «ampliación», 30, BABYLON.Animation.ANIMATIONTYPE_VECTOR3); animation.setKeys ([{frame: 0, valor: newBABYLON.Vector3 (offset / 2.0,0, offset / 2,0)}, {frame: 100, valor : newBABYLON.Vector3 (offset / 2,0, data.value escala *, offset / 2,0)}]); bar.animations.push (animación); animación = newBABYLON.Animation ( «anim2», «position.y», 30, BABYLON.Animation.ANIMATIONTYPE_FLOAT); animation.setKeys ([{frame: 0, valor: 0}, {frame: 100, valor: (data.value escala *) / 2}]); bar.animations.push (animación) ; scene.beginAnimation (bar, 0100, falso, 2,0);

puede observar que creamos dos animaciones: una para el escalado y uno para la posición (el pivote de cada caja está en el medio de la malla). El scene.beginAnimation se usa para iniciar la animación.

Nada compleja aquí, pero un efecto fresco para el usuario

Conclusión

Si quieres ir más lejos, se puede considerar la incorporación de este código en un control y trabajo con datos dinámicos para lograr una forma realmente Mente-lowing de datos de visualización.

Mensajes relacionados

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *