Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

27.02.2008, 21:22

Vollbildmodus: Nach dem Switchen kein Bild mehr

Hallo!

Ich bastel gerade an einem kleinen DirectX 9 Projekt (mit Hilfe des Buches 3D Spieleprogrammierung). Dabei trat folgendes Problem auf:
Wenn ich das Programm im Vollbildmodus starte läuft alles ganz normal (im Moment zeigt er mir nur einen rötlichen Hintergrund, alles andere hab ich schon auskommentiert um Fehlerquellen auszuschließen). Wechsel ich aber einmal zu Windows und zurück, erhalte ich nurnoch ein weißes Windowsfenster über den ganzen Bildschirm (halt auch mit Leiste oben wo man minimieren, schließen und so kann).
Starte ich das Ganze im Fenstermodus, kann ich switchen soviel ich will, das Programm zeigt nacher immernoch den rötlichen Hintergrund.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void beginRender(D3DCOLOR backgroundColor)
{
    if( NULL == direct3dDevice  ) return;

    direct3dDevice ->Clear( 0,
                            NULL,
                            D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
                            backgroundColor,
                            1.0f,
                            0);

    direct3dDevice ->BeginScene();
}

void endRender()
{   
    direct3dDevice ->EndScene();
    direct3dDevice ->Present( NULL, NULL, NULL, NULL );
}


In der WinMain wird dann (außer dem üblichen) nichts weiter gemacht als diese beiden Funktionen aufzurufen.
Aber wenn die Initialisierung von DirectX falsch wäre, würde es ja schon vor dem Switchen Probleme geben.
Hat jemand ne Idee wo genau der Fehler liegen könnte? Oder muss ich nach dem Switchen bestimmte Dinge neu initialisieren?

(bzw, falls das eher ins Buch-Forum gehört weil ich damit gerade arbeite, dann bitte dahin verschieben oder so)

2

27.02.2008, 21:28

Re: Vollbildmodus: Nach dem Switchen kein Bild mehr

Zitat von »"CoB-Twister"«

Oder muss ich nach dem Switchen bestimmte Dinge neu initialisieren?

Ja musst du wohl oder übel. Klassischer Fall von LostDevice und ResetDevice.
Also deine InitDevice-Funktion nach dem Switchen nochmals ausführen. Ggf. Ressourcen neu laden.

3

27.02.2008, 22:00

Also ich hab eine Funktion, die jedesmal aufgerufen wird, wenn mein Fenster nach dem Wechsel wieder aktiviert wird (brauchte ich schon, um mir Maus Und Tastatur zurückzuholen). Der habe ich jetzt folgenden Code beigefügt:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
direct3dDevice  = NULL;
    direct3d = Direct3DCreate9( D3D_SDK_VERSION );

    D3DPRESENT_PARAMETERS d3dpp; 
    ZeroMemory( &d3dpp, sizeof(d3dpp) );
    d3dpp.Windowed = false;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat = D3DFMT_R5G6B5;
    d3dpp.BackBufferCount  = 1;
    d3dpp.BackBufferHeight = wndHeight;
    d3dpp.BackBufferWidth  = wndWidth;
    d3dpp.hDeviceWindow    = wndHandle;
    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
    d3dpp.EnableAutoDepthStencil = TRUE;
    d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
    d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;

    direct3d->CreateDevice( D3DADAPTER_DEFAULT,
                            D3DDEVTYPE_HAL,
                            wndHandle,
                            D3DCREATE_HARDWARE_VERTEXPROCESSING,
                            &d3dpp,
                            &direct3dDevice);

    direct3dDevice ->SetRenderState(D3DRS_NORMALIZENORMALS, TRUE);


Sind die selben Einstellungen mit denen ich auch am Anfang mein d3dDevice lade. Hat das Problem aber leider nicht gelöst, oder hab ich da was missverstanden?

4

27.02.2008, 22:16

Im Prinzip genügt es, wenn du die Presentparameters aktualisierst, und dann die Reset-Methode des Device aufrufst: direct3dDevice->Reset(&d3dpp)

5

27.02.2008, 22:34

Stimmt, die Schnittstelle hatte sich da beim Copy + Paste reingeschlichen. Ist jetzt draußen.
Auf Fehler hab ichs jetzt mal provisorisch so geprüft:

C-/C++-Quelltext

1
2
3
4
5
6
if(D3D_OK!=direct3d->CreateDevice( D3DADAPTER_DEFAULT,
                            D3DDEVTYPE_HAL,
                            wndHandle,
                            D3DCREATE_HARDWARE_VERTEXPROCESSING,
                            &d3dpp,
                            &direct3dDevice)) MessageBox(0,"fehlgeschlagen","Fehler",0);


Bekomme aber keine Nachricht, von daher scheint die Neuinitialisierung zu klappen. Die Funktion wird wie gesagt aufgerufen, sobald das Fenster wieder im Vordergrund ist. Das mache ich indem ich WM_ACTIVATE abfange. Im Fenstermodus klappt das, wird im Vollbildmodus evtl ne andere Nachricht gesendet auf die ich prüfen muss?

/edit:
Das Ganze sieht dann jetzt so aus )klappt leider auch nicht)

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
D3DPRESENT_PARAMETERS d3dpp; 
    ZeroMemory( &d3dpp, sizeof(d3dpp) );
    d3dpp.Windowed = false;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat = D3DFMT_R5G6B5;
    d3dpp.BackBufferCount  = 1;
    d3dpp.BackBufferHeight = wndHeight;
    d3dpp.BackBufferWidth  = wndWidth;
    d3dpp.hDeviceWindow    = wndHandle;
    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
    d3dpp.EnableAutoDepthStencil = TRUE;
    d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
    d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;

    direct3dDevice->Reset(&d3dpp);

