DirectXの描画について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
たろう

DirectXの描画について

#1

投稿記事 by たろう » 15年前

DIrectXで描画したのですが、描画WM_PAINTのところにDirectXの描画関数を入れて実行したのですが、
それだと画面の外に移動してもちゃんと描画されたのですが、
while(1)
if(PeekMessage(...))
{
....
}
else
{
Render()
}
と言う風にそれを実行すると、外に画面を移すと描画されないで表示されるのですが。
描画WM_PAINTのところにDirectXの描画関数を入れる方法以外に外に画面を移すと描画されないで表示されることを回避する方法はないでしょうか?
上のソースのようにして、この外に画面を移すと描画されないで表示されるというようなことを起こさない方法はないのでしょうか?

シエル

Re:DirectXの描画について

#2

投稿記事 by シエル » 15年前

画面を掴んでいる間は、ウィンドウプロシージャが処理中だからではないでしょうか?

Justy

Re:DirectXの描画について

#3

投稿記事 by Justy » 15年前

 スレッドで描画。

シエル

Re:DirectXの描画について

#4

投稿記事 by シエル » 15年前

私はストリーミング再生のためだけに、スレッドを作って常に読み込ますようにしてます。。。

たろう

Re:DirectXの描画について

#5

投稿記事 by たろう » 15年前

回答ありがとうございます。
>画面を掴んでいる間は、ウィンドウプロシージャが処理中だからではないでしょうか?
FPS制御するときに支障はないのでしょうか?
他の方法はやっぱりないのでしょうか?
あと、
WNDCLASS wc;
.
.
.
wc.hbrBackground = NULL;
これを(HBRUSH)GetStockObject(WHITE_BRUSH)にするとチカチカするのですが、これは、
バックグラウンドが白になるため移動したりした時にバックグラウンドの白も再描画されてしまうためなのでしょうか?間違っていたらすみません。
質問ばかりですみません。よろしくお願いします。

シエル

Re:DirectXの描画について

#6

投稿記事 by シエル » 15年前

描画はどのような方法で行ってますか?
バックバッファに描画してから、メイン画面へ反映へする方法はとっていないのですか?

たろう

Re:DirectXの描画について

#7

投稿記事 by たろう » 15年前

回答ありがとうございます。
描画は、下のようにしています。
g_D3DPP.BackBufferCountでバックバッファに描画してると思うのですが、違いますでしょうか?
HRESULT Initialize(HWND hwnd,bool fullScreen,int Hieght,int Width)
{
    D3DDISPLAYMODE d3dMode;
    //Direct3D9のオブジェクトの作成
    if((g_pD3D=Direct3DCreate9(D3D_SDK_VERSION))==0)
    {
        return E_FAIL;
    }
    //現在のディスプレイモードを取得
    if(FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&d3dMode)))
    {
        return E_FAIL;
    }
    //デバイスのプレゼンテーションパラメータを初期化    
    ZeroMemory(&g_D3DPP,sizeof(D3DPRESENT_PARAMETERS));
    g_D3DPP.BackBufferCount=1;
    if(fullScreen)//フルスクリーンかどうか?
    {
        g_D3DPP.Windowed=FALSE;
        g_D3DPP.BackBufferHeight=Hieght;
        g_D3DPP.BackBufferWidth=Width;
    }
    else
    {
        g_D3DPP.Windowed=TRUE;
    }
    g_D3DPP.BackBufferFormat=d3dMode.Format;    //カラーモードの指定
    g_D3DPP.SwapEffect=D3DSWAPEFFECT_DISCARD;    //どの方法でモニター画面に転送するか指定
    g_D3DPP.EnableAutoDepthStencil=TRUE;        //エラー対策
    g_D3DPP.AutoDepthStencilFormat=D3DFMT_D16;    //エラー対策

    //ディスプレイアダプタを表すためのデバイスを作成
    //描画と頂点処理をハードウェアで行う
    if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,
                                    D3DDEVTYPE_HAL,
                                    hwnd,
                                    D3DCREATE_HARDWARE_VERTEXPROCESSING,
                                    &g_D3DPP,&g_pD3DDevice))){
            //描画はハードウェアで行い頂点処理はCPUが行う
            if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,
                                        D3DDEVTYPE_HAL,
                                        hwnd,
                                        D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                        &g_D3DPP,&g_pD3DDevice))){
                //描画と頂点処理はCPUで行う
                if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,
                                                D3DDEVTYPE_REF,
                                                hwnd,
                                                D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                                &g_D3DPP,&g_pD3DDevice))){
                                                    g_pD3D->Release();
                                                    return E_FAIL;
                
                }
            }
    }
