QtでDirect3Dを使用する

かつて、Direct3DをQtと組み合わせて使用​​する必要がありました。 インターネットを数日間検索した後、ほんの少しの情報しか見つけませんでした。 どこでもDirect3Dを使用するメカニズムの完全な説明はありませんでした。 その結果、多くの研究を重ねた後、私は望んでいたことを達成しました:)

猫の下には、Direct3DとQtの「rapprochement」命令、およびそのまま使用できるウィジェットコードがあります。



この記事を書くとき、次のツールが使用されました。

  1. Qt 4.5.0
  2. VS2008 SP1
  3. DirectX SDK 2008年8月


別のものを使用している場合。 IDEの場合、ビルド時間はわずかに異なります。 VS2008のみのアセンブリ例を示します。 ビルドがdirect3dエンジンをサポートしていることが確実な場合は、Qtの構成とビルドのステップをスキップしてください。



Qtの構成と構築





ウィジェットコード



Direct3DWidget.h

  1. #ifndef DIRECT3DWIDGET_H #define DIRECT3DWIDGET_H #include <QtGui/QWidget> #include <d3d9.h> #include <atlbase.h> class Direct3DWidget : public QWidget { Q_OBJECT CComPtr < IDirect3D9 > m_pD3D ; CComPtr < IDirect3DDevice9 > m_pd3dDevice ; public : Direct3DWidget ( QWidget * parent = 0 ) ; ~Direct3DWidget ( ) ; bool InitDirect3D ( ) ; public slots : bool Rendering ( ) ; private : void paintEvent ( QPaintEvent * pEvent ) ; } ; #endif



  2. #ifndef DIRECT3DWIDGET_H #define DIRECT3DWIDGET_H #include <QtGui/QWidget> #include <d3d9.h> #include <atlbase.h> class Direct3DWidget : public QWidget { Q_OBJECT CComPtr < IDirect3D9 > m_pD3D ; CComPtr < IDirect3DDevice9 > m_pd3dDevice ; public : Direct3DWidget ( QWidget * parent = 0 ) ; ~Direct3DWidget ( ) ; bool InitDirect3D ( ) ; public slots : bool Rendering ( ) ; private : void paintEvent ( QPaintEvent * pEvent ) ; } ; #endif



  3. #ifndef DIRECT3DWIDGET_H #define DIRECT3DWIDGET_H #include <QtGui/QWidget> #include <d3d9.h> #include <atlbase.h> class Direct3DWidget : public QWidget { Q_OBJECT CComPtr < IDirect3D9 > m_pD3D ; CComPtr < IDirect3DDevice9 > m_pd3dDevice ; public : Direct3DWidget ( QWidget * parent = 0 ) ; ~Direct3DWidget ( ) ; bool InitDirect3D ( ) ; public slots : bool Rendering ( ) ; private : void paintEvent ( QPaintEvent * pEvent ) ; } ; #endif



  4. #ifndef DIRECT3DWIDGET_H #define DIRECT3DWIDGET_H #include <QtGui/QWidget> #include <d3d9.h> #include <atlbase.h> class Direct3DWidget : public QWidget { Q_OBJECT CComPtr < IDirect3D9 > m_pD3D ; CComPtr < IDirect3DDevice9 > m_pd3dDevice ; public : Direct3DWidget ( QWidget * parent = 0 ) ; ~Direct3DWidget ( ) ; bool InitDirect3D ( ) ; public slots : bool Rendering ( ) ; private : void paintEvent ( QPaintEvent * pEvent ) ; } ; #endif



  5. #ifndef DIRECT3DWIDGET_H #define DIRECT3DWIDGET_H #include <QtGui/QWidget> #include <d3d9.h> #include <atlbase.h> class Direct3DWidget : public QWidget { Q_OBJECT CComPtr < IDirect3D9 > m_pD3D ; CComPtr < IDirect3DDevice9 > m_pd3dDevice ; public : Direct3DWidget ( QWidget * parent = 0 ) ; ~Direct3DWidget ( ) ; bool InitDirect3D ( ) ; public slots : bool Rendering ( ) ; private : void paintEvent ( QPaintEvent * pEvent ) ; } ; #endif



  6. #ifndef DIRECT3DWIDGET_H #define DIRECT3DWIDGET_H #include <QtGui/QWidget> #include <d3d9.h> #include <atlbase.h> class Direct3DWidget : public QWidget { Q_OBJECT CComPtr < IDirect3D9 > m_pD3D ; CComPtr < IDirect3DDevice9 > m_pd3dDevice ; public : Direct3DWidget ( QWidget * parent = 0 ) ; ~Direct3DWidget ( ) ; bool InitDirect3D ( ) ; public slots : bool Rendering ( ) ; private : void paintEvent ( QPaintEvent * pEvent ) ; } ; #endif



  7. #ifndef DIRECT3DWIDGET_H #define DIRECT3DWIDGET_H #include <QtGui/QWidget> #include <d3d9.h> #include <atlbase.h> class Direct3DWidget : public QWidget { Q_OBJECT CComPtr < IDirect3D9 > m_pD3D ; CComPtr < IDirect3DDevice9 > m_pd3dDevice ; public : Direct3DWidget ( QWidget * parent = 0 ) ; ~Direct3DWidget ( ) ; bool InitDirect3D ( ) ; public slots : bool Rendering ( ) ; private : void paintEvent ( QPaintEvent * pEvent ) ; } ; #endif



  8. #ifndef DIRECT3DWIDGET_H #define DIRECT3DWIDGET_H #include <QtGui/QWidget> #include <d3d9.h> #include <atlbase.h> class Direct3DWidget : public QWidget { Q_OBJECT CComPtr < IDirect3D9 > m_pD3D ; CComPtr < IDirect3DDevice9 > m_pd3dDevice ; public : Direct3DWidget ( QWidget * parent = 0 ) ; ~Direct3DWidget ( ) ; bool InitDirect3D ( ) ; public slots : bool Rendering ( ) ; private : void paintEvent ( QPaintEvent * pEvent ) ; } ; #endif



  9. #ifndef DIRECT3DWIDGET_H #define DIRECT3DWIDGET_H #include <QtGui/QWidget> #include <d3d9.h> #include <atlbase.h> class Direct3DWidget : public QWidget { Q_OBJECT CComPtr < IDirect3D9 > m_pD3D ; CComPtr < IDirect3DDevice9 > m_pd3dDevice ; public : Direct3DWidget ( QWidget * parent = 0 ) ; ~Direct3DWidget ( ) ; bool InitDirect3D ( ) ; public slots : bool Rendering ( ) ; private : void paintEvent ( QPaintEvent * pEvent ) ; } ; #endif



  10. #ifndef DIRECT3DWIDGET_H #define DIRECT3DWIDGET_H #include <QtGui/QWidget> #include <d3d9.h> #include <atlbase.h> class Direct3DWidget : public QWidget { Q_OBJECT CComPtr < IDirect3D9 > m_pD3D ; CComPtr < IDirect3DDevice9 > m_pd3dDevice ; public : Direct3DWidget ( QWidget * parent = 0 ) ; ~Direct3DWidget ( ) ; bool InitDirect3D ( ) ; public slots : bool Rendering ( ) ; private : void paintEvent ( QPaintEvent * pEvent ) ; } ; #endif



  11. #ifndef DIRECT3DWIDGET_H #define DIRECT3DWIDGET_H #include <QtGui/QWidget> #include <d3d9.h> #include <atlbase.h> class Direct3DWidget : public QWidget { Q_OBJECT CComPtr < IDirect3D9 > m_pD3D ; CComPtr < IDirect3DDevice9 > m_pd3dDevice ; public : Direct3DWidget ( QWidget * parent = 0 ) ; ~Direct3DWidget ( ) ; bool InitDirect3D ( ) ; public slots : bool Rendering ( ) ; private : void paintEvent ( QPaintEvent * pEvent ) ; } ; #endif



  12. #ifndef DIRECT3DWIDGET_H #define DIRECT3DWIDGET_H #include <QtGui/QWidget> #include <d3d9.h> #include <atlbase.h> class Direct3DWidget : public QWidget { Q_OBJECT CComPtr < IDirect3D9 > m_pD3D ; CComPtr < IDirect3DDevice9 > m_pd3dDevice ; public : Direct3DWidget ( QWidget * parent = 0 ) ; ~Direct3DWidget ( ) ; bool InitDirect3D ( ) ; public slots : bool Rendering ( ) ; private : void paintEvent ( QPaintEvent * pEvent ) ; } ; #endif



  13. #ifndef DIRECT3DWIDGET_H #define DIRECT3DWIDGET_H #include <QtGui/QWidget> #include <d3d9.h> #include <atlbase.h> class Direct3DWidget : public QWidget { Q_OBJECT CComPtr < IDirect3D9 > m_pD3D ; CComPtr < IDirect3DDevice9 > m_pd3dDevice ; public : Direct3DWidget ( QWidget * parent = 0 ) ; ~Direct3DWidget ( ) ; bool InitDirect3D ( ) ; public slots : bool Rendering ( ) ; private : void paintEvent ( QPaintEvent * pEvent ) ; } ; #endif



  14. #ifndef DIRECT3DWIDGET_H #define DIRECT3DWIDGET_H #include <QtGui/QWidget> #include <d3d9.h> #include <atlbase.h> class Direct3DWidget : public QWidget { Q_OBJECT CComPtr < IDirect3D9 > m_pD3D ; CComPtr < IDirect3DDevice9 > m_pd3dDevice ; public : Direct3DWidget ( QWidget * parent = 0 ) ; ~Direct3DWidget ( ) ; bool InitDirect3D ( ) ; public slots : bool Rendering ( ) ; private : void paintEvent ( QPaintEvent * pEvent ) ; } ; #endif



  15. #ifndef DIRECT3DWIDGET_H #define DIRECT3DWIDGET_H #include <QtGui/QWidget> #include <d3d9.h> #include <atlbase.h> class Direct3DWidget : public QWidget { Q_OBJECT CComPtr < IDirect3D9 > m_pD3D ; CComPtr < IDirect3DDevice9 > m_pd3dDevice ; public : Direct3DWidget ( QWidget * parent = 0 ) ; ~Direct3DWidget ( ) ; bool InitDirect3D ( ) ; public slots : bool Rendering ( ) ; private : void paintEvent ( QPaintEvent * pEvent ) ; } ; #endif



  16. #ifndef DIRECT3DWIDGET_H #define DIRECT3DWIDGET_H #include <QtGui/QWidget> #include <d3d9.h> #include <atlbase.h> class Direct3DWidget : public QWidget { Q_OBJECT CComPtr < IDirect3D9 > m_pD3D ; CComPtr < IDirect3DDevice9 > m_pd3dDevice ; public : Direct3DWidget ( QWidget * parent = 0 ) ; ~Direct3DWidget ( ) ; bool InitDirect3D ( ) ; public slots : bool Rendering ( ) ; private : void paintEvent ( QPaintEvent * pEvent ) ; } ; #endif



  17. #ifndef DIRECT3DWIDGET_H #define DIRECT3DWIDGET_H #include <QtGui/QWidget> #include <d3d9.h> #include <atlbase.h> class Direct3DWidget : public QWidget { Q_OBJECT CComPtr < IDirect3D9 > m_pD3D ; CComPtr < IDirect3DDevice9 > m_pd3dDevice ; public : Direct3DWidget ( QWidget * parent = 0 ) ; ~Direct3DWidget ( ) ; bool InitDirect3D ( ) ; public slots : bool Rendering ( ) ; private : void paintEvent ( QPaintEvent * pEvent ) ; } ; #endif



  18. #ifndef DIRECT3DWIDGET_H #define DIRECT3DWIDGET_H #include <QtGui/QWidget> #include <d3d9.h> #include <atlbase.h> class Direct3DWidget : public QWidget { Q_OBJECT CComPtr < IDirect3D9 > m_pD3D ; CComPtr < IDirect3DDevice9 > m_pd3dDevice ; public : Direct3DWidget ( QWidget * parent = 0 ) ; ~Direct3DWidget ( ) ; bool InitDirect3D ( ) ; public slots : bool Rendering ( ) ; private : void paintEvent ( QPaintEvent * pEvent ) ; } ; #endif



  19. #ifndef DIRECT3DWIDGET_H #define DIRECT3DWIDGET_H #include <QtGui/QWidget> #include <d3d9.h> #include <atlbase.h> class Direct3DWidget : public QWidget { Q_OBJECT CComPtr < IDirect3D9 > m_pD3D ; CComPtr < IDirect3DDevice9 > m_pd3dDevice ; public : Direct3DWidget ( QWidget * parent = 0 ) ; ~Direct3DWidget ( ) ; bool InitDirect3D ( ) ; public slots : bool Rendering ( ) ; private : void paintEvent ( QPaintEvent * pEvent ) ; } ; #endif



  20. #ifndef DIRECT3DWIDGET_H #define DIRECT3DWIDGET_H #include <QtGui/QWidget> #include <d3d9.h> #include <atlbase.h> class Direct3DWidget : public QWidget { Q_OBJECT CComPtr < IDirect3D9 > m_pD3D ; CComPtr < IDirect3DDevice9 > m_pd3dDevice ; public : Direct3DWidget ( QWidget * parent = 0 ) ; ~Direct3DWidget ( ) ; bool InitDirect3D ( ) ; public slots : bool Rendering ( ) ; private : void paintEvent ( QPaintEvent * pEvent ) ; } ; #endif











