DirectX Guide

DirectX は新しいビデオカードやハードウエアの開発と共に、頻繁にバージョンアップを重ねて来ました。
その間に Windows System や Visual Studio もバージョンアップされ、組み合わせによっては DirectX が動きません。
そこで DirectX の開発環境を含め、プログラミングの要点をまとめてみました。

私のホームページは複数のサーバーに分割しています。
直接リンク出来ないときはトップページからたどって下さい。
前田稔(Maeda Minoru)の超初心者のプログラム入門

Windows Guide Page Index

Windows Store Guide

  1. 最初に Windows Store のプログラミングに付いて私が感じたことを説明します。
    Microsoft は 2012/10/末 に新しいOSである Windows8 の発売を開始しました。 \(^o^)/
    Windows8 は、これまでの OS と仕様が大きく変わっていて、Windows Phone など携帯端末やスマホにも対応する OS です。
    DirectX も同様で「Windows7 までとは全く違う」と言っても過言ではありません。
    Windows7 までは Visual Studio をインストールしてから、さらに DirectX のインストールが必要でしたが、 Visual Studio のインストールだけでOKなようです。
  2. Windows Store(Windows8 以降)の C++ は従来に比べて非常に組み難くなっています。
    Windows ストアアプリの C++ が 従来の .NET Framework のものではなく、新しい WinRT という API を利用していることが原因のようです。
    従来使っていた API が使えなくなったり、やたらとチェックが厳しくコンパイルエラーが無くなるまでに一苦労です。
    「何でこれがエラーになるの (^_^;) 」と思うこともしばしばで、試行錯誤の連続です。
    コンパイルが通っても実行直後にエラーメッセージが表示されたり実行中にこけたりで、動くようになるまでは苦労の連続です。 (;_;)
    また仕様の公開が不十分で解りにくく、新しいことに挑戦しようとなると至難の業です。
    スマホならともかく、パソコンでは従来の OS(Windows7 など)でことが足りるなら、その方がお勧めです。
  3. DirectX は基本的なプログラミングの知識を持っていることが前提で、初心者にはちょっと難しいかも知れません。
    Store App の DirectX ではさらに輪をかけて組み難くなっています。
    DirectX9(X10) でことが足りるなら、絶対にその方がお勧めです。 ヽ(^^ )
    3Dモデルを使わない2Dゲームでは[Windows デスクトップ アプリケーション]で開発するのがお勧めです。
    [Windows デスクトップ アプリケーション]を使うと Windows7 と同様にメッセージループでレンダリングすることが出来ます。
  4. DirectX には Direct2D と Direct3D があります。
    Direct2D は従来の DirectDraw と同様に、二次元画像を描画する機能です。
    Direct3D では、立体モデルなどを描画します。
    最も困るのがネットで検索すると新旧の DirectX のページが混在していることです。
    Store App 以前の DirectX とは仕様が異なるので参考になりませんし、Store App でもバージョンが異なると動きません。
  5. 今までの Direct3D では「X-FILE や .sdkmesh」など、3Dモデルの標準フォーマットが定められていました。
    また、標準モデルをロードする機能がサポートされていたのですが、Windows8 では無くなったようです。
    3Dモデルを描画するサンプルも「OBJモデル」を専用のコンバータを使って一時的に内部形式に変換しています。
    X-FILE などを描画するには、専用のローダーを開発しなければならないようです。
  6. Windows Store(Windows8 以降)でもデスクトップモードに切り替えると従来のアプリを動かすことが出来ます。
    また Visual Studio のバージョンやプロジェクトの種類にもよるのですが、従来のプロジェクトをコンパイルすることも出来るようです。
    以前は[上位互換]と言って、古いバージョンのプロジェクトをコンパイル出来たのですが、動かない場合もあるようです。
    特に DirectX では[上位互換]は保たれていないので要注意です。
  7. WinRT の API は非常に使い難いのですが、C# の WPF プロジェクトでは従来と同じ .NET Framework を使っています。
    WPF(Windows Presentation Foundation) アプリはフォルダーの構成がシンプルで、自動的に[スタート][すべてのアプリ]に登録されることはありません。
    ソースコードは従来と多少異なるようですが、同じようにプログラミング出来るようです。
    但し DirectX のプロジェクトは C# は使えず C++ で開発しなけれはならないようです。

Windows & DirectX

