面の描画

 四角形の平面を1枚描画します。これまでの点や線とは違い、大分3Dっぽくなりました。見た目は四角形ですが、三角形の平面2枚で構成されています。DirectXでは、全ての図形は3角形のポリゴンの集合で表現されます。2つの三角形を描画するためには、全部で6つの頂点が必要になります。

しかし、左の図を見ても分かるように、一つの四角形を2つの三角形で表現しようとすると、②と④、③と⑤の頂点のように座標が同じものが2組出来てしまいます。描画したい四角形が増えるほど、この同じ座標の頂点の組は増えていってしまい、とても無駄です。そこで、真ん中の図のように4つの頂点を、書いてある数字の順番で用意します。すると、DirectXはその順番に沿って真ん中の図のような三角形を二つ描画してくれます。このような描画を行うためは、IASetPrimitiveTopology()関数にD3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIPを指定します。「~STRIP」の付くものは、そのような一筆書きで描画するタイプのものです。一つの四角形を複数の四角形で表現したい場合は、図の右側のようになります(厳密には右図のようにしてしまうと、⑦から⑨へ辺が出来てしまいますが、今回のサンプルような平面の場合は特に問題ありません)。

 一口に「面」と言ってもそこには、表と裏があり、塗りつぶすか否かなど、色々と考えられます。DirectXでは、目の前に三つの頂点があった時、それが時計回りになぞって出来た面だと表になり、その反対側が裏になります。表面のみを描画したり、両面を描画したい場合等は、ラスタライザと呼ばれる所で設定を行います。下記では、表面の設定方法と予め予定していた3Dのベクトル等の計算を行うために使うDirectXMathについて解説します。

​コード解説

① ラスタライザの設定
 描画を行うポリゴンの面情報の設定をします。

2行目から4行目で面情報の設定を行っています。

  2行目:塗りつぶすかどうかを決める

   ・D3D11_FILL_WIREFRAME … 頂点と頂点を線で結びワイヤーフレームで表示する

   ・D3D11_FILL_SOLID   … 3つの頂点を結んで出来た三角形を塗りつぶす

  3行目:面の描画ルールを決める

   ・D3D11_CULL_NONE   … 表面と裏面の両方を描画する

   ・D3D11_CULL_FRONT   … 表面を描画しない(裏面のみ描画)

​   ・D3D11_CULL_BACK   … 裏面を描画しない(表面のみ描画)

​  4行目:面の裏表を定義

   ・TRUE         … 反時計回りの時に表面になる

   ・FALSE        … 時計回りの時に表面になる

​少しややこしいのが、3行目と4行目です。4行目で、時計回りと反時計回りのどちらが「表面」であるのかを決めます。3行目でD3D11_CULL_FRONTを指定していたとしても、4行目のTRUE、FALSEで面が表示されるのか、されないのかが変わってきます。

② DirectXMathライブラリを使った計算
 DirectXMathは、3Dグラフィックスのためのベクトルや行列を扱うための型や便利な関数があります。ここでは、代表的な型や関数の使い方の説明をします。3Dグラフィックスにおける原理や数式の詳細等の説明はしません。下記は、サンプルプログラム内でDirectXMathが使われている所です。

1行目から3行目では、カメラを定義(カメラの位置、見ている方向、上方向)するためのベクトルをそれぞれ設定しています。後半の3行、4行目から6行目では、座標変換を行うための行列を定義しています。4行目はカメラから覗いた世界に変換するビュー変換、5行目は、近くのものは大きく、遠くのものは小さく見せる透視変換、6行目は絶対座標に対するワールド変換です。

< 定数 >

 〇 XM_PI    = 3.141592654f : 円周率 π (角度で表すと180°)
 〇 XM_2PI   = 6.283185307f : 2π (角度で表すと360°)
 〇 XM_1DIVPI  = 0.318309886f : 1.0 / π
 〇 XM_1DIV2PI = 0.159154943f : 1.0 / (2π)
 〇 XM_PIDIV2  = 1.570796327f : π / 2.0 (角度で表すと90°)
 〇 XM_PIDIV4  = 0.785398163f : π / 4.0 (角度で表すと45°)

 〇 XMMATRIX XMMatrixIdentity(): 単位行列

