bate's blog

調べたこと実装したことなどを取りとめもなく書きます。

tutorial01

英語だけど読んだよ。
誤魔化しながら日本語にしてみたよ。


Tutorial 1:Direct3D 11 Basics


Direct3D 11デバイスの準備
一番最初にすることは下記のオブジェクトを作成すること
・デバイス
・イミディエイトコンテキスト(DX11からの新しいオブジェクト)
スワップチェイン


DX10では、デバイスはレンダリングとリソース作成を行っていた
DX11では、イミディエイトコンテキストがバッファへのレンダリングを行い、
デバイスがリソース作成の方法を持つ。


スワップチェインは、デバイスレンダーとモニター表示のバッファ管理を行う。
少なくともフロントとバックを含む2つ以上のバッファを持つ。
もちろん、バックバッファとフロントバッファのスワップもする。


スワップチェインを作るために、DXGI_SWAPCHAIN_DESC構造体を設定する必要がある。
BackBufferUsageはバックバッファを使うフラグを設定するメンバ変数だ。
バックバッファにレンダーしたいのでBackBufferUsageにDXGI_USAGE_RENDER_TARGET_OUTPUTを設定する。
OutputWindowは、スワップチェーンが画面にイメージを表示するのに使うウィンドウを設定する。
SampleDescはマルチサンプリングを可能にする。
しかし、今わ使わないのでSampleDesc.Count=1とSampleDesc.Quality=0にする。


設定が終われば、D3DX11CreateDeviceAndSwapChainでデバイスとスワップチェインを作る。


次にするべきことは、レンダーターゲットビューを作ることだ。
レンダーターゲットビューは、DX11において一種のリソースビューだ。
リソースビューはリソースにグラフィックパイプラインのある特定のステージとの境界となることを許す。
リソースビューはC言語におけるキャストのようだ。
生のメモリの塊を整数の配列や構造体などにキャストする。
型が分からない生のメモリは役に立たない。
DX11のリソースビューは、似たような振る舞いをする。
例えば2Dテクスチャ、生メモリの塊に似ている、は下張りの生リソースだ。
異なるフォーマットでグラフィックスパイプラインの異なるステージにテクスチャを結びつけるために
異なるビューリソースを作ることができるリソースがある。
レンダーターゲットにレンダーするものだったり、深度情報を受け取るデプスステンシルバッファだったり、
もしくはテクスチャリソースだったりする。
C言語の型キャストは異なるマナーでメモリの塊を使うことを許すように、DX11リソースビューもこれに倣う。


レンダーターゲットとしてスワップチェインのバックバッファとして結びつけるために
レンダーターゲットを作る必要がある。
これにより、DX11はそれにレンダーすることを可能にする。
まず、GetBuffer()をバックバッファオブジェクトを取得するためにコールする。
選択的に、レンダーターゲットビューを作るための記述であるD3D11_RENDERTARGETGETVIEW_DESC構造体を
設定することができる。
この記述は普通はCreateRenderTargetViewの第二引数だが、ここではデフォルトレンダーターゲットで十分だ。
デフォルトレンダーターゲットは第二引数をNULLにすることで得られる。
レンダーターゲットビューを作ったら、パイプラインにそれを結びつけるために
イミディエートコンテキストでOMSetRenderTargets()をコールできる。
これは、パイプラインレンダーがバックバッファへの書き込みを取得する出力を保障する。


DX11がレンダー可能になる前にセットアップする最後のことは、
ビューポートを初期化することだ。
ビューポートは、XとYは-1から1の範囲、Zは0から1の範囲のクリップスペース座標を
レンダーターゲットスペース(ピクセルスペース)に位置づけする。
DX9では、アプリケーションがビューポートを設定しない場合、レンダーターゲットと同じサイズの
デフォルトのビューポートが設定される。
DX11では、デフォルトではビューポートは設定されない。
それ故に、画面で何かを見たければビューポートを設定しなければならない。
出力として全部のレンダーターゲットを使いたいならば、
左上を(0,0)として、幅と高さをレンダーターゲットと全く同一のサイズに設定すること。


メッセージループの変更
ウィンドウとDX11の設定はできたのでレンダーの準備はできた。
しかし、メッセージループにGetMessage()を使ってメッセージを受け取るという問題が残っている。
GetMessage()の問題は、メッセージない場合にメッセージが利用可能になるまで他の処理をブロックして戻ってこないことだ。
つまり、メッセージキューが空の時はレンダリングなどの何かしらの処理をしているのではなく、
メッセージを待ち続けるのだ。
GetMessage()の代わりにPeekMessage()を使うことで、この問題は解決できる。
PeekMessage()はGetMessage()のように、メッセージを回収するし、メッセージがない時は、
他の処理をブロックする代わりにすぐに戻ってくる。
そうなれば、メッセージがない時もレンダリングが可能になる。


レンダリングコード
レンダリングはRender()関数で行われる。
このチュートリアルでは、単色でスクリーンを埋めるような、可能な限り簡素なシーンをレンダリングする。
DX11では、単色でレンダーターゲットを埋める簡単な方法は、
イミディエイトコンテキストのClearRenderTargetView()関数を使うことだ。
まず、スクリーンを埋めたい色を表すfloat4つの配列を定義する。
そして、ClearRenderTargetView()に渡す。今回は青を選んだ。
バックバッファを埋めたら、レンダリングを完了するためにスワップチェインのPresent()関数を呼ぶ。
Present()は、ユーザーが見ることができるスクリーンのスワップチェーンのバックバッファコンテキストを
表示する責任がある。