Windows System, Visual Studio, DirectX はバージョンアップが繰り返され、組み合わせによっては動きません。
そこで DirectX の開発環境を含め、プログラミングの要点をまとめてみました。

  1. 1994/01/18 PC9821AP2 を購入しました。
    OS は MS-DOS 6.2 & Windows 3.1 です。
    1995/11/23 Windows95 をインストールして DirectX-5, DirectX-6 を始めます。
  2. 1998/09/02 Pro-400S を購入しました。
    OS は Windows98, WindowsME です。
    当初は Visual C++ ver 1.5 をインストールしましたが、Visual C++ ver 2.0 にバージョンアップします。
    その後 Visual Studio 6.0 にバージョンアップします。
    DirectX-7, DirectX-8 のプロジェクトは、Windows98(WindowsME) & Visual Studio 6.0 の環境で開発します。
    この頃から DirectX のホームページ掲載を始めました。
    WindowsXP 以前のOS(Windows95, Windows98, WindowsME)では Visual Studio 6.0 & DirectX9 が適しているようです。
  3. 2002/12/18 Windows XP が搭載された VAIO を購入しました。
    Windows XP(ウィンドウズ エックスピー)は、マイクロソフトが2001年に発表したWindowsシリーズに属するオペレーティングシステム(OS)です。
    WindowsXP は旧システムと新システムの境界で、Visual Studio 6.0 も Visual Studio .NET も一応動きますが、ハードの仕様によっては動かないことがあります。
    Visual Studio 6.0 を使った場合には DirectX 9.0 Summer 2003 が適しているようです。
    Visual Studio .NET(7.0) を使った場合には DirectX 9.0 April 2005 が適しているようです。
  4. 2007/01/06 DELL(DIMENSION 9200)を購入します。
    購入時は XP ですが、Vista にバージョンアップが出来ます。
    2007/01/06 以降のプロジェクトは、WindowsXP & Visual Studio .NET 2003 の環境で開発します。
  5. 2007/04/02 Vista にバージョンアップします。
    Windows vista からは Visual Studio .NET & DirectX August 2007 がお勧めです。
    August 2007 は DirectX9 と DirectX10 の境界で、Windows vista 上で DirectX9 が動作します。
    vista からシステムの安定とセキュリティの強化から (^_^;) 不正(不用意)なメモリ領域へのアクセスを厳しく管理するようになりました。
    今まで問題なく通っていた string 関係の関数を中心として warning(警告)が発せられます。
  6. 2008/7 DirectX August 2007 を使います。
    Windows vista & VisualC++ .NET 2005 & August 2007(X9, X10)の環境で開発します。
    August 2007 は DirectX9 と DirectX10 の境界で、vista 上で DirectX9 が動作します。
    DirectX10 以降では、ビデオカードの仕様が大きく変わり、例え Windows vista に対応していても X10 が動かないことがあります。
    DirectX10 August 2007 ではプログラムシェーダー4.0 に対応したグラフィックボードが必要になります。
    私も Vista にバージョンアップしたのですが、DirectX10 には対応していませんでした。 (;_;)
    ビデオカードの発展は留まることを知らず、DirectX November2008 では GPU を汎用の演算用途に用いようというアイデアが提唱され、GPGPU(Genral Purpose GPU)という概念が生まれました。
    GPGPU に対応するビデオカードは 2009 年度中には発売される予定です。
    また GPGPU の概念は DirectX に留まらず、新しい OS の開発にも大きな影響を及ぼしそうです。
  7. 2010/01 に待望の DirectX 10 対応のマシン Dell(Studio 540)を購入しました。\(^o^)/
    購入時は Vista ですが、Windows7 にバージョンアップすることが出来ます。
    Windows7 & Visual Studio .NET2005 & DirectX November2008 の組み合わせで順調に動いています。
    DirectX November2008 には DirectX10 だけでなく、DirectX9 や DirectX11 のプログラムも含まれています。
    そこで DirectX11 のサンプルを実行しようとしたのですが、残念ながら起動出来ませんでした。 (^_^;)
    November2008 の DirectX11 は開発途上のようで、DirectX11 を学ぶなら June 2010 を使って下さい。
    DirectX-9, DirectX-10 のプロジェクトは、この環境で開発しています。
  8. 2011/12 には Visual C++ 2010 Express をインストールしました。
    12月以降の環境は Windows7 & Visual C++ 2010 Express & DirectX June 2010 の組み合わせで動かします。
    DirectX-9, DirectX-10, DirectX-11 のプロジェクトは、この環境で開発しています。
    June 2010 のインストールと時を同じくして mview.exe(X-FILE の Viewer)がダブルクリックで起動出来なくなりました。
    Summer2004 をインストールしている(Vista)でも同じ現象が起きているので June 2010 のインストールとは関係ないかも知れません。
    mview.exe は DirectX のユーティリティに格納されていた長年愛用のプログラムです。
    June 2010 のユーティリティには格納されておらず、いよいよ X-FILE も賞味期限が切れたのでしょうか。 (^_^;)
    「超初心者のプログラム入門(DirectX9)/Sample Brower のプロジェクト/Mview を作成する」で X-FILE の Viewer の作成方法を解説しています。
  9. X-FILE に代わるのが sdkmesh ですが評判は今ひとつで、3Dアニメーションでもメタセコイアや六角大王が幅を利かしています。
    【注】これらのソフトでアニメーションするには、外部ソフト(RokDeBone2 や Mikoto など)を利用します。
    sdkmesh に関して気になるページを見つけました。
    SDK メッシュ ファイル形式の概要
    DXUT メッシュ形式 (.sdkmesh) は製品版のタイトルに推奨されるファイル形式ではありません。
    この形式は、SDK サンプルの特定の要求に合わせて設計されています。
    実際のアプリケーションでは、アプリケーションの特定の要求を満たす形式を優先し、このファイル形式の使用は避けてください。
  10. 2012/09/02 Windows8 評価版をインストールします。
    Windows8 & Microsoft Visual Studio Express 2012 for Windows 8 の環境で開発します。
  11. Microsoft は 2012/10/末 に新しいOSである Windows8 の発売を開始しました。 \(^o^)/
    Windows8 は Windows7 までと、仕様が大きく変わっています。
    DirectX も同様で「Windows7 までとは全く違う」と言っても過言ではありません。
    Windows8 からは DirectX のインストールは必要無く Visual Studio のインストールだけで 組み合わせなどを考える必要はありません。
    但し、Windows8(8.1)で DirectX9(X10,X11)を使うときは、従来と同様にインストールする必要があります。
  12. 2012/11/06 Windows8 搭載のパソコン VALUESTAR(NEC) を購入します。
    Windows8 DirectX のプロジェクトは、Windows8 & Visual Studio Express 2012 for Windows 8 の環境で開発します。
    自動的に生成される Direct2D のサンプルは XAML が組み込まれた静的な描画プロジェクトです。
    C# や C++ と同様に、ページを遷移するプログラムには向いているのですが、アニメーションなどには向きません。
    そこで XAML を外してレンダリングループを組み込み、アニメーションができるようなテンプレートを提供しています。
  13. 2013/07/24 Windows8.1 評価版をインストールします。
    また [Microsoft Visual Studio Professional 2013 Preview - 日本語] をダウンロードしました。
    Windows8.1 評価版 & Microsoft Visual Studio Professional 2013 Preview - 日本語の環境で開発します。
  14. 2013/10/20 Windows 8.1 正式版にバージョンアップしました。
    Windows 8.0 から Windows 8.1 には、無料でバージョンアップすることが出来ます。
    同時に Visual Studio Professional 2013 をダウンロードしました。
    2013/10/20 以降のプロジェクトは、Windows 8.1 & Microsoft Visual Studio Professional 2013 Preview の環境で開発します。
  15. 2014/01/20 Professional 2013 の試用期限が切れました。
    2014/01/22 以降は Windows 8.1 & Visual Studio 2005 の環境に戻ります。 (^_^;)
    2014/04/13 Windows 8.1 Update 版 に Vresion UP します。
  16. 2014/08/08 Windows8(8.1) で DirectX9 が動くようなのでデスクトップモードでテストしてみました。
    開発環境は Windows8.1 & Visual Studio 2005 & DirectX November 2008 です。
    C言語及びC#で作成した DirectX9 のプログラムが何の問題もなく実行出来ました。
    DirectX10 も動くのですが、ちょっとした工夫が必要です。
    詳細は Windows8+DirectX10 を参照して下さい。
  17. 2015/10/07 Windows10 をインストールします。
    ブラウザも Internet Explorer から Edge に変わっているようです。
    Windows10 の使い勝手は Windows7 に比べても大きな相違は無く、戸惑うことはなさそうです。
    私の DirextX もこれまでかと諦めていたのですが、幸いにして Visual Studio Community 2015 を手に入れることが出来ました。
    2015/10/08 以降は Windows10 & Visual Studio Community 2015 の環境で開発します。
  18. 2016/05/24 Windows10 が不安定になり再セットアップした所、Visual Studio Community 2015 で作成した従来のプロジェクトが起動出来なくなりました。
    Visual Studio 2015 にも幾つかの Version が存在するようで要注意です。
    ちなみに新しくインストールした Version は Microsoft Blend for Visual Studio Community 2015 Version 4.6.01038 です。
    操作の方法や作成されるプロジェクトには大きな違いはないようですが、以前のプロジェクトが開けないのは困りもんです。
    何か方法があるのでしょうね。 (^_^;)
    幸いにしてソースファイルはそのまま使えるようなので、プロジェクトを組みなおすだけでOKです。
    DirectX のプロジェクトを構築するときは Visual Studio Community 2015 を立ち上げます。(Blend ではない)
    完成したプロジェクトを *.sln から起動すると Blend for Visual Studio が立ち上がります。
  19. 2017/08 Blend for Visual Studio Community 2017 Version 15.2(26430.16) をダウンロードしました。
    Visual Studio 2015 で開発したプロジェクトは、そのまま動くようです。
    詳細は [DirectX Store] から [Visual Studio 2017 DirectX] を参照して下さい。
    2019/01/12 Visual Studio Enterprise 2019 Preview をダウンロードしました。
    2019/05/15 Visual Studio Professional 2019 16.0.4 にバージョンアップしました。

3Dグラフィックス

