windowsストアーアプリでsharpdxを動かしてみる
DESCRIPTION
MetroStyleDeveloper (プチ) #06 大阪 ~メトロスタイルアプリ エキスパート塾++2~で使用したセッション資料です。TRANSCRIPT
MetroStyleDeveloper( プチ ) #06 大阪~メトロスタイルアプリ エキスパート塾 ++2 ~2012/9/26 THU
SharpDX•DirectX のラッパー•http://sharpdx.org/
DirectX•ゲームおよびマルチメディア処理用 API の集合
•COM ベースで C++ での使用が前提•最新は DirectX 11.1 ( Windows 8 以降)
SharpDX と DirectX
Direct3D DirectSound
DirectDraw ( DirectX 7 で終了) Direct2D ( Windows 7 以降)DirectInput などなど
Managed DirectX•DirectX を C#/VB などから使えるようにするラッパー +α•Version 1.0 のみで終了
XNA Framework•DirectX の上にマネージドなフレームワークを構築•最新の XNA 4.0 は Direct3D 9 の上に構築されている (なので、 Direct3D 10 以降の機能は使えない)•Windows 、 Xbox 360 、 Windows Phone 7
XNA
デスクトップアプリ•DirectX でも XNA でもご自由に
メトロスタイルアプリ•C++/DirectX のみ•マネージドから使う方法は無い•XAML と DirectX の親和性アップ!
Windows 8
SurfaceImageSourceを使ってみる
NuGet で SharpDX.Direct3D11 を入れる手動で参照設定するときは
SharpDX.dll 、 SharpDX.D3DCompiler.dll 、
SharpDX.Direct3D11.dll 、 SharpDX.DXGI.dllを入れる
準備
Rectangle を適当に貼り付け
XAML
<Rectangle x:Name=“Rectangle1” ...以下略 .../>
using
フィールド
Direct3D の初期化( 1 )using SharpDX;using SharpDX.Direct3D;using SharpDX.Direct3D11;using SharpDX.DXGI;using SharpDX.IO;
// Direct3D デバイスprivate SharpDX.Direct3D11.Device1 d3dDevice;
// Direct3D コンテキストprivate SharpDX.Direct3D11.DeviceContext1 d3dContext;
Direct3D の初期化( 2 )
// Direct3D デバイスの取得var creationFlags = DeviceCreationFlags.VideoSupport | DeviceCreationFlags.BgraSupport
| DeviceCreationFlags.Debug;using (var defaultDevice = new SharpDX.Direct3D11.Device(DriverType.Hardware, creationFlags)){
this.d3dDevice = defaultDevice.QueryInterface<SharpDX.Direct3D11.Device1>();}
// Direct3D コンテキストを取得this.d3dContext = d3dDevice.ImmediateContext.QueryInterface<SharpDX.Direct3D11.DeviceContext1>();
コード( OnNavigatedTo() メソッド内)
using
フィールド
SurfaceImageSource の初期化( 1 )
using Windows.Graphics.Display;using Windows.UI.Xaml.Media.Imaging;
// SurfaceImageSourceprivate SurfaceImageSource surfaceImageSource;
コード( OnNavigatedTo() メソッド内)
SurfaceImageSource の初期化( 2 )// SurfaceImageSource の作成int pixelWidth = (int)(this.Rectangle1.Width * DisplayProperties.LogicalDpi / 96.0);int pixelHeight = (int)(this.Rectangle1.Height * DisplayProperties.LogicalDpi / 96.0);this.surfaceImageSource = new SurfaceImageSource(pixelWidth, pixelHeight);var brush = new ImageBrush();brush.ImageSource = this.surfaceImageSource;this.Rectangle1.Fill = brush;
using (var surfaceImageSourceNative = ComObject.As<SharpDX.DXGI.ISurfaceImageSourceNative>(this.surfaceImageSource)){
surfaceImageSourceNative.Device = this.d3dDevice.QueryInterface<SharpDX.DXGI.Device>();}
描画コールバック( 1 )// 描画コールバックを開始CompositionTarget.Rendering += CompositionTarget_Rendering;
private void CompositionTarget_Rendering(object sender, object e){
int pixelWidth = (int)(this.Rectangle1.Width * DisplayProperties.LogicalDpi / 96.0);int pixelHeight = (int)(this.Rectangle1.Height * DisplayProperties.LogicalDpi / 96.0);var updateRect = new SharpDX.Rectangle(0, 0, pixelWidth, pixelHeight);
DrawingPoint offset;using (var surfaceImageSourceNative =
ComObject.As<SharpDX.DXGI.ISurfaceImageSourceNative>(this.surfaceImageSource))using (var surface = surfaceImageSourceNative.BeginDraw(updateRect, out offset)){
// レンダーターゲット作成Size renderTargetSize;RenderTargetView renderTargetView;using (var backBuffer = surface.QueryInterface<SharpDX.Direct3D11.Texture2D>()){
renderTargetSize = new Size(backBuffer.Description.Width, backBuffer.Description.Height);renderTargetView = new RenderTargetView(this.d3dDevice, backBuffer);
}...続く
描画コールバック( 2 )...続き
// ビューポート作成Viewport viewport = new Viewport(0, 0,
(int)renderTargetSize.Width, (int)renderTargetSize.Height, 0.0f, 1.0f);
// レンダーターゲット、ビューポートをセットthis.d3dContext.OutputMerger.SetTargets(renderTargetView);this.d3dContext.Rasterizer.SetViewports(viewport);
// 背景クリアthis.d3dContext.ClearRenderTargetView(renderTargetView, Colors.Red);
// レンダリングthis.d3dContext.Draw(36, 0);
surfaceImageSourceNative.EndDraw();}
}
Direct3D で 3D CG を描画頂点シェーダー GPU で頂点座標を計算ピクセルシェーダー GPU で各ピクセルの色を計算頂点レイアウト GPU に頂点の配置順を教える頂点バッファー 頂点の集まり頂点インデックス 頂点の並び順定数バッファー GPU の変数を渡す
レンダーターゲットビュー ポリゴンの色を描画深度バッファー ポリゴンの奥行き値を描画
ファイルをコピー•SimpleVertexShader.cso 、 SimplePixelShader.cso をコピーしてプロジェクトに追加•「ビルドアクション」を「コンテンツ」、「出力ディレクトリにコピー」を「新しい場合はコピーする」にする
本当は、、、•fx ファイルをコンパイルして fxo にする•hlsl ファイルをコンパイルして cso にする•Visual C++ ならデフォで対応してるんだが、、
シェーダーの準備
フィールド
ポリゴンの準備( 1 )
// 頂点シェーダーprivate VertexShader vertexShader;
// ピクセルシェーダーprivate PixelShader pixelShader;
// 頂点レイアウトprivate InputLayout layout;
// 頂点バッファーprivate VertexBufferBinding vertexBufferBinding;
// 定数バッファーprivate SharpDX.Direct3D11.Buffer constantBuffer;
コード( OnNavigatedTo() メソッド内)
ポリゴンの準備( 2 )
// 頂点シェーダー、ピクセルシェーダーの読み込み、作成var installPath = Windows.ApplicationModel.Package.Current.InstalledLocation.Path;var vertexShaderByteCode = NativeFile.ReadAllBytes(Path.Combine(installPath, "SimpleVertexShader.cso"));this.vertexShader = new VertexShader(this.d3dDevice, vertexShaderByteCode);this.pixelShader = new PixelShader(this.d3dDevice,
NativeFile.ReadAllBytes(Path.Combine(installPath, "SimplePixelShader.cso")));
// 頂点レイアウト作成this.layout = new InputLayout(this.d3dDevice, vertexShaderByteCode, new[]{
new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0),new InputElement("COLOR", 0, Format.R32G32B32A32_Float, 16, 0)
});...続く
ポリゴンの準備( 3 )...続き
// 頂点バッファー作成var vertices = SharpDX.Direct3D11.Buffer.Create(this.d3dDevice, BindFlags.VertexBuffer, new[]{
new Vector4( 0.0f, 1.3f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), // Frontnew Vector4( 1.1f, -0.6f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),new Vector4(-1.1f, -0.6f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
});this.vertexBufferBinding = new VertexBufferBinding(vertices, Utilities.SizeOf<Vector4>() * 2, 0);
// 定数バッファー作成this.constantBuffer = new SharpDX.Direct3D11.Buffer(d3dDevice, Utilities.SizeOf<SharpDX.Matrix>(), ResourceUsage.Default,
BindFlags.ConstantBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);
コード( CompositionTarget_Rendering() メソッド内の背景をクリアした後)
ポリゴンのレンダリング
// レンダリングパイプライン構築this.d3dContext.InputAssembler.SetVertexBuffers(0, this.vertexBufferBinding);this.d3dContext.InputAssembler.InputLayout = this.layout;this.d3dContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;this.d3dContext.VertexShader.SetConstantBuffer(0, this.constantBuffer);this.d3dContext.VertexShader.Set(this.vertexShader);this.d3dContext.PixelShader.Set(this.pixelShader);
// 定数バッファーに変換行列をセットvar projection = SharpDX.Matrix.OrthoLH(4.0f,
4.0f * (float)renderTargetSize.Height / (float)renderTargetSize.Width, 0f, 2f);var worldViewProjection =
SharpDX.Matrix.RotationZ(2f * (float)Math.PI * (float)DateTime.Now.Millisecond / 1000f)* projection;
worldViewProjection.Transpose();this.d3dContext.UpdateSubresource(ref worldViewProjection, this.constantBuffer, 0);
SharpDX のサンプル•Samples\Win8\MiniCubeBrushXaml
SurfaceImageSource のサンプル•Samples\Win8\MiniCubeXaml
SwapChainBackgroundPanel のサンプル
•SharpDX のサンプルに DeviceManager 、 SurfaceImageSourceTarget 、 SwapChainBackgroundPanelTarget など便利なクラスが入ってます
Windows Store app samples•http://code.msdn.microsoft.com/windowsapps/site/search?f%5B0%5D.Type=Technology&f%5B0%5D.Value=DirectX•C++ のサンプルだけど参考にはなる
リソース