Your Search Results

    Animating textures in WebGL

    今回のデモンストレーションでは、前回の例で用いた静的なテクスチャを Ogg ビデオファイルのフレームに置き換えます。実はこれを行うのはとても簡単ですが、見ていて楽しいです。さっそく始めましょう。なお同様のコードを、どんな種類のデータ (<canvas> など) をテクスチャのソースとして用いる場合でも使用することができます。

    ビデオへのアクセスを得る

    始めに、ビデオフレームを取り出すのに使う <video> 要素を作成する HTML を追加します:

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

    これは単純に、ビデオファイル "Firefox.ogv" を再生する要素を作成します。この video 要素が表示されないようにするため、以下の CSS を使用します:

    video {
      display: none;
    }
    

    続いて、JavaScript のコードに注意を向けます。まずは start() 関数に、video 要素への参照を取得するコードを追加します:

    videoElement = document.getElementById("video");
    

    次に、インターバル駆動による drawScene() の呼び出しを設定しているコードを以下のコードに置き換えます:

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

    これには、ビデオの再生が中断されないよう充分にバッファリングされるまではアニメーションを始めたくないという考え方があります。そこで、 データが充分にバッファリングされてビデオが切れ目なく再生できると期待できることを、video 要素が通知するまで待つためのイベントリスナを追加します。また、ビデオの再生が終わったときにアニメーションを停止できるように、2 番目のイベントを追加します。そうしなければ、正当な理由がないのに CPU 時間を浪費することになってしまうためです。

    startVideo() 関数は以下のようにします:

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

    これは単にビデオの再生を開始して、キューブの描画を制御するために drawScene() のインターバル駆動による呼び出しを定義します。

    videoDone() 関数は単純に、アニメーションの更新を終わらせるために window.clearInterval() を呼び出します。

    ビデオフレームをテクスチャとして用いる

    次に変更するのは initTexture() です。画像ファイルを読み込む必要がなくなったため、とても単純になります。画像を読み込む代わりに、後で使う空のテクスチャオブジェクトを作成します:

    function initTextures() {
      cubeTexture = gl.createTexture();
    }
    

    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);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
      gl.generateMipmap(gl.TEXTURE_2D);
      gl.bindTexture(gl.TEXTURE_2D, null);
    }
    

    このコードは、以前見たことがあります。これは以前の例にあった handleTextureLoaded() ルーチンとほぼ同じであり、texImage2D()を呼び出すときに Image オブジェクトに代わり <video> 要素を渡すところが異なります。WebGL は現在のフレームを取り出して、それをテクスチャとして使用する方法がわかります。

    updateTexture() はシーンを再描画する準備が整ったときに毎回、drawScene() によって呼び出されます。drawScene() の唯一の変更点は、処理の最初に updateTexture() の呼び出しを追加することです。

    以上で完了です! WebGL 対応のブラウザを使用している場合は、こちらをクリックして デモを実行することができます。

    参考情報

    Document Tags and Contributors

    Contributors to this page: ethertank, yyss
    最終更新者: ethertank,