3Dグラフィックスを描画するための座標系やカリングモードの説明です。

    左手座標系と右手座標系

  1. 座標系には左手座標系と右手座標系があります。
    DirectX
    1. DirectX では好きな方に設定出来ますが、左手座標系が一般的です。
      左手座標系では左下を基点にして、座標が大きくなる方向は「右(X座標), 上(Y座標), 奥(Z座標)」です。
    2. カメラは手前(Z座標が負の値)に置くのが基本です。
          D3DXMatrixLookAtLH(&matView,
              &D3DXVECTOR3(0.0f, 0.0f, -5.0f),
              &D3DXVECTOR3(0.0f, 0.0f, 0.0f),
              &D3DXVECTOR3(0.0f, 1.0f, 0.0f) );
      
    3. Windows Store の DirectX では、規定値が右手座標系に変わっているようです。
      また座標が大きくなる方向はC#とは異なり「左(X座標), 下(Y座標), 手前(Z座標)」のようです?
          m_camera->SetViewParameters(
              float3(0, 1.0f, 2.0f),
              float3(0, 0, 0),
              float3(0, 1, 0) );
      
  2. C#
    1. C# では右手座標系が使われているようです。
      右手座標系では左下を基点にして、座標が大きくなる方向は「右(X座標), 上(Y座標), 手前(Z座標)」です。
    2. カメラはZ座標が正の値に置くのが基本です。
          device.Transform.View = Matrix.LookAtLH(
              new Vector3( 0.0f, 0.0f, 5.0f ),
              new Vector3( 0.0f, 0.0f, 0.0f ),
              new Vector3( 0.0f, 1.0f, 0.0f ) );
      
  3. XNA
    1. XNA では右手座標系が使われているようです。
      右手座標系では左下を基点にして、座標が大きくなる方向は「右(X座標), 上(Y座標), 手前(Z座標)」です。
    2. カメラはZ座標が正の値に置くのが基本です。
          basicEffect.View = Matrix.CreateLookAt(
              new Vector3(0.0f, 0.0f, 5.0f),
              Vector3.Zero,
              Vector3.Up );
      
  4. Java3D
    1. Java3D では右手座標系が使われているようです。
      右手座標系では左下を基点にして、座標が大きくなる方向は「右(X座標), 上(Y座標), 手前(Z座標)」です。
    2. カメラはZ座標が正の値に置くのが基本です。

    頂点データの形式

  5. Shade(3Dツール)のようにソリッドモデルを使う場合もあるのですが、主流はモデルをポリゴンの集合として扱います。
    ポリゴンは3角形、4角形、5角形以上があるのですが、3角形を超えると鞍点が出来て座標計算に時間がかかります。
    そこで DirectX では3角形ポリゴンを組み合わせてモデルを表現します。
  6. DirectX では、ポリゴンの頂点座標を構造体を用いて定義します。
    構造体(頂点座標の形式)は、次の要素で構成されます。
  7. 実際のモデルでは、上で述べた全てが使われる訳ではありません。
    最も簡単なモデルは、頂点座標だけです。
    DirectX9 の自動生成モデルでは、頂点座標と法線ベクトルで構成されていました。
    Store App の DirectX のサンプルプロジェクトでは、頂点座標と色情報で構成されています。
    Store App で Basic Shapes Class を使って生成したモデルは、頂点座標と法線ベクトルとテクスチャ座標で構成されます。
  8. 法線ベクトルが設定されていないと、光源で照らした場合に光と影が表現できないので、立体感が得られません。
    色情報が無いと白黒になるのですが、DirectX Store ではピクセルシェーダーでモデル全体の色を設定します。
    テクスチャ座標は、画像をポリゴンに貼り付けるときにだけ関係します。

    カリングモード

  9. カメラをまわしてポリゴンを裏側から描画して見ると解りますが、ポリゴンが描画されません。
    これは不要な処理を省くために「ポリゴンの裏側を描画しない」ようにカリングモードが設定されているからです。
    カリングモードの規定値は「反時計回りの面をカリング」して、時計回りの面を描画するように設定されています。
  10. TRIANGLESTRIP で二個以上の矩形を組み合わせるときのカリングモードと頂点座標の関係は、次のように決めると解りやすいでしょう。
    三次元座標では左下を基点にして、座標が大きくなる方向は「右(X座標), 上(Y座標)」です。
    ウインドウや画像の座標とは異なるので注意して下さい。

  11. テクスチャ座標は、画像のサイズに関係なく「左上=0.0f, 0.0f, 右下=1.0f, 1.0f」とした float タイプで設定します。

    Java のテクスチャ座標は「左下=0.0f, 0.0f, 右上=1.0f, 1.0f」で DirectX とは異なっていました。
  12. DirectX のカリングモードの設定です。
    反時計回りをカリング 表面を描画(規定値) g_pDEV->SetRenderState(D3DRS_CULLMODE,D3DCULL_CCW);
    時計回りをカリング 裏面を描画 g_pDEV->SetRenderState(D3DRS_CULLMODE,D3DCULL_CW);
    カリングなし 両面を描画 g_pDEV->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
  13. Java のカリングモードの設定です。
    反時計回りをカリング 表面を描画(規定値) pattr.setCullFace(PolygonAttributes.CULL_BACK);
    時計回りをカリング 裏面を描画 pattr.setCullFace(PolygonAttributes.CULL_FRONT);
    カリングなし 両面を描画 pattr.setCullFace(PolygonAttributes.CULL_NONE);
  14. C# のカリングモードの設定です。
    反時計回りをカリング 表面を描画(規定値) device.RenderState.CullMode = Cull.CounterClockwise;
    時計回りをカリング 裏面を描画 device.RenderState.CullMode = Cull.Clockwise;
    カリングなし 両面を描画 device.RenderState.CullMode = Cull.None;
  15. XNA のカリングモードの設定です。
    反時計回りをカリング 表面を描画(規定値) GraphicsDevice.RenderState.CullMode = CullMode.CullCounterClockwiseFace;
    時計回りをカリング 裏面を描画 GraphicsDevice.RenderState.CullMode = CullMode.CullClockwiseFace;
    カリングなし 両面を描画 GraphicsDevice.RenderState.CullMode = CullMode.None;

    マテリアルの説明

  16. マテリアルとは、ポリゴンの色を決める属性となるもので、反射特性、放射特性、反射係数、半透明特性などのことを言います。
  17. ディフューズ属性(diffuse)
    一次反射色のことで、光源によって影響される色で、光源からの入射角が垂直に近いほど効果が強くなる色の属性。
  18. アンビエント属性(ambient)
    環境光色のことで、光源によって影響される色であるが、光源からの向きや距離に関わらず一定の効果が反映される色の属性。
  19. エミッション属性(emissive property)
    自己発色属性、素材のライトに依存しない色属性を示すマテリアル属性、発光または発色。
  20. スペキュラ属性(specular property)
    ライトからの入射光の角度と視点への反射光の角度の両方に依存したマテリアル属性。
  21. 強度(power)
    マテリアルのスペキュラ属性で、スペキュラ ハイライトの鮮明度を決める値。
    この値が 5 のときは金属的な外観になり、値がもっと高くなるとよりプラスチック的な外観になる。
  22. アルファ チャネル(alpha channel)
    アルファ値によって定義される、画像の半透明特性(アルファ・ トランスペアランシー)。
    不透明度を定義するアルファ値は、ピクセル単位にほかの色成分と共に与えられるか (ARGB などの場合)、 独立したアルファ サーフェス内でピクセル単位に与えられるか、またはサーフェス全体に固定の値で与えられる。

回転座標

