最近のマルチモニタ事情――Direct3DやらOpenGLやら

頼まれ仕事をしていて、ちょっとしたノウハウ(とも言えないレベルですが)を得たので、一応書き記しておこうと思います。


随分昔にも、趣味でプログラムを書いていて、マルチモニタで3D画面が出せると面白いかな、と考えたことがあるのですが、当時のWindows98、MatroxG400DH(民生用初のデュアルモニタ対応カード)、DirectX7の環境下、素人プログラミングスキルでは、到底無理であった事を実感しました(^^;; Win98では、仕様上プライマリモニタ以外でD3DのHALが使えないという制約があったため、おそらく苦労しても相応の効果は得られなかったと思います。


で、現在ですが、Windows2000/XPではデュアルのデスクトップと、1つのワイドなデスクトップと言う感じで、二通りのマルチモニタの方法があります。前者でマルチモニタを有効にするには(DirectX9の場合)、おおまかに

  1. PC画面をデュアルのデスクトップへ設定する。
  2. プログラム上で、D3DインターフェースからGetAdapterCountでアダプタ数を調べ、GetAdapterIdentifierでアダプタIDを取得する
  3. 取得したアダプタIDからD3DDeviceを生成
  4. それぞれのD3DDeviceで描画。もちろん、それぞれにビューポートや座標変換行列、レンダーステートの設定が必要。


という感じになります。よく分からなかったX7時代に比べると、随分すっきりしているのですが、細かい所でハードルが存在し、プログラムの改変も大きくなります。


これに対して、ワイドなディスプレイとして画面を扱った場合、使い勝手が大幅に変わります。DirectXで、単一のデバイスとして幅広(もしくは上下に広い)の画面解像度が、フルスクリーンでも選択可能になるため、単純にこれを選ぶと、結果的にマルチモニタになってくれます(^^
幅広のビューポートを用いて、ワイドな視野角を持たせるも良し、ビューポートで区切って複数の視点を持たせるのもありです。また、X8以降ではテクスチャへのレンダリングも大幅に手順が簡略化されているため、テクスチャに対して描画し、最終的に2次元ポリゴンで自由に貼り付けるという手も使えます。X7の時に随分苦労したことを思い出すと、随分楽になったものです(^^;;


ちなみに、後者の方法はOpenGLでも基本的には変わらないため、同様に使えるはずです。ただ、テクスチャへのレンダリングは、まずバックバッファに対して描画した結果を、glCopyTexImage2D()関数を用いてポインタ経由でプログラム上で用意しているテクスチャへ転送し、glTexImage()関数でビデオカードへ転送する、という二度手間となります(OpenGL1.1準拠時)
高速化したい場合、Cg等のシェーダや、ビデオカードベンダーの各社が用意している拡張命令群を使用する必要があります。この辺、日本語のドキュメントがいまいち少ないのが難点ですね(^^;;