スワップチェーン設定
この章では、SharpDX(DirectX)の初期化部分について解説します。主にデバイス(Device)とスワップチェーン(SwapChain)を扱います。
スワップチェーン(SwapChain)とは
スワップ チェーンは、ユーザーにフレームを表示するために使用されるバッファーのコレクションです。
引用:Windows デベロッパー センター(2017/02/08)
要は、画面に表示する為のバッファの一覧とそれを切り替える機能です。 そのため、2D・3Dどちらを扱う場合にでもスワップチェーンは使います。 読み方によっては「スワップチェイン」と呼ばれる時もあるみたいですが、ここでは引用元に沿って「スワップチェーン」で用語を統一して説明いたします。
2D・3D共通部分を初期化
必要なパッケージをインストール
- 「NuGet」を使った同じやり方で「SharpDX.DXGI」と「SharpDX.Direct3D11」をインストールします。
スワップチェーン設定
- スワップチェーンを設定するために必要なファイルを関連付けます。
using SharpDX; using SharpDX.DXGI;
- メンバ変数にディスプレイへアクセスを可能とするハンドラのを宣言しておきます。
// 表示対象ハンドル protected IntPtr DisplayHandle { get { return Handle; } }
- 次に先ほど宣言したディスプレイを描画対象に指定して、スワップチェーンの設定を作成します。
// スワップチェーン設定 var desc = new SwapChainDescription() { // バッファ数 // ※ダブルバッファリングを行う場合は2を指定 BufferCount = 1, // 描画情報 ModeDescription = new ModeDescription(ClientSize.Width, ClientSize.Height, new Rational(60, 1), Format.R8G8B8A8_UNorm), // ウィンドウモードの有効・無効 IsWindowed = true, // 描画対象ハンドル OutputHandle = DisplayHandle, // マルチサンプル方法の指定 SampleDescription = new SampleDescription(1, 0), // 描画後の表示バッファの扱い方法の指定 SwapEffect = SwapEffect.Discard, // 描画画像の使用方法 Usage = Usage.RenderTargetOutput };
デバイスとスワップチェーンを生成
- DirectX11用のファイルを関連付けます。
using SharpDX.Direct3D; using SharpDX.Direct3D11;
- 生成するデバイス用の変数を宣言しておきます。
// Direct3Dのデバイス public SharpDX.Direct3D11.Device Device { get { return _device; } } private SharpDX.Direct3D11.Device _device = null; // スワップチェーン // ※デバイスが描いた画像をウィンドウに表示する機能 SwapChain _SwapChain; Texture2D _BackBuffer;
- 次にスワップチェーンをデバイスと関連付けた上で作成します。
// デバイスとスワップチェーンを生成 SharpDX.Direct3D11.Device.CreateWithSwapChain( // デバイスの種類 DriverType.Hardware, // ランタイムレイヤーの有効にするリスト DeviceCreationFlags.BgraSupport, // フィーチャーレベル // ※ある程度のハードウェアのレベルを規定して,それぞれのレベルにあわせたプログラムを書ける仕組み // ※DirectX の世代を指定 new[] { SharpDX.Direct3D.FeatureLevel.Level_11_0 }, // スワップチェーン設定 desc, // 生成した変数を返す out _device, out _SwapChain);
- 不要な機能をスワップチェーン経由で無効にします。
※これを行わない場合、Alt+Enterでフルスクリーンに出来てしまいます。 - 描画対象であるバックバッファーを変数に保持しておきます。
※後で2D・3Dの描画先であるレンダーターゲットを生成する際に使います。
コード
Program.cs
GameForm.cs
初期化の処理が長くなってきたので
public void Initialize()
を作り、public void Exec()
から1度だけ呼ばれるようにしました。
ここまでの進捗
ここまでで2D・3D共通の初期化処理は終わりました。次からは2D・3Dどちらの描画を行いたいかで描画先であるレンダーターゲットの生成方法が変わります。どちらも使う場合はそれぞれ生成する必要があります。