回転座標の計算です。

    正十角形の座標計算

  1. 中心座標を 0,0 として、半径から正十角形の座標を計算してみましょう。

  2. 正十角形の中心角は 36 度なので次の式でP座標の中心からのズレ(横方向)が計算できます。
    X= sin(36)*半径
  3. 同様にP座標の中心からのズレ(縦方向)は次の式で計算できます。
    Y= cos(36)*半径
  4. 従って、回転軸の中心を 0,0 とすると、36 度左回転した時の座標(P)は次のようになります。
    X座標= -(sin(36)*半径), Y座標=-(cos(36)*半径)
  5. 同様に 36 度右回転した時の座標は次のようになります。
    X座標= sin(36)*半径, Y座標=-(cos(36)*半径)

    回転座標を求める関数

  6. 回転軸の中心を 0,0 として、二次元の回転座標を計算します。
        // 回転計算
        void  rot(float rt, float len, float *x, float *y)
        {   *x= (LONG)(sin(rt/180*3.14)*len);
            *y= (LONG)(cos(rt/180*3.14)*len);
        }
        
    rot() 関数のパラメータの説明です。
    引数 説明
    rt 回転角度
    len 円の半径
    *x X座標を格納する領域
    *y Y座標を格納する領域
  7. 回転軸の中心点を「0,0,0」として、三次元座標の回転を計算する Rotate() 関数です。
        void  Rotate(D3DXVECTOR3 *Vect, float rt, int xyz)
        {   float   px,py,pz;
    
            px= Vect->x;
            py= Vect->y;
            pz= Vect->z;
            switch(xyz)
            {   case 0: Vect->z= (float)(pz*cos(rt)-py*sin(rt));
                        Vect->y= (float)(pz*sin(rt)+py*cos(rt));
                        return;
                case 1: Vect->x= (float)(px*cos(rt)-pz*sin(rt));
                        Vect->z= (float)(px*sin(rt)+pz*cos(rt));
                        return;
                case 2: Vect->y= (float)(py*cos(rt)-px*sin(rt));
                        Vect->x= (float)(py*sin(rt)+px*cos(rt));
                        return;
            }
        }
        
    Rotate() 関数のパラメータの説明です。
    引数 説明
    *Vect 元の3次元座標
    *Vect 回転した値を格納する
    rt 回転角度
    xyz 回転軸(0:X, 1:Y, 2:Z)
  8. 回転軸の中心点を指定して、三次元座標の回転を計算する Rotate() 関数です。
        void  Rotate(D3DXVECTOR3 *Vect,D3DXVECTOR3 *Cen,float rt,int xyz)
        {   float   px,py,pz;
    
            px= Vect->x-Cen->x;
            py= Vect->y-Cen->y;
            pz= Vect->z-Cen->z;
            switch(xyz)
            {   case 0: Vect->z= (float)(pz*cos(rt/180*3.14)-py*sin(rt/180*3.14)+Cen->y);
                        Vect->y= (float)(pz*sin(rt/180*3.14)+py*cos(rt/180*3.14)+Cen->z);
                        return;
                case 1: Vect->x= (float)(px*cos(rt/180*3.14)-pz*sin(rt/180*3.14)+Cen->x);
                        Vect->z= (float)(px*sin(rt/180*3.14)+pz*cos(rt/180*3.14)+Cen->z);
                        return;
                case 2: Vect->y= (float)(py*cos(rt/180*3.14)-px*sin(rt/180*3.14)+Cen->x);
                        Vect->x= (float)(py*sin(rt/180*3.14)+px*cos(rt/180*3.14)+Cen->y);
                        return;
            }
        }
        
    Rotate() 関数のパラメータの説明です。
    引数 説明
    *Vect 元の3次元座標
    *Vect 回転後の値を格納する
    *Cen 回転軸の基点
    rt 回転角度
    xyz 回転軸(0:X, 1:Y, 2:Z)

    変換行列を使って座標を回転

  9. DirectX の変換行列を使ってライトの座標を回転してみましょう。
    ライトの座標を次のように定義します。
        D3DXVECTOR3     vLight(2,-3,2);     // ライトの座標の初期値
    
        light.Direction = vLight;
        g_pDEV->SetLight(0,&light);
        
  10. 変換行列を使って、Y軸を中心に回転する MatRotate() 関数です。
    *Vect で渡された座標を、Y軸を中心にして rt(ラジアン角)度回転します。
        void  MatRotate(D3DXVECTOR3 *Vect,float rt)
        {  D3DXMATRIX   mat;
           // 変換マトリックスの作成
           D3DXMatrixIdentity(&mat);
           mat._11 = cos(rt);   mat._13 = -sin(rt);
           mat._31 = sin(rt);   mat._33 = cos(rt);
           D3DXVec3TransformNormal(Vect, Vect, &mat);
        }
    
    DirectX Store で変換行列を使って回転する方法が解らなかったので三次元座標を回転する関数を作成しました。
    回転結果は変換行列を使ったときと一致するようです。
    // 中心点を 0,0,0 として、座標 pos を rx, ry, rz で回転する
    float3 Rot3D(float3 pos, float rx, float ry, float rz)
    {
        float3  ans, wk;
        ans = pos;
        wk = pos;
        ans.y = (float)(wk.y*cos(rz) - wk.x*sin(rz));
        ans.x = (float)(wk.y*sin(rz) + wk.x*cos(rz));
        wk = ans;
        ans.x = (float)(wk.x*cos(ry) - wk.z*sin(ry));
        ans.z = (float)(wk.x*sin(ry) + wk.z*cos(ry));
        wk = ans;
        ans.z = (float)(wk.z*cos(rx) - wk.y*sin(rx));
        ans.y = (float)(wk.z*sin(rx) + wk.y*cos(rx));
        return ans;
    }
    
    その後、ようやく変換行列を使って回転する方法が解りました。
    ところが何故か Rot3D() と逆回転になるので RollPitchYaw で負の値を設定しています。
    座標の回転は vect = XMVector3TransformNormal(vect, mat); で終わっているのですが、そのあとのコードは float3 でリターンするためです。
    // 中心点を 0,0,0 として、座標 pos を rt で回転する
    float3 MatRotate(float3 pos, float3 rt)
    {
        XMMATRIX    mat;
        float3      ans;
        XMVECTOR    vect;
        vect = XMVectorSet(pos.x, pos.y, pos.z, 0.0f);
        mat = XMMatrixRotationRollPitchYaw(-rt.x, -rt.y, -rt.z);
        vect = XMVector3TransformNormal(vect, mat);
        ans.x = XMVectorGetX(vect);
        ans.y = XMVectorGetY(vect);
        ans.z = XMVectorGetZ(vect);
        return ans;
    }
    
  11. D3DXMATRIX mat は4*4の変換行列で、座標を移動するときは次のように設定します。

    また座標を回転するときは次のようになります。

    上図は DirectX の場合で、プログラム言語によっては「行と列が入れ替わる」場合があるので注意して下さい。
    また、Java の Matrix4f は m00 ~ m33 で、DirectX は ._11 ~ ._44 になっているので要注意です。
    例えば Java でX座標を移動するときは、次のようになります。
        Matrix4f mat4 = new Matrix4f
        ( 1.0f, 0.0f, 0.0f, 0.0f,
          0.0f, 1.0f, 0.0f, 0.0f, 
          0.0f, 0.0f, 1.0f, 0.0f,
          0.0f, 0.0f, 0.0f, 1.0f );
          // X軸で移動
          mat4.m03= -0.3f;
        ( 1.0f, 0.0f, 0.0f, 0.0f,
          0.0f, 1.0f, 0.0f, 0.0f, 
          0.0f, 0.0f, 1.0f, 0.0f,
         -0.3f, 0.0f, 0.0f, 1.0f );
        
  12. 設定する行列の場所や値を覚えなくても、便利な関数が用意されています。
    例えば、今回説明した使ったY軸を中心に回転するコードは
        // 変換マトリックスの作成
        D3DXMatrixIdentity(&mat);
        mat._11 = cos(rt);  mat._13 = -sin(rt);
        mat._31 = sin(rt);  mat._33 = cos(rt);
        
    次のように書くことが出来ます。
        D3DXMATRIX      matWorld;
        D3DXMatrixRotationY(&matWorld, rt);
        
    同様にX軸を中心に回転する場合は、次のように書きます。
        D3DXMATRIX      matWorld;
        D3DXMatrixRotationX(&matWorld, rt);
        
    コンパイラによって異なりますが、一般的に変換行列同士の演算が出来るようになっています。
        D3DXMATRIX      mat1;
        D3DXMATRIX      mat2;
        D3DXMATRIX      mat3;
        D3DXMatrixRotationY(&mat1, rt);
        D3DXMatrixRotationX(&mat2, rt);
        mat3 = mat1 * mat2;
        

    変換行列, オイラー角, クォータニオン

  13. モデルの回転座標を計算する方法として、変換行列が基本なのですが、オイラー角やクォータニオンも使われます。
  14. オイラー角は、XYZの軸を順番に回転してモデルの姿勢を決める方法です。
    yaw, pitch, roll の回転順序によって姿勢が変わるので要注意です。
    DirectX では、軸回転の順序は「ZXY」です。
  15. クォータニオンは、回転する軸の傾きをXYZで指定して、Wで回転の度合いを指定します。
    DirectX のアニメーション設定などで使われています。
  16. モデルで姿勢を確認しながら変換行列, オイラー角, クォータニオンの値を印字するツール 座標変換ツール を開発しました。
    リンクがエラーになるときは「前田稔(Maeda Minoru)の超初心者のプログラム入門」からたどって下さい。

