イントレ
  • 新規
  • ペイント
  • 一覧
  • 管理
  • Home
  • ダウンロード
  • 日記
  • イラスト
  • リンク
  • About
  •  RSS

本文へジャンプ


イントレ。

Tag for "SlimDX"

«Prev || 1 · | Next»

WPF with SlimDX。

.NET 3.5 SP1でD3DImageが実装されてからそのうち遊ぼうと思ってすっかり忘れてた。
WPF4ではXNAとのInteropが用意されるそうだけど、Beta1には見あたらない…気がする。

…ということでググっていたらSlimDXとWPFの連携方法が書いてあった。

以下、メモも兼ねてコピペ。
[Window1.xaml]

    
        
            
        
    

[Window1.xaml.cs]
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Interop;

using System.Drawing;

using SlimDX;
using SlimDX.Direct3D9;

namespace WpfApplication1
{
	/// <summary>
	/// Interaction logic for Window1.xaml
	/// </summary>
	public partial class Window1 : Window
	{
		SlimDX.Direct3D9.Direct3D direct3D = new SlimDX.Direct3D9.Direct3D();
		Device device;
		Sprite sprite;
		Texture texture;

		public Window1()
		{
			InitializeComponent();
			Loaded += new RoutedEventHandler(Window_Loaded);
		}

		private void Window_Loaded(object sender, RoutedEventArgs e)
		{
			InitializeD3D();
			CompositionTarget.Rendering += OnRendering;
			d3dimage.IsFrontBufferAvailableChanged += new DependencyPropertyChangedEventHandler(OnIsFrontBufferAvailableChanged);

			d3dimage.Lock();
			d3dimage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, device.GetBackBuffer(0, 0).ComPointer);
			d3dimage.Unlock();
		}


		public void InitializeD3D()
		{
			HwndSource hwnd = new HwndSource(0, 0, 0, 0, 0, "test", IntPtr.Zero);

			PresentParameters pp = new PresentParameters();
			pp.SwapEffect = SwapEffect.Discard;
			pp.DeviceWindowHandle = hwnd.Handle;
			pp.Windowed = true;
			pp.BackBufferWidth = 400;
			pp.BackBufferHeight = 400;
			pp.BackBufferFormat = Format.X8R8G8B8;

			device = new Device(direct3D, 0,
								DeviceType.Hardware,
								hwnd.Handle,
								CreateFlags.HardwareVertexProcessing,
								pp);

			sprite = new Sprite(device);
			texture = Texture.FromFile(device, @"picture.jpg");

		}


		private void OnRendering(object sender, EventArgs e)
		{
			try
			{
				d3dimage.Lock();
				d3dimage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, device.GetBackBuffer(0, 0).ComPointer);
				RenderD3D();
				d3dimage.AddDirtyRect(new Int32Rect(0, 0, d3dimage.PixelWidth, d3dimage.PixelHeight));
				d3dimage.Unlock();
			}
			catch (Direct3D9Exception ex)
			{
				string msg = ex.Message;
			}
		}

		void OnIsFrontBufferAvailableChanged(object sender, DependencyPropertyChangedEventArgs e)
		{
			if (d3dimage.IsFrontBufferAvailable)
			{
				InitializeD3D();
				CompositionTarget.Rendering += OnRendering;
				d3dimage.IsFrontBufferAvailableChanged += new DependencyPropertyChangedEventHandler(OnIsFrontBufferAvailableChanged);

				d3dimage.Lock();
				d3dimage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, device.GetBackBuffer(0, 0).ComPointer);
				d3dimage.Unlock();
			}
			else
			{
				CompositionTarget.Rendering -= OnRendering;
			}

		}

		public void RenderD3D()
		{
			Result result;

			try
			{
				if (d3dimage.IsFrontBufferAvailable)
				{
					result = device.TestCooperativeLevel();
					if (result.IsFailure)
					{
						throw new Direct3D9Exception();
					}
					device.Clear(ClearFlags.Target, new Color4(System.Drawing.Color.Yellow), 0, 0);
					device.BeginScene();

					sprite.Begin(SpriteFlags.None);

					sprite.Draw(texture, new Color4(1, 1, 1, 1));

					sprite.End();

					device.EndScene();
					device.Present();
				}
			}
			catch (Exception ex)
			{
				string msg = ex.Message;

				InitializeD3D();
				CompositionTarget.Rendering += OnRendering;
				d3dimage.IsFrontBufferAvailableChanged += new DependencyPropertyChangedEventHandler(OnIsFrontBufferAvailableChanged);

				d3dimage.Lock();
				d3dimage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, device.GetBackBuffer(0, 0).ComPointer);
				d3dimage.Unlock();
			}
		}
	}
}