メインの描画は下にあるとおりです。
void RenderScene(void)
{
    // ビューポートと深度バッファのクリアとステンシルバッファの削除
    if(FAILED(g_pD3DDevice->Clear(0,NULL,         // クリアする領域は全面
                    D3DCLEAR_TARGET |            // バックバッファを指定
                    D3DCLEAR_ZBUFFER,             // 深度バッファ(Zバッファ)を指定
                    D3DCOLOR_XRGB(0,0,0),         // クリアする色
                    1.0f,                         // クリアする深度バッファ(Zバッファ)の値
                    0))) {                        // クリアするステンシルバッファの値
        return;
    }

    // 描画開始宣言
    if(SUCCEEDED(g_pD3DDevice->BeginScene())) {

        // モデルなどの描画
        Draw();

        // 描画終了宣言
        g_pD3DDevice->EndScene();
    }

    // 描画結果の転送
    if(FAILED(g_pD3DDevice->Present( 0, 0, 0, 0 ))) {
        // デバイス消失から復帰
        g_pD3DDevice->Reset(&g_D3DPP);
    }
}

シエル

Re:DirectXの描画について

#8

投稿記事 by シエル » 15年前

チカチカするのは常にチカチカするんですか?移動したときだけですか?

たろう

Re:DirectXの描画について

#9

投稿記事 by たろう » 15年前

返信ありがとうございます。はい。そうです。

たろう

Re:DirectXの描画について

#10

投稿記事 by たろう » 15年前

すみません。移動したときだけです。

たろう

Re:DirectXの描画について

#11

投稿記事 by たろう » 15年前

スレッドでやってみましたが、peekMessageを二つ使わないとできないのですが、一つでやるにはどうしたらいいでしょうか?できないのでしょうか?ソース載せます。
.
           .
           .
    // メイン メッセージ ループ:
    CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)sub,NULL,0,&ThreadId_0);
    int flag;
    
    do{
        if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
        {
            if((flag=GetMessage(&msg,NULL,0,0))==0||flag==-1)
            {
                break;
            }
                TranslateMessage( &msg );
                DispatchMessage( &msg );
        }
    }while(1);
    return 0;
DWORD WINAPI sub(void)
{
    EnterCriticalSection( &Critical_Se );// クリティカルセッション開始
    int bit;
    MSG msg = {0};
    
    do{
        if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
        {
            if((bit=GetMessage(&msg,NULL,0,0))==0||bit==-1)
            {
                break;
            }
                TranslateMessage( &msg );
                DispatchMessage( &msg );
        }
        else
        {
            RenderScene();  // Do some rendering
        }
    }while( WM_QUIT != msg.message );
    LeaveCriticalSection( &Critical_Se );//クリティカルセッション終了

    return 0;
}
とやらなくてはいけないのですがこれをPeekMessage()を一回ですることはできるのでしょうか?
よろしくお願いします。

シエル

Re:DirectXの描画について

#12

投稿記事 by シエル » 15年前

私はバックグラウンドを白にして移動してもチカチカはしませんね。
画面の外にウィンドウを持っていったときは、その部分は白くなってしまいますが。
なので私はNULLにしています。
これが正しい方法かは分かりませんが、私はあまり気にしていませんので、そう対応しています。

>>PeekMessage()を一回ですることはできるのでしょうか?
え~なぜスレッドの処理でもpeekmessageを使ってるんですか?
二回使わなければいけないと思ってる理由を具体的にお答え下さい。

たろう

Re:DirectXの描画について

#13

投稿記事 by たろう » 15年前

すみません。スレッドにPeekMessage()を使わなくてもできました。
[/pre]do{
if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
if((flag=GetMessage(&msg,NULL,0,0))==0||flag==-1)
{
break;
}
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else
{
Recnder()
}
}while(1);[/pre]
みたいにする画面を外に移動するとその分だけいろんなものが重なって表示されるという現象が起きるのですがこれはしかたのないことなのでしょうか?

シエル

Re:DirectXの描画について

#14

投稿記事 by シエル » 15年前

状況が良く分からないので、その上記二なったときの画面ショットを添付していただけると助かります。
それで、結局スレッドを使って描画するのはやめたのですか?

たろう

Re:DirectXの描画について

#15

投稿記事 by たろう » 15年前

返信ありがとうございます。いや、スレッド処理もやめていないです。ただ、先ほどの方法でできないのかと思い聞きました。この画像のようにならないようにすることはできるんでしょうか?
スレッドじゃない方法は、以下のとおりです。
do{
        if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
        {
            if((flag=GetMessage(&msg,NULL,0,0))==0||flag==-1)
            {
                break;
            }
                TranslateMessage( &msg );
                DispatchMessage( &msg );
        }
        else
        {
            RenderScene();
        }
        
    }while(1);
それで、スレッドの処理は以下のとおりです。
DWORD WINAPI sub(void)
{
    EnterCriticalSection( &Critical_Se );// クリティカルセッション開始
    int flag;
    MSG msg = {0};
    
    do{ 
            RenderScene();
    }while( 1);
    LeaveCriticalSection( &Critical_Se );//クリティカルセッション終了

    return 0;
}
です。それとスレッドはこれでも大丈夫でしょうか?

シエル

Re:DirectXの描画について

#16

投稿記事 by シエル » 15年前

ん?メッセージループの中での描画だけで、画像のようになるんですか?
それともスレッドでの描画も同時に行うと画像のようになるんですか?
クリティカルセクションの意味分かってますか?