DirectX の覚書

    DirectX8 まで

  1. DirectX は、ハードウエアやソフトウエアの発展と共にバージョンアップが繰り返され、留まる所を知らないようです。
    DirectX 開発の姿勢は、新技術に対応することが主眼で、ソフトウェアの上位互換は、二の次になってなっています。
    従って古いバージョンで作成したプログラムは、新しいバージョンでは動かなくなることが良く起こるので覚悟して下さい。
    大きく仕様が変わるときには、機能そのものが廃止されることも珍しくありません。
  2. DirectX7 までは DirectX の3Dは、IM(Immediate Mode)とRM(Retained Mode)に分かれていました。
    IMモードは、先進のグラフックボードが持つ優れた機能を引き出せるプログラムを作成することができる半面、基本の関数から自分で作成しなければなりません。
    RMモードでは、グラフック関係の多くの関数がサポートされていて、手軽にプログラミングを行うことができます。
    IM モードは3Dプログラムのアセンブラであり、RM モードは3DプログラムのC言語に例えることができるでしょう。
  3. DDS(DDSURFACEDESC)は DirectX7 から使われ始めたαチャンネル付の画像です。
    残念ながら一般的では無く、DirectX(X-FILE)以外では見かけることは無いようです。
    DDS 形式の画像ファイルを作成する で、ファイルの作成方法とビューアのプログラムを掲載しています。
  4. DirectX8 から「DirectDraw」「Direct3D」と呼ばれていたグラフィックス機能が DirectGraphics として統合されました。
    実質的には DirectDraw が廃止されました。
    DirectDraw に代わる2Dグラフィックスの機能として、Sprite がサポートされました。
    私のホームページでは DIrectX6 の頃から DirectDraw を使って画像を切り分ける Sprite Class(Sprite.cpp)を使っていました。
    DirectX 以外でも Sprite Class を使っているので、DirectX8 の Sprite と混同しないように注意して下さい。

    DirectX9

  5. DirectX 9.0 Summer 2003 から Sprite 関係の仕様が変更されているので注意が必要です。
    新しい仕様では、回転や移動は3D描画と共通です。
    HRESULT Draw(
        LPDIRECT3DTEXTURE9 pTexture,
        CONST RECT         *pSrcRect,  //Sprite の表示範囲
        CONST D3DXVECTOR3  *pCenter,   //Sprite の中心点
        CONST D3DXVECTOR3  *pPosition, //Sprite の中心点の表示位置
        D3DCOLOR           Color
    );
    
    古い仕様では、回転や移動のパラメータを設定します。
    HRESULT Draw(
        LPDIRECT3DTEXTURE9 pSrcTexture,
        CONST RECT         *pSrcRect,
        CONST D3DXVECTOR2  *pScaling,
        CONST D3DXVECTOR2  *pRotationCenter,
        FLOAT              Rotation,
        CONST D3DVECTOR2   *pTranslation,
        D3DCOLOR           Color
    );
    
  6. DirectX 9.0 Summer 2004 からはテンプレート機能が使え無くなっています。
    その代わりに DirectX Sample Browser を使って、サンプルプログラムからプロジェクトを構築することが出来ます。
  7. DirectX 9.0(Summer 2004) は64ビットに対応していて、Visual Studio 6.0 で使うときは注意が必要です。
    MicroSoft のダウンロードのホームページに、こんな記述があります。
        Extras
        Extras ダウンロードには、ソフトウェア開発キットには含まれていない以下の内容が入っています。
          ・Visual Studio 6.0 をサポートする d3dx.lib
          ・以前のバージョンのCDツール プラグイン
          ・日本語ドキュメント
        
  8. Visual Studio 6.0 で Summer 2004 に更新すると次のエラーがでました。
    原因は Visual Studio 6.0 にあるようで、Visual Studio 7.0(.NET) を使うとエラーは無くなりました。
        --------------------構成: Main - Win32 Debug--------------------
        コンパイル中...
        Main.cpp
        STAR.cpp
        リンク中...
        d3dx9.lib(fastftoa.obj) : error LNK2001: 外部シンボル "__aulldvrm" は未解決です
        Debug/Main.exe : fatal error LNK1120: 外部参照 1 が未解決です。
        link.exe の実行エラー
    
        Main.exe - エラー 2、警告 0
        
  9. DirectX 9.0 April 2005 で Summer 2003 のテンプレートで作成したプロジェクトをコンパイルした所「ライブラリが見つからない」のエラーが表示されました。
    d3dx9dt.lib
    調べて見ると d3dx9dt.lib の名前が d3dx9d.lib に変わっていました。

    DirectX10

  10. DirectX10 のメッシュファイルは拡張子が .x から .sdkmesh になり、X-FILE(拡張子が .X のファイル) がサポートされなくなりました。
    X-FILE は TEXT 形式で、エディタなどを使うと内容を確認できたのですが、sdkmesh は Binary 形式でフォーマットが解らないと判読不能です。
    DirectX SDK には X-FILE を sdkmesh に変換するプログラム(meshconvert)が格納されています。
    一部うまく変換されないところもあるようですが、一応使えるようです。
    詳細は「超初心者のプログラム入門(DirectX10)/X-FILE を sdkmesh にコンバートして描画」を参照して下さい。
    また Shader Program が必須になり、頂点シェーダー、ピクセルシェーダー、ジオメトリシェーダーが使えるようになりました。
  11. DirectX も 32bit から 64bit に移って行くのでしょうが、November 2008 では、32bit が使われています。
    ところが Windows7 で C# を使ったときの既定値は 64bit で DirectX の DLL を呼び出すことが出来ません。
    そこで C# で DirectX を組む時は 32bit(X86) に設定します。
    次のエラーが表示されたときは、これが原因です。
    BadImageFormatException はハンドルされませんでした。
    Any CPU の右のリストボックスをクリックして X86 に設定します。
    詳細は「超初心者のプログラム入門(C# Frame Work)/DirectX Program/Direct 3D で Form を表示する」 を参照して下さい。
    Windows とコンパイラが全て 64bit に移ってしまえば、こんな問題は起こらないのでしょうが、当分の間は泣かされそうです。 (^_^;)
  12. 2011/12/10 DirectX June2010 にバージョンアップします。
    Sample Browser のプロジェクトの拡張子が vcproj から vcxproj に変わっています。
    .NET2005 から起動出来るプロジェクトファイル(vcproj)は作成されません。
    私も Visual Studio 2008 をインストールして、やっとプロジェクトファイルが起動出来るようになりました。

    DirectX Store App

  13. Windows8 & DirectX
    1. Microsoft は 2012/10/末 に新しいOSである Windows8 の発売を開始しました。 \(^o^)/
      Windows8 は、これまでの OS と仕様が大きく変わっていて、Windows Phone など携帯端末やスマホにも対応する OS です。
      DirectX も同様で「DirectX10(X11) までとは全く違う」と言っても過言ではありません。
      Windows8 のプログラムを作成するには、ストアアプリ(Metro Style)に対応した専用の開発ソフトが必要です。
      私は Microsoft Visual Studio Express 2012 for Windows 8 を使っています。
      DirectX10 までは Visual Studio をインストールしてから、さらに DirectX のインストールが必要でした。
      Windows8 からは DirectX のインストールは必要無いようで、 Visual Studio のインストールだけでOKなようです。
      Visual Studio for Windows 8 では DirectX はC言語(C++)で開発するようで、C# からは DirectX が選択出来ません。
      また、サンプルで提供されている DirectX のプログラムも全てC言語(C++)が使われていました。
    2. Windows7 までは Windows でも簡単なアニメーションプログラムは作成できましたが、Windows8 ではレンダリングループを使うようなプログラムは DirectX に限られるようです。
      DirectX には Direct2D と Direct3D があります。
      Direct2D は従来の DirectDraw と同様に、二次元画像を描画する機能です。
      Direct3D では、立体モデルなどを描画します。
    3. 自動的に生成される Direct2D のサンプルは XAML が組み込まれた静的な描画プロジェクトです。
      C# や C++ と同様に、ページを遷移するプログラムには向いているのですが、アニメーションなどには向きません。
      そこで XAML を外してレンダリングループを組み込み、アニメーションができるようなテンプレートを提供しています。
      超初心者のプログラム入門(DirectX Store) を参照して下さい。
    4. 今までの Direct3D では「X-FILE や .sdkmesh」など、3Dモデルの標準フォーマットが定められていました。
      また、標準モデルをロードする機能がサポートされていたのですが、Windows8 では無くなったようです。
      3Dモデルを描画するサンプルも「OBJモデル」を専用のコンバータを使って一時的に内部形式に変換しています。
      X-FILE などを描画するには、専用のローダーを開発しなければならないようです。
    5. 2014/08 Windows8 + DirectX9 のデスクトップモードで従来の DirectX9 が動くようです。
      Windows8.1 で確認したのですが、Windows8 でも同じように動くはずです。
      DirectX9 をインストールしてインクルードファイルとライブラリファイルのパスを設定して下さい。
      また CPU モードを X86(W32) に設定して下さい。

    Windwos8.1 & DirectX9

  14. Windows8.1
    1. 2013/10/20 Windows 8.1 正式版にバージョンアップしました。
      同時に Visual Studio Professional 2013 をダウンロードしました。
      2014/04/13 Windows 8.1 Update 版 に Vresion UP します。
      ネットから無料でバージョンアップ出来ます。
      2013/10/20 以降のプロジェクトは、Windows 8.1 と Visual Studio Professional 2013 の環境で開発します。
    2. 2014/01/20 Professional 2013 の試用期限が切れました。
      仕事で使うならともかく、個人で購入するには高価過ぎます。
      2014/01/22 以降は Windows 8.1 & Visual Studio 2005 の環境で開発します。 (^_^;)
    3. 2014/08 Windows8.1 のデスクトップモードで従来の DirectX9 を動かしてみました。
      Windows 8.1 ですがストアアプリでは無いので念のため。
      Windows8.1 + DirectX9 の環境でC言語及びC#で作成した DirectX9 の実行を確認しました。
      • Windows 8.1 Update 版
      • Visual Studio 2005
      • DirectX November 2008
      • デスクトップモード
      DirectX9 をインストールしてインクルードファイルとライブラリファイルのパスを設定して下さい。
      CPU モードを X86(W32) に設定して下さい。
    4. Sample Browser で作成した DirectX10 のプロジェクトで動くのは MultiMon10 だけのようです。 (^_^;)
      他のプロジェクト(Tutorial も含め)ではデバイスが取得できないようで、次のエラーが表示されます。
      Failed create the Direct3D device
      
      Windows8.1 で DirectX10 を動かすには3Dデバイスの取得に一工夫必要なようです。
      DirectX9 のプロジェクトは問題なく動くので念のため。
      その後の調査で Release Mode でコンパイルすれば動くことが判明しました。
      詳細は Windows8+DirectX10 を参照して下さい。
    5. DirectX June 2010 を使って Sample Browser で作成したプロジェクトは Visual Studio 2005 では起動出来ません。
      本来なら Visual Studio 2008 以上を使うのでしょうが、あえて Visual Studio 2005 で起動する方法を説明します。
      ①_2008.vcproj を修正して下さい。
        Version="9.00" ⇒ Version="8.00"
      ②_2008.vcproj をダブルクリックで起動します。
        Visual Studio 2005 が起動するので、コンパイルします。
      ③終了時に _2008.sln に保存します。
      ④_2008.sln をダブルクリックして起動します。
        最初 asm.v3 の警告が表示されますが、二度目からは無くなります。
      この方法で DirectX9 のプロジェクトが無事コンパイル出来ました.
      DirectX10 のときは Release Mode に設定して下さい。

    Windwos10 & DirectX

  15. Windows10
    1. 2015/10/07 Windows10 と Visual Studio Community 2015 をダウンロードしました。
      2015/10/08 以降は Windows10 & Visual Studio Community 2015 の環境で開発します。
      従来は Visual Studio だけでは動かず DirectX のインストールも必要だったのですが、その必要は無いようです。
      ストアアプリの DirectX は、C言語(C++)で作成します。
    2. DirectX Windows8 のプロジェクトは Windows8.1 以降では動かないようで、組み直しが必要なようです。
      DirectX Windows8.1 のプロジェクトは Visual Studio 2015 でそのまま起動できるようです。
    3. 私は 2017/08 Blend for Visual Studio Community 2017 Version 15.2(26430.16) をダウンロードしました。
      ストアアプリの DirectX はC言語で開発していたのですが、何故かC言語(DirectX)のテンプレートが表示されません。
      [新規プロジェクト]から[Visual Studio インストーラーを開く]をクリックして[更新]しなければならないようです。
      詳細は [DirectX Store] から [Visual Studio 2017 DirectX] を参照して下さい。

DirectX Programming Note

DirectX では Windows Programming では余りみかけないプログラミング手法が使われています。
  1. SAFE_DELETE
    NULL を判定して、開放されていない Object Class などを開放します。
    ID3DX10Sprite*              g_pSprite = NULL;
    CDXUTTextHelper*            g_pTxtHelper = NULL;
    
    SAFE_DELETE( g_pTxtHelper );
    SAFE_RELEASE( g_pSprite );
    
    SAFE_DELETE などは #define で宣言します。
    #define     SAFE_DELETE(p)  { if (p) { delete (p);     (p)=NULL; } }
    #define     SAFE_RELEASE(p) { if (p) { (p)->Release(); (p)=NULL; } }
    #define     SAFE_DELDC(p)   { if (p) { DeleteDC (p);   (p)=NULL; } }
    #define     SAFE_DELOBJ(p)  { if (p) { DeleteObject(p); (p)=NULL; } }
    
  2. #pragma
    ライブラリを [プロジェクト] [プロパティ] [リンカ] [入力] から追加する代わりに #pragma を使うことができます。
    #pragma once は、同じライブラリを重複して組み込まないようにする指定です。
    #pragma once
    #pragma comment(lib,"dxerr.lib")
    #pragma comment(lib,"dxguid.lib")
    #pragma comment(lib,"winmm.lib")
    #pragma comment(lib,"comctl32.lib")
    #pragma comment(lib,"dxgi.lib")
    #pragma comment(lib,"d3d10.lib")
    #pragma comment(lib,"d3dx10.lib")
    
  3. float Type のデータ
    短精度浮動小数点で、4バイト(32bit)のデータです。
    DirectX では、精度を上げて計算する必要が無いことが多いので float Type が良く使われます。
    float Type のデータを編集して Message Box に表示するプログラムです。
    float   fval = 0.123f;
    char    str[80];
    sprintf(str,"%8.2f\n",fval);
    MessageBox(NULL,str,"Debug Message Box",MB_OK);
    
  4. Unicode に変換して Message Box に表示するときは次のようになります。
    Unicode の詳細は Programing Guid から「文字コードの説明」を参照して下さい。
    float   fval = 0.123f;
    char    str[80];
    WCHAR   wstr[80];
    sprintf(str,"%8.2f\n",fval);
    MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,str,-1,wstr,80);
    MessageBox(NULL,wstr,L"Debug Message Box",MB_OK);
    
  5. scope 演算子(::)
    説明は「超初心者の C++/CLI(CLR) 入門/scope 演算子」を参照して下さい。
    HRESULT CTiny::Setup( double dTimeCurrent )
    {
        ・・・
    }
    
  6. std, using
    説明は「超初心者の C++/CLI(CLR) 入門/STL(Standard Template Library)」を参照して下さい。
    using namespace std;
    std::vector<CTiny*> *m_pv_pChars;
    
  7. try, catch
    try ブロックでは、例外が発生する恐れがある処理を記述します。
    catch ブロックでは、例外が発生したときの対処方法を記述します。
    try
    {
        // 例外が発生する処理
    }
    catch (例外型 変数)
    {
        // 例外が発生した後の処理
    }
    
    DirectX で実際に使用されているソースコードです。
    try
    {
        m_v_pAnimInstances.push_back( pAI );
    }
    catch( ... )
    {
        hr = E_OUTOFMEMORY;
        goto e_Exit;
    }
    
  8. assert() 関数
    引数が偽(FALSE)だとメッセージボックスを表示します。
    デバッグモード以外で実行すると取り除かれます。
    void CAnimInstance::UpdateFrames( MultiAnimFrame * pFrame, D3DXMATRIX * pmxBase )
    {
        assert( pFrame != NULL );
    
  9. V, V_RETURN
    関数のリターン値が FLASE のときエラーを記録します。
    V_RETURN では、エラー記録をして return を実行します。
    V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 45, 50, 170), 1.0f, 0) );
    V_RETURN( g_DialogResourceManager.OnD3D9CreateDevice( pd3dDevice ) );
    
    #define で次のように宣言されています。
    #define V(x)        { hr = (x); if( FAILED(hr) ) { DXUTTrace( __FILE__, (DWORD)__LINE__, hr, L#x, true ); } }
    #define V_RETURN(x) { hr = (x); if( FAILED(hr) ) { return DXUTTrace( __FILE__, (DWORD)__LINE__, hr, L#x, true ); } }
    
  10. DXUTTrace()
    DXUTTrace() は DXUTmisc.cpp で次のように定義されています。
    HRESULT WINAPI DXUTTrace( const CHAR* strFile, DWORD dwLine, HRESULT hr,
                              const WCHAR* strMsg, bool bPopMsgBox )
    {
        bool bShowMsgBoxOnError = DXUTGetShowMsgBoxOnError();
        if( bPopMsgBox && bShowMsgBoxOnError == false )
            bPopMsgBox = false;
        return DXTrace( strFile, dwLine, hr, strMsg, bPopMsgBox );
    }
    
  11. DXTrace()
    DXTrace() はライブラリで提供されている関数らしく、DxErr.h で次のように説明されています。
    //  DXTrace
    //  Desc:  Outputs a formatted error message to the debug stream
    //  Args:  CHAR* strFile   The current file, typically passed in using the 
    //                         __FILE__ macro.
    //         DWORD dwLine    The current line number, typically passed in using the 
    //                         __LINE__ macro.
    //         HRESULT hr      An HRESULT that will be traced to the debug stream.
    //         CHAR* strMsg    A string that will be traced to the debug stream (may be NULL)
    //         BOOL bPopMsgBox If TRUE, then a message box will popup also containing the passed info.
    //  Return: The hr that was passed in.  
    
  12. #ifdef
    #ifdef は条件コンパイルです。
    次の例では、デバッグモード(DEBUG_VS を宣言)の時に、#ifdef と #endif の間の文が翻訳されます。
    #ifdef DEBUG_VS
        if( pDeviceSettings->d3d9.DeviceType != D3DDEVTYPE_REF )
        {
            pDeviceSettings->d3d9.BehaviorFlags &= ~D3DCREATE_HARDWARE_VERTEXPROCESSING;
            pDeviceSettings->d3d9.BehaviorFlags &= ~D3DCREATE_PUREDEVICE;
            pDeviceSettings->d3d9.BehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
        }
    #endif
    
  13. DDS 画像形式
    説明は「directx9/DDS 形式の画像ファイルを作成する」を参照して下さい。
  14. D3DCOLOR
    #define で次のように宣言されています。
    #define D3DCOLOR_XRGB(r,g,b) D3DCOLOR_ARGB(0xff,r,g,b)
    #define D3DCOLOR_ARGB(a,r,g,b) \
        ((D3DCOLOR)((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff)))
    
    最近では Color 表現にも浮動小数点が使われるようになってきました。
    float ClearColor[4] = { 0.1f, 0.3f, 0.8f, 0.0f };
    pd3dDevice->ClearRenderTargetView( pWindowObj->pRenderTargetView, ClearColor );
    
  15. VECTOR3
    D3DXVECTOR3 は構造体です。
    三次元 Vector と Matrix の使い方の例題です。
    D3DXMATRIX matView;
    D3DXVECTOR3 vFromPt   = D3DXVECTOR3( 0.0f, 0.0f, -5.0f );
    D3DXVECTOR3 vLookatPt = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
    D3DXVECTOR3 vUpVec    = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
    D3DXMatrixLookAtLH( &matView, &vFromPt, &vLookatPt, &vUpVec );
    m_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
    
    以前は次のような書き方が許されていましたが、新しいバージョンでは警告が出ます。
    D3DXMatrixLookAtLH(&matView,&D3DXVECTOR3(0.0f, -5.0f, 30.0f),
                       &D3DXVECTOR3(0.0f, 0.0f, 0.0f),
                       &D3DXVECTOR3(0.0f, 1.0f, 0.0f));
    
  16. D3DXMATRIX は4*4の変換行列です。
    単位行列を設定するコードは次のとおりです。
    D3DXMATRIX matWorld;
    D3DXMatrixIdentity(&matWorld);
    

