はじめに
WPFのデスクトップアプリでDirect2D描画をしたいと思ったのですが、検索しても情報が古かったりいまいち良い方法が見当たりません。
割と新しめのは
- Win2D: ユニバーサルアプリ前提なら
- WPFDXInterop: pre-release(2015/12/27時点)。今後はこれが本命?
あたりですが、今回はデスクトップアプリで使いたかったのとSharpDXを試してみたい、ということでWPFコントロールを作ってみました。
(とはいえ大半のソースは古いSharpDX/SlimDXのWPF向けサンプルソースから持ってきてるので、今回の作業はDirectX11環境向けの調整とソースの整理、nugetパッケージ化くらいです)
この記事を書いているときに気づきましたが、SharpDXはDirectX12対応の3.0.0がリリースされたようです。
時間が出来たら今回作ったコントロールも対応させるかもしれません。
(2016/1/2追記)
SharpDXのバージョンを3.0.0に上げてリリース(D2dControl 1.1.5)しました。
とりあえずSharpDX側の名前空間変更を反映しただけで、Direct2Dの新機能(DrawGradientMesh
とかDrawInk
とか?)はよくわからないので未対応です…
動作確認環境
- Windows10 / DirectX11
- Visual Studio 2015
- SharpDX 2.6.3
リンク
使い方
サンプルソースを見れば大体わかるかと思います。
基本的にはD2dControl
を継承したクラスを作り、Render
内でtarget
に対してDirect2Dの描画関数を呼ぶだけです。
通常描画の前後でBeginDraw
/EndDraw
を呼ぶ必要がありますが、基底クラス側で呼んでいるのでここでは必要ありません。
class TestControl : D2dControl.D2dControl {
public override void Render( RenderTarget target ) {
target.Clear( Color4.Black );
}
}
また、RenderTarget
に依存するリソース(ブラシなど)を格納するためのリソースキャッシュも提供しています。
Render
内でリソースの生成を行うと、これは毎フレーム呼ばれるのでパフォーマンス上よろしくないです。
だからと言ってメンバとして保持するとtarget
が変わった際に例外で落ちます。
(実際Controlのリサイズ等でtarget
は再生成されます)
というわけでresCahce
にRenderTarget
を引数とするリソース生成用delegateを渡せばtarget
更新時のリソース再生成などをやってくれるようになっています。
class TestControl : D2dControl.D2dControl {
public TestControl() {
resCache.Add( "Brush", t => new SolidColorBrush( t, Color4.White ) );
}
public override void Render( RenderTarget target ) {
var brush = resCache["Brush"] as Brush;
target.DrawRectangle( new RectangleF( 10, 10, 10, 10 ), brush );
}
}