Índice de contenido

  • Motivación
  • Definiciones básicas
  • Introducción
  • SVG
  • CSS3D
  • Canvas
  • Canvas 2D
  • WebGL
  • OpenGL ES
  • Three.js
  • Stage3D
  • Conclusiones
  • Repositorios

Motivación

Definiciones básicas

  • Biblioteca
  • API
  • XML
  • HTML
  • DOM
  • CSS
  • JavaScript
  • Flash
  • ActionScript
  • OpenGL
  • Shader
  • GLSL

Introducción

  • La Web se ha caracteriza por ser un medio visual
  • CSS y JavaScript para crear animaciones o efectos visuales
  • Recurrir a complementos como Flash
  • Con la introducción de HTML5 emergen nuevas opciones:
    • SVG
    • Transformaciones 3D de CSS3
    • Canvas 2D
    • WebGL
  • Los motores de JavaScript actuales son lo suficientemente rápidos
  • La aceleración por hardware se está implementando en muchos navegadores
  • Tendencia al uso de aplicaciones Web y moviles

¿Qué opción es más conveniente?

  • Depende de lo que quieras hacer
  • Compatibilidad
  • Rendimiento
  • Mantenibilidad
  • Facilidad de aprendizaje

SVG

  • Scalable Vector Graphics
  • Especificación para describir gráficos vectoriales bidimensionales
  • XML
  • Estáticos o animados
  • Compatible con la mayoría de las últimas versiones de todos los navegadores
  • Herramientas para construcción de contenido
    • Illustrator
    • Inkscape
  • Permite tres tipos de objetos gráficos
    • Elementos geométricos vectoriales
    • Imágenes de mapa de bits digitales
    • Texto

SVG

<html>
  <body>
    <h1>My first SVG</h1>
    <svg width="100" height="100">
      <circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
    </svg>
  </body>
</html>

SVG

CSS3D

  • Ubicar y animar elementos usando transformaciones 3D
  • Compatible con la mayoría de las últimas versiones de todos los navegadores
  • Propiedades
    • transform
    • transform-style
    • perspective
    • Entre otras
  • Métodos de transformación
    • scale3d(x,y,z)
    • rotate3d(x,y,z,angle)
    • translate3d(x,y,z)
    • Entre otros

CSS3D

#blue {
  perspective: 200px;
  perspective-origin: 50% 50%;
}

#blue .box {
  background-color: blue;
  transform: rotateY( 12deg );
}

.container {
  width: 200px;
  height: 200px;
  border: 1px solid #CCC;
  margin: 0 auto 40px;
}

.box {
  width: 100%;
  height: 100%;
}

CSS3D

Canvas 2D

  • API para dibujado 2D
  • Compatible con las últimas versiones de todos los navegadores
  • Popular
  • Se puede usar también para 3D pero no es recomendable
  • Acelaración por hardware limitada
  • Sprites, rellenado, gradientes, texto, etc
window.onload = function() {
  var canvas = document.getElementById("myCanvas");
  var context = canvas.getContext("2d");
  // draw stuff here
  context.fillStyle = "#FF0000";
  context.fillRect(0,0,150,75);
};
<!DOCTYPE HTML>
<html>
  <head></head>
  <body>
    <canvas id="myCanvas" width="578" height="200"></canvas>
  </body>
</html>

Canvas 2D

WebGL

  • API JavaScript para despliegue interactivo de gráficos en 2D y 3D
  • Sirve en cualquier navegador compatible
  • OpenGL ES 2.0
  • GLSL 1.0 Vertex y Fragment shaders
  • Aceleración por hardware
  • Mantenida por el grupo Khronos

OpenGL ES

  • OpenGL for Embedded Systems
  • Variante simplificada de la API gráfica OpenGL
  • Diseñada para dispositivos integrados
  • Teléfonos móviles, tablets, PDAs y consolas de videojuegos
  • OpenGL ES 1.0
    • Gran parte de la funcionalidad de la API original fue eliminada
    • Se añadió también alguna
    • Eliminación de glBegin glEnd
    • Vertex arrays
    • No se da soporte a texturas 3D, display lists, etc
  • OpenGL ES 1.1
    • Soporte obligatorio de multi-texturas
    • Vertex buffer objects
    • Compatible con la versión 1.0

OpenGL ES

  • OpenGL ES 2.0
    • Elimina casi toda la funcionalidad fija
    • Reemplazadas por unidades programables escritas en GLSL
    • No es compatible con OpenGL ES 1.1
  • OpenGL ES 3.0 y 3.1
    • Compatible con la versión 2.0
    • Nuevas funcionalidades
Desplegar un cubo y una pirámide
Biblioteca glMatrix para manejo de matrices

WebGL

Vertex shader

<script id="shader-vs" type="x-shader/x-vertex">
    attribute vec3 aVertexPosition;
    attribute vec4 aVertexColor;

    uniform mat4 uMVMatrix;
    uniform mat4 uPMatrix;

    varying vec4 vColor;

    void main(void) {
        gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
        vColor = aVertexColor;
    }
</script>

WebGL

Fragment shader

<script id="shader-fs" type="x-shader/x-fragment">
    precision mediump float;

    varying vec4 vColor;

    void main(void) {
        gl_FragColor = vColor;
    }
</script>

WebGL

Inicialización del contexto

var gl;

function initGL(canvas) {
    try {
        gl = canvas.getContext("experimental-webgl");
        gl.viewportWidth = canvas.width;
        gl.viewportHeight = canvas.height;
    } catch (e) {
    }
    if (!gl) {
        alert("Could not initialise WebGL, sorry D:");
    }
}

