Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

14

Share

Download to read offline

Direct xとopenglの隠蔽実装例

Download to read offline

Direct xとopenglの隠蔽実装例

  1. 1. DirectX9 と OpenGL の隠蔽実装例 TECO
  2. 2. まず始めに <ul><li>  プレゼンターが早口になっていたら </li></ul><ul><li> 指摘してあげてください。 </li></ul>
  3. 3. アジェンダ <ul><li>設計方針 </li></ul><ul><li>隠蔽方法 </li></ul><ul><li>3D 描画で必要な機能 </li></ul><ul><li>DirectX9 と OpenGL の違い </li></ul><ul><li>Q & A </li></ul>
  4. 4. 設計方針 (1) <ul><li>優先順位を明確にする </li></ul><ul><li>  ( 実行速度 ) > </li></ul><ul><li>  ( 移植性 ) ≒ ( 拡張性 ) ≒ ( 可読性 ) > </li></ul><ul><li>  ( コンパイル速度 ) </li></ul><ul><li> -> 移植性を上げるために、アプリケーションからは 基本的 に依存部分は触らなくて済むこと。 </li></ul><ul><li>->  拡張性を上げるために、無駄なリンクはされないようにする。 </li></ul><ul><li> -> 可読性が下がりそうだったら、 cpp ファイルを依存別に分けることも検討 </li></ul>
  5. 5. 設計方針 (2) <ul><li>依存部分にアクセスできること </li></ul><ul><li> -> ミドルウェアに依存部分のデータを渡す必要があることがある。 </li></ul><ul><li> -> ライブラリ側に実装されてない機能を、アプリケーション側でテストしやすい環境を作る。 </li></ul>
  6. 6. クラスの隠蔽方法 (1) <ul><li>継承 </li></ul><ul><li>#if 〜 #endif </li></ul><ul><li>動的リンク </li></ul><ul><li>pImpl イディオム </li></ul><ul><li>Typedef </li></ul><ul><li>pImpl イディオムと Typedef の思想融合型 </li></ul>
  7. 7. クラスの隠蔽方法 (2) <ul><li>継承 </li></ul><ul><li> 実行速度: ×  コンパイル速度:◯ 可読性:◯ </li></ul><ul><li> 依存部分アクセス性: ×  動的切替:◯ </li></ul><ul><li> コーディングしやすさ:◯ </li></ul><ul><li>#if 〜 #endif </li></ul><ul><li> 実行速度:◯ コンパイル速度:◯ 可読性: × or △or ◯ </li></ul><ul><li> 依存部分アクセス性:書き方次第 動的切替: × </li></ul><ul><li> コーディングしやすさ:◯ </li></ul><ul><li>動的リンク </li></ul><ul><li> 実行速度:? コンパイル速度:◯ 可読性:◯ </li></ul><ul><li> 依存部分アクセス性: ×  動的切替: </li></ul><ul><li> コーディングしやすさ:△  その他: Ogre3D で採用 </li></ul>
  8. 8. クラスの隠蔽方法 (3) <ul><li>pImpl イディオム </li></ul><ul><li> 概要:依存部分と共通部分の型を分けて、共通部分の型が依存部分の型のポインタを持つ。 依存種類の数だけ cpp ファイルを用意する。 (cpp 側で RenderDeviceDepend を定義する ) </li></ul><ul><li>  class RenderDevice { </li></ul><ul><li>  public : </li></ul><ul><li>    RenderDevice(); </li></ul><ul><li> void Draw(); </li></ul><ul><li>  private : </li></ul><ul><li>    RenderDeviceDepend* m_Depend; </li></ul><ul><li>  } </li></ul><ul><li> 実行速度:△(キャッシュミスの恐れ)コンパイル速度:◯  </li></ul><ul><li> 可読性:◯ 依存部分アクセス性: ×  動的切替: × </li></ul><ul><li> コーディングしやすさ:◯ その他: boost のスマートポインタ参照 </li></ul>
  9. 9. クラスの隠蔽方法 (4) <ul><li>Typedef </li></ul><ul><li> 概要:型名と関数名は統一して、自由に型を定義して typedef する。 </li></ul><ul><li>  class RenderDeviceDX9 { ・・・ } </li></ul><ul><li>  class RenderDeviceGL{ ・・・ } </li></ul><ul><li>  typedef RenderDeviceGL RenderDevice; </li></ul><ul><li> 実行速度:◯ コンパイル速度:△ </li></ul><ul><li> 可読性:◯ 依存部分アクセス性:◯ 動的切替: × </li></ul><ul><li> コーディングしやすさ: × </li></ul><ul><li>  おしい。 これだけでは依存部分で同じコードを各部分が発生する。 </li></ul><ul><li>  </li></ul><ul><li>  </li></ul>
  10. 10. クラスの隠蔽方法 (5) <ul><li>pImpl イディオムと Typedef の思想融合型 </li></ul><ul><li>  概要:依存部分と共通部分の型を分けて、共通部分の型が依存部分の型を実体を持つ。 依存種類の数だけ cpp ファイルを用意する。 RenderDeviceDepend は typedef で切り替える。 </li></ul><ul><li>  #include <render_device_depend.h> // この中で RenderDeviceDepend を typedef する。 </li></ul><ul><li>  class RenderDevice { </li></ul><ul><li>  public : </li></ul><ul><li> void Draw(); </li></ul><ul><li>  private : </li></ul><ul><li>    RenderDeviceDepend m_Depend; </li></ul><ul><li>  } </li></ul><ul><li> 実行速度:◯ コンパイル速度:△ </li></ul><ul><li> 可読性:◯ 依存部分アクセス性:◯ 動的切替: × </li></ul><ul><li> コーディングしやすさ:◯ </li></ul>
  11. 11. クラスの隠蔽方法 (6) <ul><li>【結論】 </li></ul><ul><li>  pImpl イディオムと Typedef の </li></ul><ul><li>            思想融合型採用 </li></ul><ul><li>【余談】 </li></ul><ul><li> グローバル関数の場合は、可読性が落ちないなら #if~#endif 、可読性が落ちそうだったら機種依存別に cpp を用意する。 </li></ul>
  12. 12. 3D 描画で必要な機能 <ul><li>デバイス </li></ul><ul><li>ビュー </li></ul><ul><li>頂点バッファ </li></ul><ul><li>頂点フォーマット </li></ul><ul><li>座標変換行列 </li></ul><ul><li>ラスタライズ設定 </li></ul><ul><li>テクスチャ </li></ul><ul><li>テクスチャサンプラ </li></ul><ul><li>シェーダ </li></ul>
  13. 13. DX9 と GL の隠蔽方針 <ul><li>基本的には DirectX 風のオブジェクト指向。 </li></ul><ul><li>依存部分には依存クラスを介してアクセス可能。各クラスは依存コードを集約させた Depend クラスの実体をメンバとして持つ。 </li></ul>
  14. 14. DX9 と GL の違い ( デバイス ) <ul><li>定義:リソース ( 頂点バッファ、テクスチャなど)管理やレンダリング用設定管理、コマンドバッファの発行を行う。 </li></ul><ul><li>    注 ) ウィンドウに 1:1 の関係ではない。 </li></ul><ul><li>【 DX9 】 </li></ul><ul><li>・オブジェクト指向 </li></ul><ul><li>・生成方法が一つ。 </li></ul><ul><li>【 OpenGL 】 </li></ul><ul><li>・非オブジェクト指向 </li></ul><ul><li> -> カレントのデバイスコンテキストを切り替える。 </li></ul><ul><li>・生成方法がプラットフォーム毎に異なる。 </li></ul><ul><li>隠蔽方針: Device クラスを作る。 OpenGL 版ではカレントのデバイスコンテキスト切り替えは自動で行う。 DirectX 版のみ、 Depend クラスにデバイスロスト用コードを仕込む。 </li></ul>
  15. 15. DX9 と GL の違い ( ビュー ) <ul><li>定義:ウィンドウに対して 1 対 1 の関係にあるもの。絵を描く紙のような概念(バックバッファを持つ)。 1 つのデバイスが複数のビューを持てる。(マルチウィンドウで描画する時に考える必要がある) </li></ul><ul><li>【 DX9 】 </li></ul><ul><li> ・ SwapChain を利用。 </li></ul><ul><li>【 GL 】 </li></ul><ul><li> ・ 1 つのデバイスで複数のビューを作る場合は新しいデバイスコンテキストを作り、親となるデバイスのリソースや設定を共有できるようにする (Windows だと wglSharedList 関数を利用 ) </li></ul><ul><li>隠蔽方針: Device クラスから View クラスとして複数生成できるようにする。 View から RenderTarget 情報を取得・設定することで描画を切り替える。 </li></ul>
  16. 16. DX9 と GL の違い ( 頂点バッファ / フォーマット) 固定シェーダ編 <ul><li>【 DX9 】 </li></ul><ul><li> ・頂点バッファと頂点フォーマットの設定が別々 </li></ul><ul><li>   ( SetStreamSource 、 SetVertexDeclaration ) </li></ul><ul><li>【 GL 】 </li></ul><ul><li> ・頂点バッファと頂点フォーマットの設定が同時 </li></ul><ul><li>   ( glVertexPointer 、 glColorPointer ・・・ ) </li></ul><ul><li>隠蔽方針: VertexBuffer 、 VertexFormat クラス、 SetVertexBuffer 関数、 SetVertexFormat 関数を定義。 OpenGL 版は、 Draw 関数を呼ばれた時に初めて gl◯◯Pointer 関数で頂点バッファとフォーマットを設定する(それまで組み合わせが確定できないので) </li></ul>
  17. 17. DX9 と GL の違い ( デカルト座標系 1) <ul><li>【 DX9 】 </li></ul><ul><li> ヘルパー関数 (D3DXMatrixPerspectiveFovLH など ) を使うと右手座標系の行列、左手座標系の行列を選べる。(最終的な z/w=0.0f 〜 1.0f ) </li></ul><ul><li>【 GL 】 </li></ul><ul><li> ヘルパー関数 (gluPerspective 、 gluLookAt) を使うと、右手座標系(最終的な z/w=-1.0f 〜 1.0f) </li></ul><ul><li>隠蔽方針: 3DAPI 依存のヘルパー関数は一切使わず、自前で左手、右手座標系用関数を用意する。 DX9 と GL では座標系が同じでも行列は違うのと、座標系が違うと表面と裏面が逆になるのを注意。 </li></ul>
  18. 18. DX9 と GL の違い ( デカルト座標系 2) <ul><li>ビュー変換行列 (vec eye,vec at, vec up) </li></ul>
  19. 19. DX9 と GL の違い ( デカルト座標系 3) <ul><li>透視射影行列 (f32 fovy , f32 aspect , f32 znear , f32 zfar ) </li></ul>
  20. 20. DX9 と GL の違い ( テクスチャ ) <ul><li>【 DX9 】     【 GL 】 </li></ul><ul><li>隠蔽方針: Texture クラスを作って隠蔽。 DirectX 版のみ Depend クラスは LostResource クラスを継承して、デバイスロスト時にリセットが必要なリソースとして管理する ( 頂点バッファも同様 ) 。座標系が違うのは、テクスチャ座標変換行列で対応する。 </li></ul>
  21. 21. Dx9 と GL の違い ( テクスチャサンプラ ) <ul><li>定義:テクスチャからどのように画素情報を取得するか。フィルター設定など </li></ul><ul><li>【 DX9 】 </li></ul><ul><li>  SetSamplerState 関数を利用。テクスチャステージ毎に反映。 </li></ul><ul><li>【 GL 】 </li></ul><ul><li>  glTexParameter 関数を利用。テクスチャ毎に反映。 </li></ul><ul><li>隠蔽方針: SamplerState クラスを作って、 Device にテクスチャステージ毎に設定できるようにした。 GL 版では設定するたびに、テクスチャステージのテクスチャに設定し直す。 </li></ul>
  22. 22. DX9 と GL の違い ( ラスタライザ・ブレンド設定 ) <ul><li>定義:カリング設定、ブレンド設定など </li></ul><ul><li>【 DX9 】 </li></ul><ul><li>  SetRenderState 関数で全て設定可能。 </li></ul><ul><li>【 GL 】 </li></ul><ul><li> それぞれにグローバル関数が用意されている。 </li></ul><ul><li>隠蔽方針: Device クラスにそれぞれの設定関数を持たせる。( DX11 が要素別に設定するようになったので) </li></ul>
  23. 23. DX9 と GL の違い(シェーダ:全般 ) <ul><li>【 HLSL 】 </li></ul><ul><li> ・エフェクトファイルがある。 </li></ul><ul><li> ・頂点、ピクセルシェーダ毎に設定可能。 (SetVertexShader 、 SetPixelShader) </li></ul><ul><li>【 GLSL 】 </li></ul><ul><li> ・エフェクトファイルが無い。 </li></ul><ul><li> ・頂点、ピクセルシェーダを一つのプログラムにバインドして利用( glGenProgram 、 glBindProgram 、 glLinkProgram 、 glUseProgram ) </li></ul><ul><li>隠蔽方針:エフェクトファイル処理は GL 版では関数はあるが、何も処理はしない。組み合わせの切り替えは容易にできるようにしたいので、 DirectX 風に作る。頂点シェーダ毎に glGenProgram を呼ぶ(理由は次のページで) </li></ul>
  24. 24. DX9 と GL の違い     ( シェーダ:頂点フォーマット ) <ul><li>【 HLSL 】 </li></ul><ul><li> ・どの入力変数がどの要素(位置、カラー)かはセマンティックスによって管理されている (POSITION0 、 COLOR0 等 ) </li></ul><ul><li>【 GLSL 】 (attribute 変数 ) </li></ul><ul><li> ・どの入力変数がどの要素かは CPU 側から変数名に対応した番号で指定する (glGetAttribLocation 、 glBindAttribLocation 、 glVertexAttribPointer) 。 glBindProgram で頂点シェーダを切り替えると glBindAttribLocation の設定はリセットされる(頂点シェーダ毎に glGenProgram を発行している理由) </li></ul><ul><li>隠蔽手法: DirectX の頂点フォーマットと同じ考え。 GL 版では各セマンティクスに対応した変数名を用意しておく(名前はカスタマイズ可能に) </li></ul>
  25. 25. DX9 と GL の違い ( シェーダ: Uniform 変数 ) <ul><li>定義: CPU 側から設定できて、シェーダ側からでは変更できないグローバル変数。 </li></ul><ul><li>【 DX9 】 </li></ul><ul><li> ・定数レジスタ番号から値を設定 </li></ul><ul><li> ・シェーダの組み合わせが変更されても有効 </li></ul><ul><li>【 GL 】 </li></ul><ul><li> ・変数名から取得できるハンドルから値を設定 </li></ul><ul><li> ・シェーダの組み合わせが変更されると無効 </li></ul><ul><li>隠蔽方針: DX9 版は定数レジスタ番号、 GL 版は変数名(指定の命名規則)に紐づいた共通 enum を使いハンドルを取得して、値を設定できるように。 </li></ul>
  26. 26. Q&A <ul><li>何かありましたら、以下のメールアドレスへ </li></ul><ul><li>  [email_address] </li></ul>
  • koheimikoshiba

    Jun. 10, 2018
  • yamaoku1500

    Jan. 6, 2017
  • mybeko3

    Dec. 20, 2016
  • ssuserf5384a

    Sep. 24, 2016
  • YukiKoawara

    May. 29, 2016
  • kymstk54

    Jul. 15, 2015
  • sykaneta

    Apr. 14, 2015
  • ShojiYamauchi

    Mar. 14, 2015
  • boxpurin

    Mar. 13, 2015
  • shintaroiguchi

    Mar. 24, 2014
  • stdmouse

    Nov. 30, 2013
  • shotahomma140

    Sep. 10, 2013
  • tyoro

    Feb. 22, 2013
  • xg2t

    Dec. 19, 2011

Views

Total views

11,833

On Slideshare

0

From embeds

0

Number of embeds

258

Actions

Downloads

46

Shares

0

Comments

0

Likes

14

×