Direct3DWidget.cpp

  1. #include "Direct3DWidget.h"
  2. Direct3DWidget :: Direct3DWidget QWidget * parent / * = 0 * / QWidget parent
  3. {
  4. setAttribute Qt :: WA_PaintOnScreen ;
  5. }
  6. Direct3DWidget :: 〜Direct3DWidget
  7. {
  8. }
  9. bool Direct3DWidget :: InitDirect3D
  10. {
  11. m_pD3D = Direct3DCreate9 D3D_SDK_VERSION ;
  12. if m_pD3D
  13. falseを返します
  14. D3DPRESENT_PARAMETERS d3dpp = { 0 } ;
  15. d3dpp。 ウィンドウ化 = TRUE ;
  16. d3dpp。 SwapEffect = D3DSWAPEFFECT_DISCARD ;
  17. d3dpp。 BackBufferFormat = D3DFMT_UNKNOWN ;
  18. d3dpp。 FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT ;
  19. d3dpp。 PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE ;
  20. d3dpp。 SwapEffect = D3DSWAPEFFECT_DISCARD ;
  21. d3dpp。 EnableAutoDepthStencil = TRUE ;
  22. d3dpp。 AutoDepthStencilFormat = D3DFMT_D16 ;
  23. HRESULT hrResult = m_pD3D- > CreateDevice D3DADAPTER_DEFAULT D3DDEVTYPE_HAL winId
  24. D3DCREATE_HARDWARE_VERTEXPROCESSING
  25. d3dpp m_pd3dDevice ;
  26. if 失敗 hrResult
  27. falseを返します
  28. trueを返します
  29. }
  30. bool Direct3DWidget :: レンダリング
  31. {
  32. if m_pd3dDevice == 0
  33. falseを返します
  34. m_pd3dDevice- > Clear 0、0 D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER D3DCOLOR_XRGB 255、255、0 1.0f 0 ;
  35. if SUCCEEDED m_pd3dDevice- > BeginScene ))
  36. {
  37. m_pd3dDevice- > EndScene ;
  38. }
  39. m_pd3dDevice- > Present 0、0、0、0 ;
  40. trueを返します
  41. }
  42. void Direct3DWidget :: paintEvent QPaintEvent * pEvent
  43. {
  44. Q_UNUSED pEvent ;
  45. レンダリング ;
  46. }








