やっと HTC Touch Diamond で Direct3DMobile が動くようになりました。
ハードウエアアクセラレータがきいていて、一応 VGA のフルスクリーンで
28~29fps くらい出ています。
かなり苦労しました。
caps を見ると Touch Pro なども同じかもしれません。
●苦労話
とにかく Touch Diamond では Direct3DM が全く動かなくて驚きました。
昔作ったプログラムも全滅で、WindowsMobile6 SDK のサンプルもだめ。
プログラムは動作するものの全く描画されないという症状。
caps はそれらしい値が取れていて、しかもハードウエアアクセラレータが有効との
魅力的な値を返してきます。
実際に d3dm_ati.dll が読み込まれているところまでは確認できます。
それでも画面は変わらず Clear() で埋めたカラーすら画面には現れてこないという。
D3DMPRESENT_PARAMETERS の組み合わせをいくら変えてもだめ。
画面の回転方向を変えてもだめ。
API 呼び出しは矛盾する設定をするとエラーになるので、一応動作しているようにも
見えます。
ちなみに d3dmref.dll も無いのでリファレンスラスタライザも使えません。
何とか d3dm_ati.dll が動く条件を見つけるしかなさそうです。
とりあえず Present() が悪いのかレンダリングそのものが走っていないのかだけ確認
してみます。
BeginScene(); Clear(); EndScene(); Present(); GetBackBuffer(); CopyRect(); // BackBuffer → ImageSurface ImageSurface->LockRect() // 読み出し ImageSurface->UnlockRect()
こんな感じで BackBuffer の値を読み出してみると、一応カラーが書き込まれている
ことがわかりました。
Present() が失敗してるだけでレンダリングそのものは動いています。
でも Present() はエラーを返さず、Device も Lost していません。
BackBuffer には書き込まれていることがわかったので、Lock して読み出して
自分で Window に描画すれば (力業だけど) 描画できるのではないかと思いつきました。
フレームバッファの値を直接読み出して CPU で DIB に変換。CompatibleBitmap に
描画してからウィンドウにコピー。
最終的には R5G6B5 サーフェースの値がそのまま DIB として利用できることが
わかったので、転送や変換を減らして下記の通りです。
~ iDevice->Present( NULL, NULL, NULL, NULL ); IDirect3DMobileSurface* iBack= NULL; iDevice->GetBackBuffer( 0, &iBack ); iDevice->CopyRects( iBack, NULL, 0, iSurface, NULL ); iBack->Release(); D3DMLOCKED_RECT lock; iSurface->LockRect( &lock, NULL, D3DMLOCK_READONLY ); SetDIBitsToDevice( hDC, 0, 0, Width, Height, 0, 0, 0, Height, lock.pBits, &BitmapHead, DIB_RGB_COLORS ); iSurface->UnlockRect();
一応これで VGA (640×480) フルスクリーンでの Direct3DM の描画に成功しました。
でもかなり遅いです。上の最適化した状態で目測 5fps 程度。
この方法は FullScreen でも Windowed どちらでも動作しますが、最終的には
Bitmap 化するためウィンドウの中に描画しています。
転送を減らすため、試しに QVGA 240×320 くらいにフレームバッファを縮小してみます。
FullScreen の場合デバイスの解像度と一致していないとハングアップするので
Windowed = TRUE に。QVGA だとこの方法でも 15fps くらいになりました。
ふとこの状態で Lock & Copy をやめてみると、DIB を通さなくてもちゃんと
描画されていて、しかも 30fps 近く出ていることを発見!
ハードウエアアクセラレータ効いています。
その後いろいろためした結果、なんと「640×480 のレンダリングだけ」失敗することが
わかりました。
例えば 1pixel 減らして 480 x 639 や 478×640 にすると描画できます。
FullScreen (Windowed = FALSE) の場合デバイスの解像度と一致していないと
エラーで落ちるので、WindowMode (Windowed = TRUE) が必須となります。
●結論
・解像度を 480×640 より小さくする (480×639 or 479×640 など)
・小さくするために必ず WindowMode にする
の条件さえ満たせば Touch Diamond でも Direct3D でポリゴン描画できます。
SDK のサンプルなど、多くのプログラムは GetSystemMetrics( SM_CXSCREEN )、
GetSystemMetrics( SM_CYSCREEN ) を使ってデバイスの解像度でレンダリング
しようとしています。これが原因でした。
わかってしまえば簡単なんだけど、、、途中何度挫折しかけたことか。
リファレンスラスタライザが使えていたらすぐあきらめていたかも。
いつも読ませていただいています。かみやんです。やーすごいバグですね。なんで開発者はサンプルすら確認しなかったのだろう~。
かみやんさん こんにちは
誰も D3DM を使っていない、、その証拠がまたひとつ増えました。
やっぱり OpenGLES を使った方がよいのかな。
Windows Mobile用のibisBrowserを作るときにD3DM使おうか迷いました。EM・ONEしかハードウェアが効く端末がなく、パフォーマンスもでなかったので辞めましたが。
OpenGLESってWindows Mobileであるんだ〜。知りませんでした。
#今iPhone用のアプリ開発中〜
EM・ONE 遅いですよね・・。
GoForce にだまされて買ったものの D3DM は MMX ドライバ。
ほんとにまともに D3DM 使える端末が少ないです。
WM の 3D ものは GLES だときいたことがありますが
実際に使ったことはないです。
iPhone はアプリを見ても速そうです。