MDN’s new design is in Beta! A sneak peek: https://blog.mozilla.org/opendesign/mdns-new-design-beta/

这篇翻译不完整。请帮忙从英语翻译这篇文章

在本篇介绍中,我们基于上一个例子编译构建,用播放 Ogg 视频文件的帧来替换我们静态的纹理。这实际上很简单,但是看起来很有趣,所以我们开始吧。类似的代码可以是任何近似的数据 (例如 <canvas>)作为我们纹理的资源。

获取视频

第一步是创建一个 <video> 元素, 我们将从这个元素获取视频帧:

<video id="video">
  Your browser doesn't appear to support the HTML5 <code>&lt;video&gt;</code> element.
</video>

这里简单的创建一个元素来播放视频文件 "Firefox.ogv",我们使用CSS将这个video元素隐藏。

video {
  display: none;
}

接着我们将注意力转到Javascript代码上,通过对 start() 函数添加一行获取video元素的代码开始:

videoElement = document.getElementById('video');

我们将之前的 drawScene() 改为由事件驱动:

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

最后我们给video元素设置src属性让它开始加载。

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

这里思路是,直到视频缓冲到可以持续播放之后才开始动画。 因此,我们添加一个事件侦听器等待视频元素告诉我们,它已经缓冲了足够的数据,整个视频可以持续播放而不会暂停。

startVideo() 函数的实现:

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

这只是开始播放视频,然后通过时间间隔驱动(interval-driven)调用 drawScene() 来渲染立方体。

我们还添加了第二个事件监听器的视频的 "ended" 事件,这样当视频完成播放,我们就可以停止动画,让它不浪费处理器的时间。

function videoDone() {
  clearInterval(intervalID);
}

videoDone() 方法是通过调用 window.clearInterval()  来结束动画的更新。

用视频帧作为纹理 

接下来的变化的是 initTexture() 变得更简单,它不需要加装图片文件,他只需要创建一个空的纹理对象,并设置其过滤以供之后使用:

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);
}
下面这里就是 updateTexture(),到这里我们就完成了纹理的映射。
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);
}

上面的代码与前面示例中的 handleTextureLoaded() 几乎相同,不同的在于我们调用texImage2D(),传入的不是一个 Image 对象,而是  <video> 对象。 WebGL知道如何将当前帧拉出并把它用作纹理。

每当准备好重绘我们的场景时,drawScene() 函数会调用 updateTexture( ),唯一的不同的是我们可以在调用updateTexture() 之前做任何事情。

That's all there is to it!

View the complete code | Open this demo on a new page

参考

文档标签和贡献者

 此页面的贡献者: Awe, liuzheng644607, Gaohaoyang
 最后编辑者: Awe,