DirectX とは

DirectX のプログラミングを習う前に DirectX とは何かを説明しましょう。

    DirectX の起源

  1. CP/M[スィーピーエム] (CP/M: Control Program for Microcomputers)
    8 ビット機で主流だった OS の名前です。
    i8080 で動作し、その後その拡張後継チップ i8085 や互換品 Z80 などに適応するよう改良され 8 ビット OS の王者となりました。
    そして i8086 用の CP/M-86, MC68000 用の CP/M-68K などが順次開発されていきました。
    CP/M を模倣して作られた MS-DOS などにも、その基本思想が色濃く残っています。
    BIOS が CP/M-80 上位互換で、ディスクフォーマットが MS-DOS 互換である Z80 専用 OS "MSX-DOS" という MSX 専用の OS も存在します。
    ディジタルリサーチはその後 Novell 社に吸収され、さらに Caldera 社に引き継がれたため、現在は Caldela CP/M と呼ばれ Web ページからダウンロードすることもできます。
  2. MS-DOS[エムエスドス] (MS-DOS: MicroSoft Disk Operating System)
    過去, パソコンで最大の勢力を誇った OS の名前です。
    パソコン用に開発された 16 ビット MPU である i8086 用のオペレーティングシステムで、フロッピーディスクベースでも実用になるコンパクトな OS です。
    MS-DOS 誕生のエピソードは伝説となっています。
    IBM が IBM PC を開発中、OS までは手が回らないためビルゲイツに BASIC インタプリタのライセンスを依頼してきました。
    しかし BASIC は OS では無かったため、ビルゲイツはディジタルリサーチの CP/M を勧めました。
    しかしディジタルリサーチの社長の Gary Kildall がゴルフに行き IBM との契約をすっぽかした為、怒った IBM が急遽 Microsoft に OS 制作を依頼しました。
    頼まれた Microsoft も急だったため、仕方がなく Microsoft の近所の Seattle Computer Products 社で開発していた CP/M 互換 (パクり) の 86-DOS (QDOS: Quick and Dirty Operation System とも呼ばれる) を 5 万ドルで買収し、86-DOS 開発者である Tim Paterson 自身も加わって MS-DOS ver1.xx を完成させたと言われています。
    この買収劇は 20 世紀最大の買収、あるいは 20 世紀最大の窃盗などと呼ばれています。 (^_^;)
    ちなみにその後のディジタルリサーチは下落の一途をたどり、最後は Novell 社に吸収され生涯の幕を閉じることになります。 (;_;)
    反対にビルゲイツ(Microsoft) の方は、IBM をも凌ぐ大企業に成長しました。 \(^o^)/
    当時、パソコンのソフトがこれほど重要な役割を担うとは IBM も思っていなかったのでしょう。
    特徴はコマンドライン・インターフェイスを採用したシングルタスク OS である点、これが OS そのものの軽量化に貢献しています。
    またパソコン用の OS ということもあり、シングルユーザ OS である点も特徴的です。
    CP/M 互換という点もあり 8 ビット OS 的概念をそのまま受け継いでいます。
  3. DirectX の歴史は WinG に始まります。
    WinG [ウィンジー] とは Microsoft Windows 用 GAME API のことです。
    初期の Windows のOSはオーバーヘッドが大きく、とてもゲームプログラムには耐えられませんでした。
    所がゲーム好きのあるグループが仕事の合間に Windows で MS-DOS と同じようにゲームを楽しんでいたのです。
    原理はいたってシンプルで Windows を通さずに直接デバイスを操作する方法でした。
    これに目をつけた Microsoft が WinG として採用しました。
    Windows 95 で採用するはずの技術でしたが, 予定を早め Windows 3.1 用としてリリースされました。
    しかも, Windows 95 では DirectX という新技術が登場したため, あまり日の目を見ることはありませんでした。
    DirectX は WinG の直接デバイスを操作すると言う考えを取り入れ、ハードウエアと共に進歩して行きます。
  4. DirectX に対抗する技術としてOpenGL[オープンジーエル]があります。
    米 SGI の開発した三次元グラフィックスライブラリの基本仕様の名称で、同社が自社ワークステーション用に開発した IRIS-GL を 汎用的な形にして公表したものです。
    三次元グラフィックをプラットフォームに依存することなく使用する事を目的としています。
    Windows では、Windows NT 3.5 以降と Windows 95 OSR2 以降でサポートされています。
    DirectX は不安定で、いつになっても不具合が無くならない点や、ドキュメントが不備で必要な情報が得られないなどの点でプログラマに嫌われており、 Windows プログラマの多くは OpenGL の普及を願っていました。
    だが、Windows 95 では OpenGL を高速化するためのドライバを提供することが困難であるため一向に普及する気配が無く、やむなく DirectX を利用せざるを得ない状況が続きました。
    Microsoft は DirectX を Windows CE に搭載し、ゲーム機用 OS として OEM リリースもしており (SEGA の DreamCast OS など)、Windows CE を含めた全 Windows シリーズでの共通ゲーム API の実現を目指しているため OpenGL は邪魔な存在でした。
    当然露骨な妨害活動も多々見られました。
    そこで SGI との提携により両者の技術を統合した Fahrenheit という新 API の開発が計画されたが、完成することはありませんでした。
    ただし実際にはまだ対抗馬と呼べるものが存在していて、例えば KINETIX (Autodesk 社の部門) の 3D ソフト "3D Studio MAX" の グラフィックスインターフェイスである HEIDI (ハイヂ) などがあります。
  5. DirectX の悪口を並べましたが、DirectX の素晴らしい所は「最新のハードウエアの能力を引き出せる」ことにあります。
    DirectX はハードと共に進化してきました。
    DirectX の新バージョンが発表されると、それに対応した新しいハードが開発されるようになりました。
    つまり DirectX を使うと「最新のハードウエアの機能を簡単に利用できる」ことになります。
    逆に DirectX の難点 (?_?; は、新しいバージョンが発表される度にハードが古くなることです。 (;_;)
    DirectX のバージョンアップとハードの開発競争は何時まで続くのでしょうか。

    DirectX(3D) の実行環境

  6. DirectX を使うと Windows のシステムに邪魔されることなく、グラフィックボードや入力機器に直接アクセスすることが可能になり、 描画速度や迅速な応答を要求されるゲームプログラムなどを作成することができるようになります。
    DirectX のプログラムを作成するためには、DirectX のSDK(ソフトウェア開発キット)と C++ のコンパイラが必要です。
    DirectX SDK はマイクロソフトが無料で配布しているので、雑誌の付録やネットから無料でダウンロードしたり、送料のみで CD-ROM を手に入れることができますが C++ コンパイラは購入しなければなりません。(^_^;)
  7. DirectAudio のハードウエア(サウンドカード)は、提供している会社も少なく比較的互換性も保たれています。
    ところが Direct3D の実行環境は DirectAudio と違って多種多様です。
    一番の問題はビデオカードまたは、アクセラレータボードなどと呼ばれているグラフィックスを描画するハードウエアで、 規格が統一されていない上に多くのメーカが機能を競って独自に開発を続けてきました。
    DirectX の目的の一つはハードに依存しない統一したプログラム環境を提供することなのですが、もう一方でハードウエアの機能を 最大限に生かしてゲームのような非常に速い描画速度を要求するプログラムにも対応することなのです。
    ビデオカード以外にもモニタの規格や描画専用のバスなどハードウエアの多くの違いを克服しなければなりません。
  8. DirectX は、新しいビデオカードやハードウエアの発達と共に、約半年ごとにバージョンアップが繰り返されて来ました。
    2007 年にはバージョンアップを重ねて DirectX 10 August 2007 がリリースされました。 \(^o^)/
    DirectX を使っていて最も苦労するところが、普通はバージョンアップされても上位互換が保たれ、 古いソースコードもしばらくは使えるのですが、DirectX では平気で切り捨てられ、全く通じなくなることです。
  9. DirectX10 は DirectX9 に比べて大幅に改良?? (^_^;) されています。
    3Dグラフックスボードはプログラムシェーダー4.0 に対応したものが必要になり、今までのボードが使えないのが痛手です。 (;_;)
    ソフトでは Shader Program が必須になり、頂点シェーダー、ピクセルシェーダー、ジオメトリシェーダーが使えるようになりました。
    つまり簡単なアニメーションなどはグラフィックボードに任せてしまおうと言うのです。
    当然ながらCPUで処理するのとGPUで処理するのとでは、その違いは明らかです。
    Shader が必須になったことに伴い、ライトやマテリアルの設定は Shader でプログラムすることになり、組み方も従来とは大きく変わっています。
    また DirectX10 のメッシュファイルは拡張子が .x から .sdkmesh になり、X-FILE(拡張子が .X のファイル) がサポートされなくなりました。
    X-FILE は TEXT 形式で、エディタなどを使うと内容を確認できたのですが、sdkmesh は Binary 形式でフォーマットが解らないと判読不能です。
  10. GPU(Graphics Processig Unit) はグラフィック描画に特化したコンピュータと言うことが出来ます。
    Caps(Capability Bits Tests) とは、その GPU がどんな機能を持っているかを調べる仕組みですが、種類やバージョンの違いが多くなりすぎたこともあり、 Direct3D10 ではこれが廃止されます。
    Caps の仕組みが廃止されることにより、DirectX10 世代の GPU では Direct3D10 の機能仕様に含まれる全機能に対応していなければ「DirectX10 対応 GPU」を名乗れず、 製品間の"格差"は「機能差ではなく性能差で勝負する」ことになります。
    アプリケーション開発者は、メーカー間の互換性や製品クラス間の互換性を気にすることなく、積極的に GPU を活用したソフトウェアを制作しやすくなると言うのが Microsoft の言い分です。 (^_^;)
  11. GPGPU(Genral Purpose GPU)
    近年の GPU は驚異的な進歩を遂げています。
    特にベクトル演算の計算速度は CPU も顔負けで、一昔前のスーパーコンピュータに匹敵する Tera FLOPS に迫っています。
    この機能を利用しない手は無いと GPU を汎用の演算用途に用いようというアイデアが提唱されました。
    演算シェーダは Direct3D 11 に統合される形で実装され、Direct3D 11で取り扱えるリソース類はすべて透過的に演算シェーダでも取り扱えるようになっています。
    機能的な側面でいうと Direct3D 11 に、GPGPU 関連の API の追加とシェーダ言語の HLSL が拡張される……というイメージになります。
    演算シェーダの活用は、一つのプログラムで大量のデータを処理するような SIMD ならぬ SPMD(Single Program Multiple Data)モデルの処理の実装に向いているとされます。
    例えば、群集シミュレーションの AI,大局的な物理シミュレーション処理,映像のエンコード処理,3Dグラフィックスのポストプロセスなどには向いているといえます。
    GPGPU は DirectX に留まらず、新しい OS の開発にも大きな影響を及ぼしそうです。
  12. Microsoft は 2012/10/末 に新しいOSである Windows8 の発売を開始しました。 \(^o^)/
    Windows8 は Windows7 までと、仕様が大きく変わっています。
    DirectX も Windows8 仕様になり、Microsoft Visual Studio Express 2012 for Windows 8 の中に含まれています。
    Windows8 のプログラム開発は Windows & Visual Studio を参照して下さい。

    X Windows

  13. 良い機会なので Windows や DirectX に良く似た紛らわしい言葉を整理しておきましょう。
  14. X Window[エックスウィンドウ] (X Window)
    "X Window System" に対する UNIX 初心者を中心に使われる誤った呼び方の一つです。
  15. X-Windows[エックスウィンドーズ] (X-Windows)
    "X" に対する UNIX 初心者を中心に使われる誤った呼び方のひとつで、恐らく Microsoft Windows の語呂からこの名に至ったものと思われるが、 正式名称は "X Window System" であり、X Consotium においては、"X"、"X Window System"、"X version 11" (11 はバージョン番号) 等の使用を求められています。
    つまり、X-Windows はありそうで存在しません。Window は単数形で、かつハイフンは付きません。
    改めて私のホームページを見てみると、所々に「X-Window」の記述が見つかりました。
    誤った名称を広げるのに一役かっていたのでしょうか。 (^_^;)
  16. X Window System[エックスウィンドウシステム] (X Window System)
    米マサチューセッツ工科大学により開発されたウィンドウシステムです。
    基本的に GUI を提供するだけの機能しか持たず、OS やシェルとしての機能はありません。
    OS としての機能がないので、Microsoft Windows 3.x のように、他の OS 上から起動される形で使用します。
    またシェルを利用するためには xterm や kterm などの端末ソフトウェアを使用し、その上でシェルを利用するのが一般的です。
    但し、単なる GUI というわけでも無いのが X Window System の特徴で、X プロトコルと呼ばれるプロトコルを用いてプログラム間で通信を行い、 クライアント/サーバー型のシステムとして機能します。
    例えば画面描画の機能などが "サーバー" であり、クライアントはサーバーに対して描画の要求を行なったり、サーバーからの命令により処理を行います。
    更に、クライアントはネットワークに接続されてさえいれば全く別の場所にあってもよく、これが Windows などの他の GUI システムと大きく趣を異にする点です。
    "X" の語源は、かつて Window の頭文字を取り "W" というウィンドウシステムが存在し、その改良版という意味をこめて次の文字である "X" とした といわれています。
    X window System は PS2 の Linux 版にも使われています。
  17. この項の執筆にあたっては DDwin の通信用辞書を参照しました。

実行環境の設定

Windows Store(Windows8 以降)からは Visual Studio をインストールするだけでOKで、ここから先は参照する必要はありません。
DirectX のインストールが終わると Visual Studio に DirectX のパスを設定します。
Visual Studio 6.0 でも Visual Studio .NET でも同じ要領です。
構成によっては自動的にパスが設定される場合もあるので、パスの設定を確認して下さい。

    パスの設定

  1. Visual Studio を起動して[ツール]メニューの[オプション]をクリックして[プロジェクト/VC++ ディレクトリ]を選択します。
    [ディレクトリを表示するプロジェクト]にインクルードファイル]を選択します。
    次の行(空白の行)をクリックして include ファイルのパスをタイプします。
    新しくタイプした行を、↑アイコンで先頭に移動します。
    C:\DXSDK\include を設定した例です。
    画像は Visual Studio のバージョンによって多少異なります。
    説明の画像

  2. 次に[ディレクトリを表示するプロジェクト]に[ライブラリファイル]を選択して同じようにパスを設定します。
    新しくタイプした行を、↑アイコンで先頭に移動します。
    C:\DXSDK\Lib を設定した例です。
    説明の画像

  3. ファイルのパスは、バージョン(インストールされるフォルダー)によって変わります。
    幾つかの例を挙げますので、例に習って設定して下さい。
    以前はマイコンピュータ(Windows Explorer)で DirectX が格納されているパスを調べていたのですが、最近のバージョンではパスをタイプするとサブフォルダーの一覧が表示されます。
    例えば「C:\」とタイプすると C:\ 以下のサブフォルダーが、「C:\Program Files\Microsoft DirectX SDK (August 2007)\」と タイプするとサブフォルダーの一覧が表示されるようになっています。
  4. Visual C++ 2010 Express では、パスの設定メニューが変わったようです。
    メニューバーから [プロジェクト/プロパティ/構成プロパティ/すべての構成/VC++ディレクトリ]から設定します。
    Sample Brower で作成した SimpleSample のときの設定です。

    ライブラリの組み込み

  5. アプリケーションごとに必要なライブラリを取り込んで下さい。
    メニューバーから [プロジェクト] [プロパティ] [リンカ] [入力] から設定します。
    Sample Brower で作成した SimpleSample のときのに取り込まれているライブラリです。

    ライブラリは、#pragma を使って取り込むこともできます。
    #pragma once
    #pragma comment(lib,"dxerr.lib")
    #pragma comment(lib,"dxguid.lib")
    #pragma comment(lib,"d3dx9d.lib")
    #pragma comment(lib,"d3dx10d.lib")
    #pragma comment(lib,"d3d9.lib")
    #pragma comment(lib,"winmm.lib")
    #pragma comment(lib,"comctl32.lib")
    
  6. コマンドラインからコンパイルする場合には、DirectX の DLL が格納されているパスを LIBPATH で設定する必要があります。
    C/C++/CLI の DX.BAT の説明は「超初心者のプログラム入門(C/C++/CLI)」から Command Line から DirectX を動かす を参照して下さい。
    直接リンク出来ないときは「前田稔(Maeda Minoru)の超初心者のプログラム入門」から辿って下さい。
  7. Visual Studio のプロジェクトを使ったときに、次のエラーが発生しています。
    エラー 1 fatal error C1107: アセンブリ 'Microsoft.DirectX.dll' がみつかりませんでした: 
    /AI または LIBPATH 環境変数を使用してアセンブリ検索パスを指定してください。
    
    プロジェクト・プロパティから[#using参照の解決]で設定します。
    また実行時に LoaderLock で停止することがあります。
    LoaderLock を解除して実行します。
    LoaderLock の解除は Command Line から DirectX を動かす を参照して下さい。
  8. C# でもコマンドプロンプトから DirectX をコンパイルすることが出来ます。
    詳細は C# の Command Line から DirectX を実行 を参照して下さい。