8/25(火)


せきちゃんから返事が来た。

>あと、V-Syncを待つ、みたいな処理は書いてないけど、
>これはフリップすると自動的に待って、切り替えてくれるのかな?
>それとも、そもそもV-Syncとかってモノがないのかしらん?
フリップすれば、かってにV-Syncを取ってくれたんじゃないかな。
でも、ビデオカードによっては100fpsなどとてつもなく速くなってしまうので
60fpsで処理するようにタイミングを取ってやらないといけないはずです。
たいていは大丈夫だと思うけどね。

>アイドル中に描画とフリップをすればいいのか?ってのと、
アプリケーション = DirectXのプログラムならいいんじゃないですか?
普通は " DDFLIP_WAIT " で切り替えてれば気にしなくていいはずです。

せきちゃん

なるほど・・・
V-Syncは勝手に待ってくれるのか。

あと、フリップのタイミングもアイドル中でいいみたいだ。
「アプリケーション = DirectXのプログラム」ってのは、リアルタイム系ならってことだろう。
たしかに、非リアルタイム系なら別のタイミングのイベントでフリップすればいいもんね。
たとえば、3DのモデラーとかをDirectXで作った場合は「なんか編集されたら」みたいなタイミングでOKだろう。


今日もDirectX関係やってみた。
例によって「実践DirectXプログラミング」のサンプルをBuilderに書き換えてみる。
今日は「ダブルバッファを作ってフリップさせてみる」だ。

前回からの書き換えは極わずかだ。
あと、スペースキーを押したらフリップするってプログラムなので、OnKeyDownなんかを書いてやる。
書き換えは実にあっさり終わった。

で、コンパイル、実行・・・・動かん?

ナゼ? Why? どうして?

正確な症状は画面が一瞬真っ黒になって、普通のデスクトップに戻ってしまう。
フリップさせるスペースキーを押したら、EAccessVioration例外発生。(ようは、メモリの変なところにアクセスしたのね)
本来なら解像度が切り替わって、画面が真っ黒になり、そのままにならないとおかしい。

ソースをじっくり確かめてみる。
どこもまちがっとらんぞ?
そもそも、えむっちはDirectXにはまだ慣れてないのでスペルミスとかはあっても、論理的に間違うなんて有り得ん。
スペルミスぐらいならコンパイラが「間違ってるよ」って教えてくれるのでそれも無い。

なんでじゃろ?
ともかく、どれが失敗してるかを確かめないと・・・

で、調べた結果、どうやら
ret = pDDraw->CreateSurface(&ddsd,&pOldScreen,NULL);
が、失敗しているらしい・・・

なぜ?
サンプル1ではちゃんと動いてたぞ?
サンプル1との差はどこか、調べてみる?

構造体ddsdに設定した値が違うことが判明。(以下)






 

 ZeroMemory(&ddsd,sizeof(ddsd));
 ddsd.dwSize = sizeof(ddsd);
 ddsd.dwFlags = DDSD_CAPS;
 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;





 

 ZeroMemory(&ddsd,sizeof(ddsd));
 ddsd.dwSize = sizeof(ddsd);
 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
 ddsd.dwBackBufferCount = 1;

この値まちがっとるんやろか?
他の本のサンプルと見比べてみようと思い、「Direct3Dプログラミングガイド」のサンプルを見てみる。

・・・まったく同じ値じゃないか。
えむっちのビデオカードがダブルバッファに対応してないのか知らん?
いや、サンプルにくっついてきた実行形式はちゃんと動いてるから、それはないなぁ。

じゃ、コンパイラの設定がおかしいのか?
でも、ちゃんとコンパイルできてるよなぁ。
DirectXはCOMとかDLLで実装されてるから、サンプルにっくっついてきた実行形式もえむっちが作った実行形式も
どっちも同じモノにアクセスしたワケだし・・・
はっきり言ってわからんぞ?

と、思いつつ、ヤル気うせうせモードに入ったのだが・・・

「そうだ!SetCooperativeLevel()に渡した、Handleがサンプルとは異なるゾ」とヒラメイタのである。

じゃ、変わりにどのHandle渡すの?
HandleはForm->HandleとApplication->Handleあるけど?
今、渡してるのはForm->Handleだよなぁ・・・
でも、Application->HandleはメインフォームのHandleといっしょのはずだよなぁ・・・
とりあえず、やってみるか。

・・・うわっ!スケスケのウィンドウが!!
ん?でもFormも表示されてるぞ?
うーん、と言うことは・・・

ApplicationはForm1とは別のWindowを持ってたんだ・・・
しかも、透明で見えなくしてたのね・・・

うーん、これを応用すれば、「すけすけパンツ計画」の透けるWindowも作れるかも・・・

って指し当たっての問題が解決してないよ・・・

やっぱり、だめねぇ・・・

サンプルのヤツとなんか違うところがあるんだろうなぁ・・・

このSetCooperativeLevel()に渡すHandleは、「こうじゃないとダメ」みたいな決まりがあるのかも知れん。

しょうがない、やりたくないけど、非VCLモードで組んでみよう。
Builderは普通のRADじゃないコンパイラとしても使えるので、そのモードを試してみることにした。
知らない人のためにチョットだけやり方を書いておきます。

[ファイル]->[新規作成]から[コンソールウィザード]を選択。

[ウィンドウ(GUI)]と[EXE]にラジオボタンをあわせて[完了]をクリック。

これで、空っぽのWinMainのみが作られて、普通にAPIとかでプログラムするモードになります。

うーん・・・
サンプルをカット&ペーストしてとりあえずコンパイルしてみるか・・・
おっと、libファイルを 指定せねば。

あれっ?プロジェクトマネージャで追加すると、USELIBって行が勝手に追加されたけど、
この行でコンパイルエラー出てるよ・・・

まったく、どうなってるんだよぉ。
しょうがない、makefileにダイレクトに書き込んで指定してやれ。

よしよし、コンパイル成功。
で、実行・・・・

おおっ!動くよ!
やったー!!

しかし、待てよ?これは喜んでいいのか?
これでしか動かんと言うことは、DirectXはこのモードで組まねばならんと言うことでは・・・

げぇー、さいてー!!

それだけは避けたい。
VCLを使わないのなら、Builderでやるメリットなど何一つ残らず消し飛んでしまう!!
それなら、VC++の方が65536倍以上もいいじゃないか!!

何とかならんのかよぉ・・・

うーん、もし、SetCooperativeLevel()に渡すHandleは、「こうじゃないとダメ」って決まりがあったとして、
その決まりがわかれば何とかなるかも知れんなぁ・・・

あと、世の中にはBuilderやDelphiで使えるDirectXのコンポーネントが結構出回っている。
それらはコンポーネントなので当然VCLモードで組んでいるわけだ。
これらのコンポーネントを解析すれば何か解決の糸口がつかめるかも知れんゾ。

よしっ、指し当たってDDDDをダウンロードだ。
DDDDはDelphiでDirectXを使えるようにするコンポーネントだ。Builderでも使えるらしい。
Electrical Fireworksからダウンロードできる。
しかし、DDDDは当然Pascalなんだよなぁ・・・・
えむっちはPascalを勉強したことが無いので、読むのに骨がおれるんだよぉ・・・

あ、Direct3ZCもあったなぁ・・・
でも、あれはシェアウェアだし・・・
体験版にソースついてこないよなぁ、当然。
あとで調べてみるか・・・・

SetCooperativeLevel()の方はせきちゃんに聞いてみよう。

と、言うところで今日は遅いので、また今度。
せきちゃんにメールだけ出しとかないとね。


戻る