それと、Sleepを適度に入れないと、超高速ループになってしまうので、
入れるべきですよ。(これが原因かも)

たろう

Re:DirectXの描画について

#17

投稿記事 by たろう » 15年前

>メッセージループの中での描画だけで、画像のようになるんですか?
そうです。
クリティカルセッションならわかります。同期を取るんですよね。
Sleepやってみましたがだめでした。

たろう

Re:DirectXの描画について

#18

投稿記事 by たろう » 15年前

while(1)
if(PeekMessage(...))
{
....
}
else
{
Render()
}
ではできないのでしょうか?

たろう

Re:DirectXの描画について

#19

投稿記事 by たろう » 15年前

わかるかたいらしたらよろしくご教授お願いします。

たろう

Re:DirectXの描画について

#20

投稿記事 by たろう » 15年前

やっぱりできないのでしょうか・・・

ideyan

Re:DirectXの描画について

#21

投稿記事 by ideyan » 15年前

>画面を掴んでいる間は、ウィンドウプロシージャが処理中だからではないでしょうか?
とシエルさんも仰っていますが
while(1)  
if(PeekMessage(...))  
{  
....  
}  
else  
{  
   Render()  
}
の形式に固執する限りはずっとifの方の式が実行されて
描画はされないと思います。

たろう

Re:DirectXの描画について

#22

投稿記事 by たろう » 15年前

返信誠にありがとうございます。ウィンドウプロシージャが処理をしているからと言うのは聞きました。やっぱり無理があるのでしょうか?
それだけが知りたいです。

シエル

Re:DirectXの描画について

#23

投稿記事 by シエル » 15年前

いや、ですので、スレッドでの描画を提案したのですが?

たろう

Re:DirectXの描画について

#24

投稿記事 by たろう » 15年前

そうなんですか(汗)できないということでいいんですね!すっきりしました。回答してくださた方誠にありがとうございました。

たろう

Re:DirectXの描画について

#25

投稿記事 by たろう » 15年前

解決しました。

ISLe

Re:DirectXの描画について

#26

投稿記事 by ISLe » 15年前

できないということで決着してしまったみたいですが…。

ウインドウ内部に引きずったあとが残るのは、WM_ERASEBKGNDメッセージに対してウインドウのクライアント領域の背景が消去されないからです。
WM_ERASEBKGNDメッセージはデフォルトでウインドウクラスに設定された背景ブラシでクライアント領域全体を塗りつぶします。
質問者さんは背景ブラシをNULLに設定しているので結果的に塗りつぶしが行われません。

対応としては、
・ウインドウのドラッグが開始されたらメインの描画を停止
・WM_ERASEBKGNDメッセージのイベント応答としてクライアント領域に描画
・ウインドウのドラッグが終了したらメインの描画を再開
というふうにします。

Direct3DデバイスからGDI下のクライアント領域には描画できないのでひと工夫してください。
#WM_PAINTで描画しても変わらないのは↑と同じ理由です。

ISLe

Re:DirectXの描画について

#27

投稿記事 by ISLe » 15年前

失礼しました。
WM_PAINTで描画すれば上手くいくと書いてありましたね。

消去を要求するためにWM_ERASEBKGNDメッセージ、描画を要求するためにWM_PAINTメッセージが飛んでくるので適切に対応するしかありません。
ウインドウメッセージが来ないときに描画するだけではウインドウメッセージに対応できません。
フルスクリーンモードではうまく行ってもウインドウモードではボロが出てしまいます。

システムのプロパティの視覚効果の『ドラッグ中にウインドウの内容を表示する』が有効かどうかで動作が変わります。

たろう

Re:DirectXの描画について

#28

投稿記事 by たろう » 15年前

レスありがとうございます。
やっぱりそうですか。。。
>システムのプロパティの視覚効果の『ドラッグ中にウインドウの内容を表示する』が有効かどうかで動作が変わります。
はどうやって設定すればよいのでしょうか?

ISLe

Re:DirectXの描画について

#29

投稿記事 by ISLe » 15年前

> >システムのプロパティの視覚効果の『ドラッグ中にウインドウの内容を表示する』が有効かどうかで動作が変わります。
> はどうやって設定すればよいのでしょうか?

XPの場合、
マイコンピュータのプロパティ→詳細設定タブ→パフォーマンスの設定ボタン→
Vista/7の場合、
コンピュータのプロパティ→システムの詳細設定→パフォーマンスの設定ボタン→

ラジオボタンでカスタムにして『ドラッグ中にウインドウの内容を表示する』のチェックを外す

ウインドウのドラッグ中は枠だけが表示されるようになります。

スレッドで描画するとどこに表示されるのか確認したことなかったです。
画面は更新されなくなるかも。

たろう

Re:DirectXの描画について

#30

投稿記事 by たろう » 15年前

レスありがとうございます。
>スレッドで描画するとどこに表示されるのか確認したことなかったです。
画面は更新されなくなるかも。
スレッドでやりましたが描画はちゃんとされていました。

閉鎖

“C言語何でも質問掲示板” へ戻る