前回「WPF上でManaged DirectXを使用する」で WPF ウインドウに Managed DirectX で作成したビューを表示しました。今回は XNA のライブラリを使ってポリゴンを表示させたいと思います。以下がサンプル画面です。内容は前回とほとんど同じです。
今回 XNA のライブラリを使いますが、WindowsFormsHost コントロールを使うところは特に違いはなく、単純に Managed DirectX のコードを XNA Framework に置き換えたような感じになります。
XNA Framework を使用するので、参照に「Microsoft.Xna.Framework」を追加してください。「Microsoft.Xna.Framework.Game」もありますが、こちらはゲーム専用プロジェクトで使うものなので入れる必要はありません。
以下が、GtaphicsDeviceControl のコードです(デザイナ部分除く)。ファイルやコードの作り方とかは前回の「WPF上でManaged DirectXを使用する」を参照してください。コードも Managed DirectX のときと似ていると思います。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace XNAOnWPF
{
public partial class GraphicsDeviceControl : Control
{
private GraphicsDevice device = null;
private BasicEffect effect = null;
private VertexPositionColor[] vertices = new VertexPositionColor[3];
public VertexPositionColor[] Vertices
{
get { return this.vertices; }
}
public GraphicsDeviceControl()
{
InitializeComponent();
}
protected override void OnCreateControl()
{
if (this.DesignMode == false)
{
try
{
PresentationParameters pp = new PresentationParameters();
pp.SwapEffect = SwapEffect.Discard;
pp.BackBufferWidth = 300;
pp.BackBufferHeight = 300;
pp.EnableAutoDepthStencil = true;
pp.AutoDepthStencilFormat = DepthFormat.Depth16;
this.device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter,
DeviceType.Hardware, this.Handle, pp);
this.vertices[0] = new VertexPositionColor(
new Vector3(0.0f, -2.0f + (float)Math.Sqrt(3) * 3.0f, 0.0f),
new Microsoft.Xna.Framework.Graphics.Color(255, 0, 0));
this.vertices[1] = new VertexPositionColor(
new Vector3(3.0f, -2.0f, 0.0f),
new Microsoft.Xna.Framework.Graphics.Color(0, 255, 0));
this.vertices[2] = new VertexPositionColor(
new Vector3(-3.0f, -2.0f, 0.0f),
new Microsoft.Xna.Framework.Graphics.Color(0, 0, 255));
this.device.VertexDeclaration =
new VertexDeclaration(this.device, VertexPositionColor.VertexElements);
this.effect = new BasicEffect(this.device, null);
this.effect.VertexColorEnabled = true;
this.effect.View = Matrix.CreateLookAt(
new Vector3(0.0f, 0.0f, -10.0f),
new Vector3(0.0f, 0.0f, 0.0f),
Vector3.Up);
this.effect.Projection = Matrix.CreatePerspectiveFieldOfView(
MathHelper.ToRadians(45.0f), 1.0f, 1.0f, 100.0f);
this.device.RenderState.CullMode = CullMode.None;
this.device.RenderState.AlphaBlendEnable = true;
this.device.RenderState.SourceBlend = Blend.SourceAlpha;
this.device.RenderState.DestinationBlend = Blend.InverseSourceAlpha;
}
catch (Exception ex)
{
Trace.WriteLine(ex.ToString());
}
}
base.OnCreateControl();
}
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
if (disposing)
{
if (this.device != null)
{
this.device.Dispose();
}
}
base.Dispose(disposing);
}
protected override void OnPaint(PaintEventArgs pe)
{
this.Draw();
base.OnPaint(pe);
}
private void Draw()
{
if (this.device == null)
{
return;
}
this.device.Clear(Microsoft.Xna.Framework.Graphics.Color.DarkBlue);
this.effect.Begin();
this.effect.Techniques[0].Passes[0].Begin();
this.effect.World = Matrix.CreateRotationY((float)Environment.TickCount / 1000.0f);
this.device.DrawUserPrimitives<VertexPositionColor>(
PrimitiveType.TriangleList, vertices, 0, 1);
this.effect.Techniques[0].Passes[0].End();
this.effect.End();
this.device.Present();
}
private void timer_Tick(object sender, EventArgs e)
{
this.Draw();
}
}
}
WPF の方(XAMLとプログラム)は前回とほぼ同じで、違うのは名前空間ぐらいです。詳しくはサンプルプロジェクトのほうを参照してください。
以下、実行ファイルです。「.NET Framework 3.0」と「最新の DirectX ランタイム」「Microsoft XNA Framework Redistributable 2.0」が必要です。また、ハードウェア要件として「ピクセルシェーダ 1.1 以上に対応したグラフィックカード」が必要です(たぶん)。
サンプルプロジェクト一式です。「Visual Studio 2008 Professional Edition」で作成しています。XNA は Visual Studio 2008 には対応していないと言われているので、ビルドコンテンツなどが使えない可能性があるかもしれません(このあたりはまだ試していません)。