はじめに
Managed DirectXには、ビデオやオーディオを再生する機能を集めた「AudioVideoPlayback」という名前空間があります。今回はこの中にある「Video
」というクラスを利用します。
対象読者
言語はC#を利用し、.Net Framework 1.1とManaged DirectXについてのプログラミング環境がある読者を想定しています。
それともう1点、今回はDirect3Dについてはあまり触れません。サンプルのため複雑なことはしていませんが、テクスチャが扱える程度の知識は必要です。Direct3Dについては私のページで説明していますので、分からない点があったときは役に立つかもしれません。
必要な環境
上記の2つの環境が揃っていれば、他に必要なものはありません。
解説内容
今回は2段階で説明を行います。まずは「Video
」を利用した通常のビデオ再生を行い、その後に3Dへの投影を行います。
1. Videoクラスを利用したVideo再生
前準備
AudioVideoPlaybackを利用するためにはまず、「Microsoft.DirectX」と「Microsoft.DirectX.AudioVideoPlayback」を参照に追加する必要があります。
コード
Video
クラスの利用の仕方はきわめて単純です。MCI並です。
- ファイルを開く
- 再生する
この2手順で行えます。
using Microsoft.DirectX.AudioVideoPlayback; Video video_; video_ =new Video("ファイルネーム"); video_.Owner = コントロールをセットする。 video_.Play();
このコードの必要なところを埋めるだけでビデオが再生できます。
2. テクスチャとして利用する
前準備
Direct3Dを利用するので、「Microsoft.DirectX.Direct3D」と「Microsoft.DirectX.Direct3DX」を参照に追加してください。
コード
全体の流れは次のとおりです。
- Direct3Dの初期化
Video
の初期化Video
のコールバック時に描画を行うように設定する。- 再生開始
- 各フレームごとにセットした描画メソッドが呼ばれるので、描画を行う。
/// <summary> /// Dierct3DとVideoの初期化を行う。 /// </summary> private void myInialize() { //デバイスの初期化 PresentParameters pp =new PresentParameters(); pp.Windowed=true; pp.SwapEffect =SwapEffect.Discard; try { //ハードウェア device_ =new Device(0,DeviceType.Hardware,this ,CreateFlags.SoftwareVertexProcessing,pp); } catch { try { //リファレンスで再挑戦 device_ =new Device(0,DeviceType.Reference,this ,CreateFlags.SoftwareVertexProcessing,pp); } catch { MessageBox.Show("Direct3Dの初期化に失敗しました"); return; } } //頂点作成 vertexBuffer_ =new VertexBuffer( typeof(CustomVertex.PositionTextured),4 ,device_,0,CustomVertex.PositionTextured.Format,Pool.Managed); CustomVertex.PositionTextured []verts = new CustomVertex.PositionTextured[4]; verts[0].Position = new Vector3(-1,-1,0); verts[1].Position = new Vector3( 1,-1,0); verts[2].Position = new Vector3(-1, 1,0); verts[3].Position = new Vector3( 1, 1,0); verts[0].Tu=1;verts[0].Tv=1; verts[1].Tu=0;verts[1].Tv=1; verts[2].Tu=1;verts[2].Tv=0; verts[3].Tu=0;verts[3].Tv=0; GraphicsStream gs =vertexBuffer_.Lock(0,0,0); gs.Write(verts); vertexBuffer_.Unlock(); //ビデオ読み込み try { video_ =new Video(@"I:\test.avi"); } catch { MessageBox.Show("ビデオファイルがありません"); return; } //呼び出してもらうメソッドをセットする。 video_.TextureReadyToRender += new TextureRenderEventHandler(video__TextureReadyToRender); //再生を開始する。 video_.RenderToTexture(device_); }
重要なのは最後の2行です。
「TextureReadyToRender
」はVideo
を再生したときにテクスチャが準備できると呼び出されます。よって、これに描画のためのメソッドをくっつければ、ビデオをテクスチャとして利用できます。
「RenderToTexture
」はPlay
のテクスチャ版です。テクスチャを渡して欲しいときは、これを使ってビデオをスタートさせます。
/// <summary> /// Videoからの描画呼び出し /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void video__TextureReadyToRender( object sender, TextureRenderEventArgs e) { //テクスチャをセット device_.SetTexture(0,e.Texture); //ステータスを調整 device_.RenderState.Lighting = false; device_.RenderState.CullMode = Cull.None; device_.Transform.World = Matrix.RotationY(Environment.TickCount/300f); //カメラ設定 device_.Transform.View = Matrix.LookAtLH( new Vector3(0,0,3),new Vector3(0,0,0),new Vector3(0,1,0)); device_.Transform.Projection = Matrix.PerspectiveLH((float)Math.PI / 4f,1,1,100); //クリア device_.Clear(ClearFlags.Target,Color.Gray.ToArgb(),1.0f,0); //描画開始 device_.BeginScene(); device_.SetStreamSource(0,vertexBuffer_,0); device_.VertexFormat = CustomVertex.PositionTextured.Format; device_.DrawPrimitives(PrimitiveType.TriangleStrip,0,2); device_.EndScene(); device_.Present(); }
これがVideo
から呼び出されるメソッドです。「TextureRenderEventArgs
」の中にはテクスチャが入っています。これを使って描画を行えばOKです。
後処理について
このプログラムは[閉じる]ボタンを押しても終了しない可能性があります。対策として、Formがクローズされたときに次の処理を行いましょう。クローズした時に再生が行われる場合はストップする処理です。
private void Form1_Closed(object sender, System.EventArgs e) { if(video_ !=null) { video_.Stop(); video_.Dispose(); } if(device_!=null) { device_.Dispose(); } }
まとめ
今回はテクスチャをただUVマッピングで貼り付けただけでしたが、ピクセルシェーダーを使ってリアルタイムエフェクトをかけながら動画を再生すると、もっと面白いと思います。