Animating textures in WebGL

En esta demostraci√≥n nos basamos en el ejemplo anterior, solo que ahora reemplazaremos nuestra textura est√°tica con los fotogramas de un video Ogg.

Esto es de hecho muy f√°cil de entender y de hacer, as√≠ que vamos a empezar. 

Podemos utilizar un c√≥digo similar para usar, como fuente para las texturas, otros tipos de datos tales como <canvas>.

Obteniendo acceso al video

El primer paso es a√Īadir el HTML para crear el elemento <video> que usaremos para obtener los fotogramas de video:

<video id="video">
  Parece ser que tu navegador no soporta el elemento HTML5. <code>&lt;video&gt;</code>
</video>

Esto simplemente crea un elemento para reproducir el archivo de video "Firefox.ogv". Usaremos CSS para ocultar el video

video {
  display: none;
}

Ahora pasamos al c√≥digo JavasScript, empezando por a√Īadir una l√≠nea de c√≥digo a la funci√≥n start() para obtener la referencia al elemento de video:

videoElement = document.getElementById("video");

Y reemplazamos el código que configura las llamadas de "interval-driven" en drawScecene() por esto:

videoElement.addEventListener("canplaythrough", startVideo, true);
videoElement.addEventListener("ended", videoDone, true);

Finalmente configuramos el atributo src para empezar a cargar el video. FIXME (bjacob): Tambi√©n se debe configurar preload="auto" o si no, el video nunca ejecuta canplaythrough en Firefox. En Chrome se deber√≠a cargar el video aun sin usar preload="auto".

video.preload = "auto";
videoElement.src = "Firefox.ogv";

El objetivo aqu√≠ es no empezar la animaci√≥n hasta que una parte suficiente del video se haya cargado de modo que pueda ser reproducido sin interrupciones. Para esto a√Īadimos un event listener para esperar a que el elemento de video nos diga que ya ha cargado los suficientes datos como para reproducir el video puede ser reproducido sin pausas.

The startVideo() quedar√° as√≠:

function startVideo() {
  videoElement.play();
  intervalID = setInterval(drawScene, 15);
}

Esto simplemente reproduce el video, entonces establece las llamadas "interval-driven" a drawScene() para gestionar el renderizado del cubo.

A√Īadiremos tambi√©n un segundo event listener en el "ended" del video de modo que cuando el video haya finalizado de reproducirse nosotros podamos parar la animaci√≥n.

function videoDone() {
  clearInterval(intervalID);
}

La funci√≥n de videoDone() simplemente llama a window.clearInterval()  para terminar de llamar a la funci√≥n de actualizar la animaci√≥n.

Usando los fotogramas del video como textura

El siguiente paso es initTexture(), el cual se ha vuelto mucho más simple desde que no es necesario cargar un archivo de imagen. En lugar de esto, todo lo que vamos a hacer es crear un objeto de textura vacío para configurar el filtering cuando lo usemos más tarde:

function initTextures() {
  cubeTexture = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D, cubeTexture);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
}
La funci√≥n updateTexture() quedar√≠a as√≠; Aqu√≠ es donde se realiza el trabajo real.
function updateTexture() {
  gl.bindTexture(gl.TEXTURE_2D, cubeTexture);
  gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA,
        gl.UNSIGNED_BYTE, videoElement);
}

Has visto este c√≥digo antes. Es pr√°cticamente id√©ntico a la rutina de handleTextureLoaded() en el ejemplo anterior, excepto que cuando llamamos a texImage2D() en lugar de pasarle un objeto Image, lo pasamos en el elemento <video>. Ya que WebGL sabe como obtener el fotograma actual y usarlo como textura.

updateTexture() se llama cada vez que estamos preparados para que la funci√≥n drawScene() redibuje la escena. La √ļnica diferencia es que a√Īadimos la llamada de updateTexture() antes de hacer nada m√°s.

¬°Esto es todo al respecto!

Ver el código completo | Abrir esta demo en una nueva página

Artículos relacionados