Maus reagiert sehr langsam



  • In meinen Direct3D-Programmen reagiert die Maus immer sehr träge. Allerdings nur im Vollbildmodus und mit eingeschalteter VSync. Habt ihr auch dieses Problem?



  • Nö, aber du kannst ja mal den Code posten (bitte nicht sparen).



  • Ok, hier ein kleines Beispiel. (Verwendet das DirectX9 SDK Update Summer 2004)

    #include <d3d9.h>
    #include <d3dx9.h>
    
    //--------------------------------------------------
    // Globale variablen
    //--------------------------------------------------
    
    // Fenster
    HWND mainwindow;
    
    // 3D
    LPDIRECT3D9 lpD3D;
    LPDIRECT3DDEVICE9 lpDevice;
    
    // Fonts
    LPD3DXFONT lpFont;
    
    // Mausposition
    int mx, my;
    POINT curPos;
    
    //--------------------------------------------------
    // Alles löschen
    //--------------------------------------------------
    void CleanUp( )
    {
    	// Devices löschen
    	if( lpDevice != NULL )
    	{
    		lpDevice->Release( );
    	}
    
    	if( lpD3D != NULL )
    	{
    		lpD3D->Release( );
    	}
    }
    
    //--------------------------------------------------
    // Tastaturabfrage
    //--------------------------------------------------
    bool KeyPressed( int key )
    {
    	short result = GetAsyncKeyState( key );
    
    	if( result & 0x8000 )
    		return true;
    
    	if( result & 0x0001 )
    		return false;
    
    	return false;
    }
    
    //--------------------------------------------------
    // Text
    //--------------------------------------------------
    void RenderText( int x, int y, char *text, D3DCOLOR color, bool shadow )
    {
    	RECT rc;
    
    	if( shadow == true )
    	{
    		rc.left = x+2;
    		rc.top = y+2;
    		lpFont->DrawText( NULL, 
    						  text, 
    						  -1, &rc, DT_CALCRECT, D3DCOLOR_XRGB( 0, 0, 0 ) );
    		lpFont->DrawText( NULL, 
    						  text, 
    						  -1, &rc, DT_CENTER, D3DCOLOR_XRGB( 0, 0, 0 ) );
    	}
    
    	rc.left = x;
    	rc.top = y;
    
    	lpFont->DrawText( NULL, 
    					  text, 
    					  -1, &rc, DT_CALCRECT, color );
    	lpFont->DrawText( NULL, 
    					  text, 
    					  -1, &rc, DT_CENTER, color );
    }
    
    //--------------------------------------------------
    // MessageHandler
    //--------------------------------------------------
    LRESULT CALLBACK MessageHandler( HWND hWnd, unsigned int message, WPARAM wParam, LPARAM lParam )
    {
    	switch( message )
    	{
    		case WM_MOUSEMOVE:
    			mx = LOWORD( lParam );
    			my = HIWORD( lParam );
    			break;
    
    		case WM_DESTROY:
    			CleanUp( );
    			PostQuitMessage( 0 );
    			break;
    	}
    
    	return DefWindowProc( hWnd, message, wParam, lParam );
    }
    
    //--------------------------------------------------
    // Init-Funktion
    //--------------------------------------------------
    void InitEverything( )
    {
    	// Fenster erstellen
    	WNDCLASSEX wndClass = { sizeof( WNDCLASSEX ), CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW, 
    							MessageHandler, 0, 0, GetModuleHandle( 0 ), 
    							NULL, LoadCursor( NULL, IDC_ARROW ), NULL, NULL, "WindowClass", NULL };
    
    	RegisterClassEx( &wndClass );
    
    	DWORD style = WS_VISIBLE | WS_POPUP;
    
    	RECT wndRect = {0,0,1024,768};
    	AdjustWindowRectEx( &wndRect, style, false, 0 );
    
    	mainwindow = CreateWindowEx( 0, "WindowClass", "DirectX9-Test", style, 0, 0, 
    					wndRect.right-wndRect.left, wndRect.bottom-wndRect.top, NULL, NULL, GetModuleHandle( 0 ), NULL );
    
    	// Device erstellen
    	lpD3D = Direct3DCreate9( D3D_SDK_VERSION );
    
    	D3DPRESENT_PARAMETERS PParams;
    	ZeroMemory( &PParams, sizeof( PParams ) );
    	PParams.BackBufferWidth = 1024;
    	PParams.BackBufferHeight = 768;
    	PParams.Windowed = false;
    	PParams.hDeviceWindow = mainwindow;
    	PParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
    	PParams.BackBufferFormat = D3DFMT_A8R8G8B8;
    	PParams.EnableAutoDepthStencil = true;
    	PParams.AutoDepthStencilFormat = D3DFMT_D24X8;
    
    	lpD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, mainwindow, 
    						 D3DCREATE_SOFTWARE_VERTEXPROCESSING, 
    						 &PParams, &lpDevice );
    }
    
    //--------------------------------------------------
    // Main-Funktion
    //--------------------------------------------------
    int WINAPI WinMain( HINSTANCE hInstance, 
    					HINSTANCE hPrevInstance, 
    					LPSTR lpCmdLine, 
    					int nShowCmd )
    {
    	InitEverything( );
    
    	// Text
    	D3DXCreateFont( lpDevice, 
    					30, 0, 0, 
    					1, false, DEFAULT_CHARSET, 
    					OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, 
    					DEFAULT_PITCH | FF_DONTCARE, 
    					"Tahoma", 
    					&lpFont );
    
    	MSG message;
    	ZeroMemory( &message, sizeof( message ) );
    
    	while( message.message != WM_QUIT )
    	{
    		if( PeekMessage( &message, NULL, 0, 0, PM_REMOVE ) )
    		{
    			TranslateMessage( &message );
    			DispatchMessage( &message );
    		}
    		else
    		{
    			// Text rendern
    			lpDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB( 127, 127, 127 ), 1.0f, 0 );
    			lpDevice->BeginScene( );
    
    			GetCursorPos( &curPos );
    			RenderText( curPos.x, curPos.y, "Problem ist nur mit eingeschalteter VSync sichtbar!", D3DCOLOR_XRGB( 255, 255, 255 ), true );
    
    			lpDevice->EndScene( );
    			lpDevice->Present( NULL, NULL, NULL, NULL );
    
    			// Programm bei Escape beenden
    			if( KeyPressed( VK_ESCAPE ) == true )
    			{
    				CleanUp( );
    				PostQuitMessage( 0 );
    			}
    
    		}
    	}
    
    	return 0;
    }
    


  • d3d = Direct3DCreate9(D3D_SDK_VERSION);
    
    	D3DFORMAT d3dFmt = D3DFMT_X8R8G8B8;
    
        d3dPP.Windowed                = false;
    	d3dPP.hDeviceWindow           = Window::getInstance().getHWnd();
        d3dPP.SwapEffect              = D3DSWAPEFFECT_DISCARD;
    	d3dPP.PresentationInterval    = D3DPRESENT_INTERVAL_DEFAULT;
        d3dPP.EnableAutoDepthStencil  = true;
        d3dPP.AutoDepthStencilFormat  = D3DFMT_D16;
        d3dPP.BackBufferFormat        = d3dFmt;
        d3dPP.BackBufferWidth         = GetSystemMetrics(SM_CXSCREEN);
    	d3dPP.BackBufferHeight        = GetSystemMetrics(SM_CYSCREEN);
    
    	d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, Window::getInstance().getHWnd(), D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dPP, &d3dDev);
    
    	d3dDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
    	d3dDev->SetRenderState(D3DRS_LIGHTING, FALSE);
    	d3dDev->SetRenderState(D3DRS_ZENABLE, TRUE);
    

    Und lass dir mal die FPS ausgeben...



  • Das Problem besteht immer noch, solange VSync an ist. Das Programm läuft mit
    60 FPS.



  • Ich habe deinen Code ausgefuhrt. Bemerkt habe ich lediglich die normale, minimale Verzögerung zwischen Mauszeiger und Text. Liegt wohl an deiner Hardware.



  • Ich hab eine Lösung gefunden:

    - Für das PresentationInterval D3DPRESENT_INTERVAL_IMMEDIATE angeben und
    - Sleep( 16 ) vor Present verwenden, um die Framerate bei ca. 60 FPS zu halten.

    Danke für deine Hilfe!



  • D3DPRESENT_INTERVAL_IMMEDIATE und Sleep( 16 ) vor Present

    schon mal ueberlegt, welche nachteile das haben koennte?



  • Nö, welche denn?



  • ProGamer.Coder schrieb:

    Nö, welche denn?

    Dein Rechner rendert das im null komma nix, d.h. ein Frame braucht so gut wie keine Zeit (16ms * 60frames = ~1000ms also 1Sekunde). Wenn es nun einen langsameren PC gibt, der sagen wir mal 5ms für ein Frame braucht, dann wären das 5ms + 16ms (sleep pro frame) = 21ms pro Frame und 21ms * 60frames = 1260ms, also würde er für die 60Frames 1,2Sekunden brauchen (wären also nur 50FPS bei diesem Rechner).



  • Danke, klingt plausibel.
    Aber wie bekomme ich denn eine Framerate von 60 fps bei deaktivierter VSync?



  • Hoffe das hilft..

    int Framerate = 60;
    
    LONGLONG Frequency; // Frequenz des Counters
    LONGLONG Offset;    // Abstand zwischen den Frames
    LONGLONG NextFrame; // Zeit bis zum nächsten Frame
    LONGLONG CurCount;  // aktueller Zählerstand 
    
    // Windows main-Funktion
    int WINAPI WinMain(HINSTANCE hInstance,      
                       HINSTANCE hPrevInstance,  
                       LPSTR lpCmdLine,          
                       int nCmdShow)             
    {   
        MessageBox(0,"Dieses Programm zeigt, wie die Framerate auf einen festen Wert "
                     "gesetzt wird.\nDie Framerate kann mit den Tasten '+' und '-' "
                     "erhöht und erniedrigt werden.","FixedFrameRate",MB_OK);
    
        // Fenster erzeugen und Handle speichern
        hWnd = CreateMainWindow(hInstance);
    
        // Wenn der Rückgabewert 0 ist, ist ein Fehler aufgetreten
        if(0 == hWnd)
        {
            MessageBox(0,"Fenster konnte nicht erzeugt werden","Fehler",MB_OK);
            return -1;
        }
    
        // Direct3D initialisieren
        if(!Direct3D.Init(hWnd,FALSE))
        {
            return -1;
        }
    
        ResourceManager.Init(Direct3D.GetDevice());
    
        // Maus-Cursor verstecken
        ShowCursor(FALSE);
    
        // Farbe die beim Löschen verwendet werden soll
        Direct3D.SetClearColor(D3DCOLOR_XRGB(0,0,0));
    
        int i;
    
        // Zufallsgenerator initialisieren
        srand(timeGetTime());
    
        // Grafiken (Texturen) laden
        char Filename[128];
    
        // Frequenz speichern, wenn Counter vorhanden
        if(!QueryPerformanceFrequency(
                       (LARGE_INTEGER*)&Frequency))
        {
            MessageBox(0,"Performancecounter nicht vorhanden.","Fehler",MB_OK);
            return -1;
        }
    
        // Abstand zwischen zwei Frames berechnen
        Offset = Frequency / Framerate;
    
        // aktuellen Zählerstand Zeit speichern
        QueryPerformanceCounter((LARGE_INTEGER*)&CurCount);
    
        // berechnen wann nächstes Frame dargestellt wird 
        NextFrame = CurCount + Offset;
    
        // Struktur, in der Informationen zur Nachricht gespeichert werden
        MSG msg = { 0 };
    
        while(msg.message != WM_QUIT)
        {
            if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
            else
            {
                // aktuellen Zählerstand holen
                QueryPerformanceCounter((LARGE_INTEGER*)&CurCount);
    
                // wenn es Zeit für das nächste Frame ist
                if(CurCount > NextFrame)
                {
                    Direct3D.BeginScene();
    
                    Direct3D.EndScene();
    
                    // Abstand zum nächsten Frame berechnen
                    NextFrame = CurCount + Offset;
                }
            }
        }
    
        // Rückgabewert an Windows
        return 0;
    }
    


  • Danke, Kuldren!


Anmelden zum Antworten