使用例:

  1. #include <QtGui / QWidget>
  2. #include <QtGui / QApplication>
  3. #include <QtGui / QHBoxLayout>
  4. #include "Direct3DWidget.h"
  5. int main int argc char * argv [ ]
  6. {
  7. // ------------------------------初期化を開始
  8. //追加のパラメータ、カンマで区切られたパラメータを追加するだけ
  9. std :: string aAdditionalParameters [ ] = { "-direct3d" } ;
  10. int iRealArgumentAmount = argc + sizeof aAdditionalParameters / sizeof std :: string ;
  11. //このダブルポインターには、argvからのパラメーターが含まれます。
  12. //このアプリケーションに必要な静的パラメータ
  13. char ** pArguments = new char * [ iRealArgumentAmount ] ;
  14. //すべてのソース(コマンドラインから)パラメーターをコピーします
  15. for int i = 0 ; i < argc ; ++ i
  16. {
  17. * pArguments + i = new char [ strlen argv [ i ] + 1 ] ;
  18. strcpy * pArguments + i argv [ i ] ;
  19. }
  20. //追加するパラメーターを追加します
  21. for int i = argc j = 0 ; i < iRealArgumentAmount ; ++ i ++ j
  22. {
  23. * pArguments + i = new char [ aAdditionalParameters [ j ]サイズ + 1 ] ;
  24. strcpy * pArguments + i aAdditionalParameters [ j ] .c_str ;
  25. }
  26. QApplication xApplication iRealArgumentAmount pArguments ;
  27. for int i = 0 ; i < iRealArgumentAmount ; ++ i
  28. delete [ ] * pArguments + i ;
  29. delete [ ] pArguments ;
  30. // --------------------------------初期化完了
  31. QWidget xMainWindow ;
  32. Direct3DWidget * xScene = 新しい Direct3DWidget xMainWindow ;
  33. QHBoxLayout * xMainLayout = new QHBoxLayout ;
  34. xMainLayout- > addWidget xScene ;
  35. xMainWindow。 setLayout xMainLayout ;
  36. //ウィジェットがウィンドウに埋め込まれた後にDirect3dを初期化することが重要です
  37. xScene- > InitDirect3D ;
  38. xMainWindow。 show ;
  39. xApplicationを返します。 exec ;
  40. }








