XNA naudojimas WPF programose
suvestinė
Aprašoma, kaip naudoti XNA Framework WPF programose.
Darbo aplinka
Būtinosios sąlygos
Palaikomos XNA versijos |
|
Palaikomos platformos |
|
"Windows" reikalinga "Vertex Shader" versija | 1.1 |
"Windows" reikalinga "Pixel Shader" versija | 1.1 |
Darbo aplinka
platforma |
medžiaga
Norėdami generuoti tam tikro valdiklio vaizdą naudodami "DirectX", turite gauti to valdiklio lango rankenėlę. Tačiau, skirtingai nei "Windows Form" valdikliai, WPF valdikliai neturi langų rankenėlių (WPF jie tiesiog "piešia" valdiklį).
Tačiau WPF suteikia valdiklį, vadinamą "WindowsFormsHost", kuris leidžia naudoti "Windows Forms" valdiklius.
Šiame straipsnyje mes sukursime daugiakampio piešimo pavyzdį, kai jis pasukamas, kaip parodyta aukščiau, tačiau praleisiu pačios XNA detales, nes tai paaiškinti būtų per ilgai. Aš tik pakalbėsiu apie WPF ir XNA santykius.
Pirmiausia atidarykite WPF langą (šiuo atveju Window1.xaml) ir įrankių juostoje įdėkite WindowsFormHost valdiklį. Dešinėje esantis slankiklis yra premija.
Man tikrai reikia šiek tiek daugiau padirbėti su XAML, bet paliksiu tai vėlesniam laikui, nes pirmiausia turiu sukurti valdiklius, kad galėčiau naudoti XNA.
Pridėkite "Windows Forms" "Pasirinktinį valdiklį" prie savo projekto. Palikite pavadinimą GraphicsDeviceControl.
Nepamirškite iš anksto pridėti nuorodos "Microsoft.Xna.Framework". Taip pat yra "Microsoft.Xna.Framework.Game", tačiau tai naudojama tik žaidimų projekte, todėl nereikia jo įtraukti.
Kad pavyzdinis kodas būtų trumpas, visos su XNA susijusios programos apibendrinamos GraphicsDeviceControl.cs. Tai nėra labai universalus rašymo stilius, todėl prašome jį pritaikyti ir perrašyti.
Visas "GraphicsDeviceControl" kodas parodytas žemiau (išskyrus dizainerio dalį). Jei kada nors naudojote XNA, žinosite, kad ji nedaro nieko neįprasto. Aš naudoju laikmačio komponentą, kad daugiakampis visą laiką suktųsi.
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
{
<summary>
グラフィックデバイスコントロール
</summary>
public partial class GraphicsDeviceControl : Control
{
<summary>
グラフィックデバイス
</summary>
private GraphicsDevice device = null;
<summary>
エフェクト
</summary>
private BasicEffect effect = null;
<summary>
頂点データ
</summary>
private VertexPositionColor[] vertices = new VertexPositionColor[3];
<summary>
頂点データ
</summary>
public VertexPositionColor[] Vertices
{
get { return this.vertices; }
}
<summary>
コンストラクタ
</summary>
public GraphicsDeviceControl()
{
InitializeComponent();
}
<summary>
コントロールが作成されるとき
</summary>
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();
}
<summary>
使用中のリソースをすべてクリーンアップします。
</summary>
<param name="disposing">マネージ リソースが破棄される場合 true、破棄されない場合は false です。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
if (disposing)
{
if (this.device != null)
{
this.device.Dispose();
}
}
base.Dispose(disposing);
}
<summary>
描画イベント
</summary>
<param name="pe"></param>
protected override void OnPaint(PaintEventArgs pe)
{
this.Draw();
base.OnPaint(pe);
}
<summary>
描画
</summary>
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();
}
<summary>
タイマーイベント
</summary>
<param name="sender"></param>
<param name="e"></param>
private void timer_Tick(object sender, EventArgs e)
{
this.Draw();
}
}
}
Dabar, kai sukūrėte valdiklį, pažvelkime į XAML. Kadangi įdėsime sukurtą valdiklį, prie šakninės žymos pridėsime vardų sritį. Čia jis apibrėžiamas kaip "xw".
<Window x:Class="ManagedDirectXOnWPF.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WPFウインドウ上でManaged DirectXを使用してポリゴン描画"
Height="338" Width="422"
xmlns:my="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
xmlns:xw="clr-namespace:ManagedDirectXOnWPF">
<!-- 省略 -->
</Window>
Tada išplėskite ką tik įdėto "WindowsFormsHost" valdiklio žymą ir pridėkite "GraphicsDeviceControl", kaip parodyta toliau.
<my:WindowsFormsHost Name="windowsFormsHostManagedDirectX" Width="300" Height="300"
HorizontalAlignment="Left" VerticalAlignment="Top">
<xw:GraphicsDeviceControl x:Name="GraphicsDeviceControl" />
</my:WindowsFormsHost>
Jums nereikia turėti "x:Name", bet pavyzdys jį naudoja norint pasiekti viršūnių duomenis slankikliu.
Jei tai padarysite, WPF galite paleisti sceną, kurioje daugiakampiai piešiami besisukančiu daugiakampiu, kaip parodyta pavyzdyje. Prieiga naudojant slankiklį yra premija, todėl atsisiųskite duomenų pavyzdį ir patikrinkite.
Programai reikalinga ".NET Framework 3.0", naujausia "DirectX" vykdyklė ir "Microsoft XNA Framework Redistributable 2.0". Be to, kaip aparatinės įrangos reikalavimas reikalinga "vaizdo plokštė, palaikanti Pixel Shader 1.1 ar naujesnę versiją".
Be to, projektas buvo sukurtas "Visual Studio 2008 Professional Edition". Paruoškite aplinką "Visual Studio 2008".