In this demonstration, we build upon the previous example by replacing our static textures with the frames of an mp4 video file that's playing. This is actually pretty easy to do and fun to watch, so let's get started. You can use similar code to use any sort of data (such as a <canvas> ) as the source for your textures.

此范例使用 glMatrix library to perform its matrix and vertex math. You'll need to include it if you create your own project based on this code. Our sample loads a copy from a CDN in our HTML's <head> .

Getting access to the video

The first step is to create the <video> element that we'll use to retrieve the video frames:

// will set to true when video can be copied to texture
var copyVideo = false;
function setupVideo(url) {
  const video = document.createElement('video');
  var playing = false;
  var timeupdate = false;
  video.autoplay = true;
  video.muted = true;
  video.loop = true;
  // Waiting for these 2 events ensures
  // there is data in the video
  video.addEventListener('playing', function() {
     playing = true;
     checkReady();
  }, true);
  video.addEventListener('timeupdate', function() {
     timeupdate = true;
     checkReady();
  }, true);
  video.src = url;
  video.play();
  function checkReady() {
    if (playing && timeupdate) {
      copyVideo = true;
    }
  }
  return video;
}
						

First we create a video element. We set it to autoplay, mute the sound, and loop the video. We then set up two events to make sure the video is playing and the time has been updated. We need both of these checks because it will produce an error if you upload a video to WebGL that has no data available yet. Checking for both of these events guarantees there is data available and it's safe to start uploading video to a WebGL texture. In the code above, we confirm whether we got both of those events; if so, we set a global variable, copyVideo , to true to indicate that it's safe to start copying the video to a texture.

And finally, we set the src attribute to start and call play to start loading and playing the video.

The video must be loaded from a secure source in order to be used to provide texture data to WebGL. That means that you'll not only need to deploy code like using a secure web server, but you'll need a secure server to test with as well. See How do you set up a local testing server? for help.

Using the video frames as a texture

The next change is to initTexture() , which becomes much simpler, since it no longer needs to load an image file. Instead, all it does is create an empty texture object, put a single pixel in it, and set its filtering for later use:

function initTexture(gl) {
  const texture = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D, texture);
  // Because video has to be download over the internet
  // they might take a moment until it's ready so
  // put a single pixel in the texture so we can
  // use it immediately.
  const level = 0;
  const internalFormat = gl.RGBA;
  const width = 1;
  const height = 1;
  const border = 0;
  const srcFormat = gl.RGBA;
  const srcType = gl.UNSIGNED_BYTE;
  const pixel = new Uint8Array([0, 0, 255, 255]);  // opaque blue
  gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
                width, height, border, srcFormat, srcType,
                pixel);
  // Turn off mips and set  wrapping to clamp to edge so it
  // will work regardless of the dimensions of the video.
  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);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  return texture;
}
						
Here's what the updateTexture() function looks like; this is where the real work is done:
function updateTexture(gl, texture, video) {
  const level = 0;
  const internalFormat = gl.RGBA;
  const srcFormat = gl.RGBA;
  const srcType = gl.UNSIGNED_BYTE;
  gl.bindTexture(gl.TEXTURE_2D, texture);
  gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
                srcFormat, srcType, video);
}
						

You've seen this code before. It's nearly identical to the image onload function in the previous example — except when we call texImage2D() , instead of passing an 图像 object, we pass in the <video> element. WebGL knows how to pull the current frame out and use it as a texture.

Then in main() in place of the call to loadTexture() in the previous example, we call initTexture () followed by setupVideo() .

In the definition of render() if copyVideo is true, then we call updateTexture() each time just before we call the drawScene() 函数。

  const texture = initTexture(gl);
  const video = setupVideo('Firefox.mp4');
  var then = 0;
  // Draw the scene repeatedly
  function render(now) {
    now *= 0.001;  // convert to seconds
    const deltaTime = now - then;
    then = now;
    if (copyVideo) {
      updateTexture(gl, texture, video);
    }
    drawScene(gl, programInfo, buffers, texture, deltaTime);
    requestAnimationFrame(render);
  }
  requestAnimationFrame(render);
						

That's all there is to it!

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

另请参阅


元数据

  1. WebGL API
  2. WebGL 教程
    1. Getting started with WebGL
    2. Adding 2D content to a WebGL context
    3. Using shaders to apply color in WebGL
    4. Animating objects with WebGL
    5. Creating 3D objects using WebGL
    6. Using textures in WebGL
    7. Lighting in WebGL
    8. Animating textures in WebGL
  3. Examples and articles
    1. Matrix math for the web
    2. WebGL model view projection
    3. WebGL best practices
    4. 使用 WebGL 扩展
    5. A basic 2D WebGL animation example
    6. WebGL by example
  4. 接口
    1. WebGLRenderingContext
    2. WebGL2RenderingContext
    3. WebGLActiveInfo
    4. WebGLBuffer
    5. WebGLContextEvent
    6. WebGLFramebuffer
    7. WebGLProgram
    8. WebGLQuery
    9. WebGLRenderbuffer
    10. WebGLSampler
    11. WebGLShader
    12. WebGLShaderPrecisionFormat
    13. WebGLSync
    14. WebGLTexture
    15. WebGLTransformFeedback
    16. WebGLUniformLocation
    17. WebGLVertexArrayObject
  5. 文档编制:
  6. 有用清单
    1. Pages tagged "WebGL"
  7. 贡献
    1. WebGL doc status
    2. MDN 工程