テンポラリなウィンドウを作ってSlimDXを初期化。
バックバッファをD3DImageに渡してCompositionTarget.Renderingイベントに反応して描画するという内容ですね。
d3dimage.IsFrontBufferAvailableChangedイベントに反応してデバイスの再作成もやってます。

…そういえば、このコードってデバイスのDisposeやってないんだけどいいんだろうか?
ガベコレくるとちゃんと回収されるのでお打ちするのが最近の流儀なのかなぁ。

しかし、C#のみでお気軽にやれるのも、COMポインタが公開されてるSlimDXならではですね。
MDXやXNAでもリフレクションを使ってやってる人はいるみたいですけど。

D3DImageが公開された当初にC++のサンプルを触ったんですが、もう少し面倒だった気がします。
あっちはDirect3D9Exとの切り替えやLockableBackBufferとかいろいろあった気がしますが…。
その内容もXPとVistaで挙動が違うって話だったんだっけか?

実際にD3DImageを使うなら何かでラップしてコントロールやImageSourceを仕立て上げるのが便利そうです。
Vista以降ではDirect3D9Exを使った方がパフォーマンスがよいとのことなのでその対応も必要ですね。
また、上記フォーラムに書いてますが、Direct3D9Exを利用した際にTexture.FromFile()で例外が出ちゃって困る人はPool.Defaultを渡してあげましょう。

このコードを.NET4.0に持って行ってもそのまま使えたのでご報告。と。

なんとなくXAudio2。

SlimDX更新してみたついでに。
ちゃんと触るのは初めてなのでサンプルを眺めてみた。

…で、XAudio2のサンプルがかなり簡単で面白いなぁと。


static void PlayPCM(string filePath)
{
  using(var device = new SlimDX.XAudio2.XAudio2())
  using(var master = new SlimDX.XAudio2.MasteringVoice(device))
  using(var stream = new SlimDX.Multimedia.WaveStream(filePath))
  using(var source = new SlimDX.XAudio2.SourceVoice(device, stream.Format))
  using(var buffer = new SlimDX.XAudio2.AudioBuffer())
  {
    buffer.AudioBytes = (int)stream.Length;
    buffer.AudioData = stream;
    source.SubmitSourceBuffer(buffer);

    source.Start();

    Console.WriteLine("[ENTER]で終了します...");
    Console.ReadLine();
  }
}
 


無圧縮Waveファイルを再生するコードなんですが、ここまでシンプルです。
抜粋して書き直してるけど殆どマンマです。

デバイス作ってマスター作って、ソースを作るという手順はDirectSoundのBuffer/SecondBufferの感じに似てますね。
AudioBufferにStream渡してる部分はSlimDXの仕様のようで、アンマネージの方だとバイト配列渡してるみたいですね。
マネージ→アンマネージのやりとりの段階でGCHandle使ってるようで、AudioBufferの生存期間には気をつけないといけないようですが。

AudioBufferをSourceVoiceにSubmitSourceBufferして「積む」ことでバッファリングも出来るようですし、
これならストリーミングも簡単に出来そうですし、デコードする部分を適当に作ってやれば他のフォーマットにも対応可能な感じ。
案外いいかもしれませんね。

アンマネージのXAudio2はいろいろ面倒な感じが見受けられましたが、
シンプルに実装されている分SlimDXはかなりいいのかもしれませんね…。

もうちょっと遊んでみよう。

«Prev || 1 · | Next»

HTML creation time [0.36sec.]
"intre." by MinagiSyu, sense 1999.11.23.
Powered by Nucleus CMS v3.41

Utilities

タグ
園芸 | C# | .NET | SAPFx | サッカー | Windows 7 | SAP1x | PCパーツ | ツクールもどき | WPF | ...すべてのタグ
カレンダー
<   2010-07   >
日月火水木金土
    123
45678910
11121314151617
18192021222324
25262728293031
最近の更新
    2010-07-11
  • [日記] WebMatrixが本気過ぎる件。
  • 2010-06-23
  • [日記] Google Reader APIの認証がまた変わった?
  • [更新履歴] Google Reader Notifier 改 r3をリリース。
  • [ダウンロード] Google Reader Notifier 改
  • 2010-05-31
  • [日記] DynamicObjectを使ったINotifyPropertyChangedラッパー。
  • 2010-05-28
  • [日記] タブが非アクティブな時にページを書き換えるフィッシング攻撃。
  • 2010-05-24
  • [日記] Mercurialのsubrepo。
Adsense