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!