6

27.02.2008, 22:41

Hab meinen letzten Post editiert.

WM_ACTIVATE funktioniert da glaube ich nicht mehr.
Verwende stattdessen (jedes Frame) direct3dDevice->TestCooperativeLevel()
Wenn der Rückgabewert (HRESULT) D3DERR_DEVICELOST ist, dann werde aktiv wie im editierten Post beschrieben.

7

27.02.2008, 22:45

Könnte auch am Backbuffer-Format liegen...

8

27.02.2008, 22:49

Die Renderfunktion sieht dann jetzt so aus:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
void beginRender(D3DCOLOR backgroundColor)
{
    HRESULT r = direct3dDevice->TestCooperativeLevel();
    if( r == D3DERR_DEVICELOST){
        D3DPRESENT_PARAMETERS d3dpp; 
        ZeroMemory( &d3dpp, sizeof(d3dpp) );
        d3dpp.Windowed = false; 
        d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; 
        d3dpp.BackBufferFormat = D3DFMT_R5G6B5; 
        d3dpp.BackBufferCount  = 1; 
        d3dpp.BackBufferHeight = wndHeight; 
        d3dpp.BackBufferWidth  = wndWidth; 
        d3dpp.hDeviceWindow    = wndHandle; 
        d3dpp.AutoDepthStencilFormat = D3DFMT_D16; 
        d3dpp.EnableAutoDepthStencil = TRUE; 
        d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; 
        d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; 

      direct3dDevice->Reset(&d3dpp);}

    direct3dDevice ->Clear( 0,
                            NULL,
                            D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
                            backgroundColor,
                            1.0f,
                            0);

    direct3dDevice ->BeginScene();
}


Leider funktionierts damit auch noch nicht. Kann das Problem evtl auch beim Fenster-Handle liegen?

/edit:

BackBuffer hab ich mal auf R8G8B8 gesetzt... bringt auch keine Besserung

9

27.02.2008, 22:56

TestCooperativeLevel würde ich irgendwo in den Messageloop packen. Außerhalb der Renderfunktion. Die so aufzuteilen (beginRender, endRender) würde ich nicht machen.
Am Fensterhandle liegt es wohl eher nicht.
Ansonsten poste mal den kompletten Code, dann kann ich dir wahrscheinlich sagen, wo das Problem ist.

Noch'n EDIT: :)
probier mal D3DFMT_X8R8G8B8

10

27.02.2008, 23:13

ok, dann hier mal der komplette Code:
(auskommentiertes lass ich mal gleich weg...)

WinMain:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
    init(hInstance, "Mein Fenster", 800, 600, false);

    MSG msg;
    ZeroMemory( &msg, sizeof(msg) );
    while( msg.message!=WM_QUIT )
    {
        if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
        {
            TranslateMessage( &msg );
            DispatchMessage( &msg );
        }
        else
        {
            beginRender(0x309932CC);
            endRender();
        }
    }

    releaseDX();

    return (int) msg.wParam;
}


die beginRender bzw endRender-Funktionen sehen wie oben aus (ob ich TestCooperativeLevel in beginRender packe, oder in der Schleife davor sollte jetzt noch keinen Unterschied machen). Fehlt noch die Init-Funktion:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
init(HINSTANCE hInstance,std::string WndName, ULONG WndWidth, ULONG WndHeight, bool windowed)
{
    WNDCLASSEX wcex;
    wndWidth = WndWidth;
    wndHeight = WndHeight;

    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = (WNDPROC)WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = 0;
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = NULL;
    wcex.lpszClassName  = WndName.c_str();
    wcex.hIconSm        = 0;
    RegisterClassEx(&wcex);

    DWORD style=WS_POPUP|WS_VISIBLE;

    style =  WS_OVERLAPPEDWINDOW;

    wndHandle = CreateWindow(WndName.c_str(), 
                             WndName.c_str(), 
                             style,
                             CW_USEDEFAULT, 
                             CW_USEDEFAULT, 
                             WndWidth, 
                             WndHeight, 
                             NULL, 
                             NULL, 
                             hInstance, 
                             NULL);
 
    hInst = hInstance;

    ShowWindow(wndHandle, SW_SHOW);
    UpdateWindow(wndHandle);

    direct3d = NULL;
    direct3dDevice  = NULL;

    direct3d = Direct3DCreate9( D3D_SDK_VERSION );

    D3DPRESENT_PARAMETERS d3dpp; 
    ZeroMemory( &d3dpp, sizeof(d3dpp) );
    d3dpp.Windowed = windowed;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
    d3dpp.BackBufferCount  = 1;
    d3dpp.BackBufferHeight = WndHeight;
    d3dpp.BackBufferWidth  = WndWidth;
    d3dpp.hDeviceWindow    = wndHandle;
    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
    d3dpp.EnableAutoDepthStencil = TRUE;
    d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
    d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;

    direct3d->CreateDevice( D3DADAPTER_DEFAULT,
                            D3DDEVTYPE_HAL,
                            wndHandle,
                            D3DCREATE_HARDWARE_VERTEXPROCESSING,
                            &d3dpp,
                            &direct3dDevice);

    direct3dDevice ->SetRenderState(D3DRS_NORMALIZENORMALS, TRUE);}


sowie die globalen Variablen (das wird später noch schöner verpackt in eine Klasse und so, aber im Moment müsste es so ja auch laufen)

C-/C++-Quelltext

1
2
3
4
5
6
LPDIRECT3D9                         direct3d;
    LPDIRECT3DDEVICE9                   direct3dDevice;
    HWND                                wndHandle;
    HINSTANCE                           hInst;
int                                 wndWidth;
    int                                 wndHeight;

Werbeanzeige