< 型の宣言と値の代入方法 >

 〇 ベクトルの宣言と代入

  ・XMFLOAT2 vec2 = { 0.0f, 0.0f };
  ・XMFLOAT3 vec3 = { 0.0f, 0.0f, 0.0f };
  ・XMVECTOR vec4 = { 0.0f, 0.0f, 0.0f, 0.0f };
  ・XMVECTOR vec4 = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f);

 〇 XMVECTORへの変換

  ・XMVECTOR vec4 = XMLoadFloat2(&vec2);

  ・XMVECTOR vec4 = XMLoadFloat3(&vec3);

 〇 XMVECTORから値を取り出す

  ・XMStoreFloat2(&vec2, vec4);

  ・XMStoreFloat3(&vec3, vec4);

 〇 行列の宣言と代入
  ・XMFLOAT3X3 mat33 = {

     0.0f, 0.0f, 0.0f,

     0.0f, 0.0f, 0.0f,

     0.0f, 0.0f, 0.0f

   };

  ・XMFLOAT4X3 mat43 = {

     0.0f, 0.0f, 0.0f,

     0.0f, 0.0f, 0.0f,

     0.0f, 0.0f, 0.0f,

     0.0f, 0.0f, 0.0f

   };

  ・XMFLOAT4X4 mat44 = {

     0.0f, 0.0f, 0.0f, 0.0f,

     0.0f, 0.0f, 0.0f, 0.0f,

     0.0f, 0.0f, 0.0f, 0.0f,

     0.0f, 0.0f, 0.0f, 0.0f

   };

 〇 XMMATRIXへの変換

  ・XMMATRIX mat = XMLoadFloat3x3(&mat33);

  ・XMMATRIX mat = XMLoadFloat4x3(&mat43);

  ・XMMATRIX mat = XMLoadFloat4x4(&mat44);

 〇 XMMATRIXから値を取り出す

  ・XMStoreFloat3x3(&mat33, mat);

  ・XMStoreFloat4x3(&mat43, mat);

  ・XMStoreFloat4x4(&mat44, mat);

< 演算 >

 〇 ベクトル同士の足し算、引き算

  ・XMVECTOR vec4 = vec4a + vec4b; ※vec4a、vec4bはXMVECTOR

 〇 内積

  ・XMVECTOR vec4 = XMVector2Dot(vec4a, vec4b); ※vec4a、vec4bはXMVECTOR

  ・XMVECTOR vec4 = XMVector3Dot(vec4a, vec4b); ※vec4a、vec4bはXMVECTOR

  ・XMVECTOR vec4 = XMVector4Dot(vec4a, vec4b); ※vec4a、vec4bはXMVECTOR

 〇 外積

  ・XMVECTOR vec4 = XMVector2Cross(vec4a, vec4b); ※vec4a、vec4bはXMVECTOR

  ・XMVECTOR vec4 = XMVector3Cross(vec4a, vec4b); ※vec4a、vec4bはXMVECTOR

  ・XMVECTOR vec4 = XMVector4Cross(vec4a, vec4b); ※vec4a、vec4bはXMVECTOR

 〇 ベクトルと行列

  ・XMVECTOR vec = XMVector2Transform(vec4, mat);

  ・XMVECTOR vec = XMVector3Transform(vec4, mat);

  ・XMVECTOR vec = XMVector4Transform(vec4, mat);

< 関数 >

 〇 ビュー変換行列

  ・XMMATRIX XMMatrixLookAtLH(XMVECTOR EyePosition, XMVECTOR FocusPosition, XMVECTOR UpDirection)

​  ・XMMATRIX XMMatrixLookAtRH(XMVECTOR EyePosition, XMVECTOR FocusPosition, XMVECTOR UpDirection)

     XMMatrixLookAtLH(…):左手座標系における頂点のワールド空間からビュー空間に変換するビュー行列

     XMMatrixLookAtRH(…):右手座標系における頂点のワールド空間からビュー空間に変換するビュー行列

       EyePosition  … カメラの位置

       FocusPosition … 視点方向

       UpDirection  … カメラの上方向

​ 〇 透視変換行列

  ・XMMATRIX XMMatrixPerspectiveFovLH(FLOAT FovAngleY, FLOAT AspectHByW, FLOAT NearZ, FLOAT FarZ)

​  ・XMMATRIX XMMatrixPerspectiveFovRH(FLOAT FovAngleY, FLOAT AspectHByW, FLOAT NearZ, FLOAT FarZ)

     XMMatrixPerspectiveFovLH(…):左手座標系の透視変換行列

     XMMatrixPerspectiveFovRH(…):右手座標系の透視変換行列

       FovAngleY … 上下の視野角(ラジアン)

       AspectHByW … アスペクト比

       NearZ   … 視点に近いクリップ面までの距離

       FarZ    … 視点から遠いクリップ面までの距離

サンプル​コード

< 動作確認環境 >
 ・Windows10 Pro
 ・Visual Studio Community 2017


基本的には空のプロジェクトを作ってもらい、以下のソースコードをコピペするだけでうまく実行できるかと思います。もしうまくいかない場合がありましたら、サンプルコードの実行に関する注意事項を一度参照してみてください。

​ソースコード

シェーダのソースコード (shader.hlsl ※必ずこの名前で保存してください)