このコードの実行結果は、そのようなウィンドウになります(ストレッチした場合)。

画像



優れたQtフレームワークでdirect3dを静かに使用するためのすべてがあるように思えますが、残念ながら、いくつかの落とし穴を発見しました。

一部のコンピューターでは、Direct3dで描画した画像の代わりにDirect3dを使用し始めた後、背景色でペイントされた画面がありました。 属性のすべての組み合わせを試しましたが、この欠陥を取り除くことができませんでした。 一部のマシンでは、direct3dエンジンの誤動作の原因を特定することもできませんでした。 Qtのドキュメントには「 この機能は実験的なものです。 "、問題はdirect3dサポートの素朴さであると仮定できます。



しかし、この欠点がDirect3Dを使用しない理由にはなりません:)。 trolltechがdirect3dを安定状態に完了する間、次の回避策を使用できます。

paintEventのRendering()の呼び出しをコメントアウトします。

  1. void Direct3DWidget :: paintEvent QPaintEvent * pEvent
  2. {
  3. Q_UNUSED pEvent ;
  4. //レンダリング();
  5. }






使用場所に次のコードを追加します。



  1. ...
  2. //ウィジェットがウィンドウに埋め込まれた後にDirect3dを初期化することが重要です
  3. xScene- > InitDirect3D ;
  4. xMainWindow。 show ;
  5. QTimer xTimer ;
  6. QWidget :: connect xTimer SIGNAL timeout )) xScene SLOT Rendering )) ;
  7. xTimer。 開始 100 ;
  8. xApplicationを返します。 exec ;
  9. ...






このコードを上記の例のコードに追加しました。

また、 QTimerヘッダーを含めることを忘れないでください



QtでDirect3d APIの使用をお楽しみください。 -direct3dオプションを使用してアプリケーションを起動することを忘れないでください。このオプションを使用例のコードに含めました。



All Articles