WebGL

Compilación de un shader

function getShader(gl, id) {
    var shaderScript = document.getElementById(id);
    if (!shaderScript) {
        return null;
    }

    var str = "";
    var k = shaderScript.firstChild;
    while (k) {
        if (k.nodeType == 3) {
            str += k.textContent;
        }
        k = k.nextSibling;
    }

    var shader;
    if (shaderScript.type == "x-shader/x-fragment") {
        shader = gl.createShader(gl.FRAGMENT_SHADER);
    } else if (shaderScript.type == "x-shader/x-vertex") {
        shader = gl.createShader(gl.VERTEX_SHADER);
    } else {
        return null;
    }

    // ...

WebGL

Compilación de un shader

gl.shaderSource(shader, str);
    gl.compileShader(shader);

    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        alert(gl.getShaderInfoLog(shader));
        return null;
    }

    return shader;
}

WebGL

Programa GLSL

var shaderProgram;

function initShaders() {
    var fragmentShader = getShader(gl, "shader-fs");
    var vertexShader = getShader(gl, "shader-vs");

    shaderProgram = gl.createProgram();
    gl.attachShader(shaderProgram, vertexShader);
    gl.attachShader(shaderProgram, fragmentShader);
    gl.linkProgram(shaderProgram);

    if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
        alert("Could not initialise shaders");
    }

    gl.useProgram(shaderProgram);

    // ...

WebGL

Atributos y uniformes

    // Se agregan como atributos a shaderProgram por comodidad

    shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
    gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);

    shaderProgram.vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor");
    gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute);

    shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
    shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
}

WebGL

Buffers

function initBuffers() {
  var vertices = [...];
  var cubeVertexIndices = [...];

  cubeVertexPositionBuffer = gl.createBuffer();

  cubeVertexPositionBuffer.itemSize = 3;
  cubeVertexPositionBuffer.numItems = 24;
  
  gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
  gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 
                         cubeVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
  
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

  cubeVertexIndexBuffer = gl.createBuffer();

  cubeVertexIndexBuffer.itemSize = 1;
  cubeVertexIndexBuffer.numItems = 36;
  
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(cubeVertexIndices), gl.STATIC_DRAW);
        
  // Similar para la piramide
}

WebGL

Despliegue de la escena

function drawScene() {
  gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

  // Transformaciones

  gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
  gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);

  gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);

  gl.drawElements(gl.TRIANGLES, cubeVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);

  // Similar para la piramide
}

WebGL

Ciclo principal

function tick() {
    requestAnimFrame(tick);
    drawScene();
    animate();
}

function webGLStart() {
  var canvas = document.getElementById("canvas-example");
  fitToContainer(canvas);
  initGL(canvas);
  initShaders()
  initBuffers();

  gl.clearColor(0.0, 0.0, 0.0, 1.0);
  gl.enable(gl.DEPTH_TEST);

  tick();
}

WebGL

Agregar una cámara a la escena

WebGL

Cámara

  • Varia según el efecto deseado
  • Uso de bibliotecas de terceros
  • Bloqueo de puntero
  • Actualizar en el ciclo principal
  • Obtener matriz de vista

WebGL

WebGL

Otras funcionalidades

WebGL

WebGL

Angle

  • Almost Native Graphics Layer Engine
  • Motor gráfico
  • Capa de abstracción
  • Brindar alto rendimiento en Windows
  • Traduce llamadas OpenGL a Direct3D
  • Usado por Chrome, Firefox y Qt
Mi experiencia con WebGL
Trazado de Rayos en Tiempo Real en GPU

WebGL

WebGL

Bibliotecas

  • Resulta dificil
  • Requiere conocimientos específicos
  • Varias bibliotecas surgen para resolver este problema
    • C3DL
    • O3D
    • PhiloGL
    • SpiderGL
    • CopperLicht
    • Babylon.js
    • Three.js

Three.js

  • Biblioteca en JavaScript
  • Desplegar gráficos en 3D
  • Puede ser usada con:
    • Canvas 2D
    • WebGL
    • SVG
    • CSS3D
  • El cubo y la pirámide con WebGL abarcaron varias líneas de código
  • Un equivalente en Three.js son muchas menos líneas
Desplegar un cubo

Three.js

<html>
  <head>
    <title>My first Three.js app</title>
    <style>canvas { width: 100%; height: 100% }</style>
    <script src="js/three.min.js"></script>
  </head>
  <body>
</html>

Three.js

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);

var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

var geometry = new THREE.BoxGeometry(1,1,1);
var material = new THREE.MeshBasicMaterial({color: 0x00ff00});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);

camera.position.z = 3;

var render = function () {
  requestAnimationFrame(render);

  cube.rotation.x += 0.1;
  cube.rotation.y += 0.1;

  renderer.render(scene, camera);
};

render();

Three.js

Compatibilidad

Stage3D

  • API en Adobe Flash Player
  • Desplegar gráficos en 3D con acelaración en GPU
  • Aplicaciones y juegos Flash
  • ActionScript 3
  • AGAL Vertex y Fragment shaders
  • Adobe Graphics Assembly Language
  • Uso de buffers

Conclusiones

  • Diferentes opciones
  • Elegir la más conveniente para el caso
  • Creación de aplicaciones y juegos
  • Era móvil
  • Estandares abiertos

Repositorios

Gracias

Información de contacto: