Frameratenbegrenzung: Unterschied zwischen den Versionen

Aus DGL Wiki
Wechseln zu: Navigation, Suche
K (Die naive Lösung)
K (Der Ausdruck ''<pascal>(.*?)</pascal>'' wurde ersetzt mit ''<source lang="pascal">$1</source>''.)
Zeile 11: Zeile 11:
  
 
==Implementierung==
 
==Implementierung==
<pascal>
+
<source lang="pascal">
 
var
 
var
 
   FMaximumFrameRate: double;
 
   FMaximumFrameRate: double;
Zeile 28: Zeile 28:
 
     FLastSleep := 0;
 
     FLastSleep := 0;
 
end;
 
end;
</pascal>
+
</source>
  
 
==Siehe auch==
 
==Siehe auch==

Version vom 10. März 2009, 19:04 Uhr

Problemstellung

Bei vielen 3D-Anwendungen erfolgt die Bildausgabe so schnell hintereinander, wie die Hardware dies ermöglicht. Das bedeutet aber auch, dass die Auslastung des Computersystems auf 100% ansteigt. Das wiederum benötigt jede Menge Strom.
Unser Auge wiederum nimmt eine Bewegung ab ca. 20 Bildern pro Sekunde als flüssig wahr - es bringt also nicht sehr viel, wenn unsere Anwendung mit mehr als 1000FPS läuft - wir bekommen davon sowieso nichts mit, außer niedriger Akkulaufzeit und hoher Stromrechnung. Die Lösung für dieses Problem ist eine Frameratenbegrenzung, die die Bildwiederholrate auf einen gewissen Wert limitiert und unsere Anwendung in der Zeit, in der nichts getan werden muss schlafen legt.

Ansatz

Die naive Lösung

Die einfachste Realisierung der Frameratenbegrenzung ist ein einfaches Hinzufügen der "Sleep" Anweisung in die Hauptschleife. Gehen wir von Sleep(5) aus, so haben wir eine Maximale Framerate von 200FPS. Diese Lösung ist jedoch etwas suboptimal. Gehen wir davon aus, dass das Zeichnen der Inhalte an sich schon 5 Millisekunden dauert, so haben wir nur noch eine Framerate von 100FPS. Auf einem älterem Rechner könnte diese Berechnung auch länger dauern und die erreichte Framerate sich daher noch mehr von unserem anvisierten Wert entfernen.

Die intelligente Lösung

Schlauer ist es, von der Zeit, die unser Programm pausiert, die Dauer des Rendervorgangs abzuziehen. Dazu ist es nötig, die Zeit, die zwischen zwei Frames vergeht zu messen. Um die Schlafenszeit nicht in dieser Messung zu haben, müssen wir uns diese natürlich merken und vorher abziehen. Mit diesem Ansatz passt sich die CPU-Auslastung an die Leistung des Systems an: Auf einem High-End PC wird sie automatisch niedriger als auf einem Rechner aus dem letztem Jahrhundert - so gehört es sich schließlich auch.

Implementierung

var
  FMaximumFrameRate: double;
  FLastSleep: double = 0;

procedure LimitFrameRate(atd: double); //"atd" ist die Zeitdifferenz zwischen zwei Frames - inklusive der "Sleeptime"
var
  sleeptime: Double;
begin
  sleeptime := 1000 / FMaximumFrameRate - (atd - FLastSleep);
  if sleeptime > 0 then
  begin
    Sleep(trunc(sleeptime));
    FLastSleep := sleeptime;
  end else
    FLastSleep := 0;
end;

Siehe auch

Framecounter