Page 1 of 2 12 LastLast
Results 1 to 10 of 12

Thread: Constant frame rate aka limit FPS

  1. #1

    Question Constant frame rate aka limit FPS

    I wonder how to limit FPS into simple 60 since now the game takes to much processor usage on Windows.

  2. #2
    This depends on the graphics library you are using.
    If you are using SDL, you might want to take a look at SDL_gfx which has some nice frame regulation functions or you may try to implement them yourself like described here: http://lazyfoo.net/SDL_tutorials/lesson14/index.php (It's C++-Code but it's relatively easy to port this to Object Pascal.)

    Edit: Sorry, I just noticed this was posted in the ZenGL forums. So my answer won't help you.
    Last edited by Stoney; 05-02-2011 at 07:00 PM.
    Freeze Development | Elysion Game Framework | Twitter: @Stoney_FD
    Check out my new book: Irrlicht 1.7.1 Realtime 3D Engine Beginner's Guide (It's C++ flavored though)

    Programmer: A device for converting coffein into software.

  3. #3
    Nah, not dependent on graphics library. I've found easiest way to insert TTimer on form with interval 17. It will be smooth, save your cpu and gpu and be very close to 60 fps.

  4. #4
    You might be interested in this post: http://www.pascalgamedevelopment.com...ll=1#post52894

    and perhaps a few above it

  5. #5
    Well actually you don't need to convert any C++ code. There is good examples of limiting FPS using SDL_Delay(); in JEDI-SDL package,SDLSpriteEngine demos folder.

  6. #6
    Quote Originally Posted by dazappa View Post
    You might be interested in this post: http://www.pascalgamedevelopment.com...ll=1#post52894

    and perhaps a few above it
    Yeah I can say that VSync may work with not all video drivers. I don't see any effect when I turn on .

    With VSync: [00010966ms] Average FPS: 459
    Without VSync : [00014209ms] Average FPS: 458


    BTW, ZGL IDE is really neat idea.

  7. #7
    Quote Originally Posted by gintasdx
    Yeah I can say that VSync may work with not all video drivers. I don't see any effect when I turn on
    Only if this drivers configured to do not use VSync, or if drivers just a cr*p

    Quote Originally Posted by gintasdx
    There is good examples of limiting FPS using SDL_Delay()
    SDL_Delay is not good idea because it's just a Sleep function under Windows, and it far from "constant value". But yeah, you can limit your fps to ~61 with this function.

  8. #8
    Quote Originally Posted by Andru View Post
    Only if this drivers configured to do not use VSync, or if drivers just a cr*p
    Well I found the solution. Seems DirectX9 version of this engine works just fine with VSync. It gives around
    55 FPS DirectX8 only about 28FPS with VSync. With OpenGL I only could get stable 60FPS with VSync in fullscreen mode,but on Linux everything is fine with the latest Intel drivers.

  9. #9
    Some old code that I've used in my projects, not sure where it originally came from...

    Code:
    unit glThread;
    
    interface
    
    uses
    	Forms, Windows, Classes, MMSystem;
    
    type
    	TThreadProcedure  = procedure of object;
    
    	TGLDrawEvent = procedure(Sender: TObject) of object;
    
    	TGLRunThread = class(TThread)
    	private
    		FIsTerminated: Boolean;
    		fAverageDrawList  : TList;
    		fAverageDrawTime  : single;
    		fFrameRate        : single;
    		fIdleTime         : Single;
    		fAverageIdleTime  : single;
    		fMaxFrameRate     : integer;
    		fThreadProc       : TThreadProcedure;
    		fGLPriority       : TThreadPriority;
    		fUnlimited        : boolean;
    		FrameCount  : integer;
    		FrameTicks  : Single;
    		procedure   SetfGLPriority  (Value : TThreadPriority);
    		procedure DoIt;
    	protected
    		QPFrequency: Int64;
    		QPCurrentTime: Int64;
    		QPLastTime: Int64;
    		QPEnabled: Boolean;
    		procedure   Execute;        override;
    		function GetTime: Single;
    	public
    		constructor Create          (CreateSuspended : boolean; ThreadProc : TThreadProcedure);
    		destructor  Destroy;        override;
    		property    GLPriority      : TThreadPriority   read fGLPriority write SetfGLPriority;
    		property    ThreadProc      : TThreadProcedure  write fThreadProc;
    		property    IdleTime        : Single           read fIdleTime;
    		property    AverageDrawTime : single            read fAverageDrawTime;
    		property    AverageIdleTime : single            read fAverageIdleTime;
    		property    FrameRate       : single            read fFrameRate;
    		property    MaxFrameRate    : integer           read fMaxFrameRate write fMaxFrameRate;
    		property    Unlimited       : boolean           read fUnlimited write fUnlimited;
    		property IsTerminated: Boolean read FIsTerminated;
    	end;
    
    	TGLThread = class(TComponent)
    	private
    		procedure ThreadProc;
    	protected
    		RunThread: TGLRunThread;
    		FOnDraw: TGLDrawEvent;
    		function GetAverageDrawTime: Single;
    		function GetFrameRate: Single;
    		function GetMaxFrameRate: Integer;
    		procedure SetMaxFrameRate(Value: Integer);
    		function GetRunning: Boolean;
    		function GetUnlimited: Boolean;
    		procedure SetUnlimited(Value: Boolean);
    	public
    		constructor Create(AOwner: TComponent); override;
    		destructor Destroy; override;
    		procedure Start;
    		procedure Stop;
    
    		property FrameRate: Single read GetFrameRate;
    		property AverageDrawTime: Single read GetAverageDrawTime;
    		property Running: Boolean read GetRunning;
    	published
    		property OnDraw: TGLDrawEvent read FOnDraw write FOnDraw;
    		property MaxFrameRate: Integer read GetMaxFrameRate write SetMaxFrameRate;
    		property Unlimited: Boolean read GetUnlimited write SetUnlimited;
    	end;
    
    procedure Register;
    
    implementation
    
    procedure Register;
    begin
    	RegisterComponents('OpenGL', [TGLThread]);
    end;
    
    {---------------------------------------------------------------------------
    -----------------------}
    
    function TGLRunThread.GetTime: Single;
    var
    	Time: Int64;
    begin
    	QueryPerformanceCounter(Time);
    	Result := (Time / QPFrequency);
    end;
    
    //TThreadPriority = (tpIdle, tpLowest, tpLower, tpNormal, tpHigher, tpHighest, tpTimeCritical);
    
    constructor TGLRunThread.Create(CreateSuspended : boolean; ThreadProc : TThreadProcedure);
    begin
      inherited Create(CreateSuspended);
      fAverageDrawList  := TList.Create;
      fFrameRate        := 0;
      fMaxFrameRate     := 60;                                              // Need a frame rate of 60 frames / second.
      fThreadProc       := ThreadProc;
      //FreeOnTerminate   := true;
      FreeOnTerminate   := FALSE;
      //GLPriority        := tpIdle;
      GLPriority        := tpNormal;
      fUnlimited        := false;
      FIsTerminated := FALSE;
      QueryPerformanceFrequency(QPFrequency);
    end; {constructor}
    
    {---------------------------------------------------------------------------
    -----------------------}
    
    destructor TGLRunThread.Destroy;
    begin
      fAverageDrawList.Free;
      inherited;
    end; {destructor}
    
    {---------------------------------------------------------------------------
    -----------------------}
    
    procedure TGLRunThread.SetfGLPriority(Value : TThreadPriority);
    begin
      if (fGLPriority <> Value) then begin
    	 fGLPriority := Value;
    	 Priority    := fGLPriority;
      end; {if}
    end; {SetfGLPriority}
    
    {---------------------------------------------------------------------------
    -----------------------}
    
    procedure TGLRunThread.Execute;
    begin
    	FIsTerminated := FALSE;
    	FrameCount  := 0;                                                     // Used to get the frame rate.
    	FrameTicks  := GetTime;
    	while not Terminated do begin
    		//Synchronize(DoIt);
    		DoIt;
    	end; {while}
    	FIsTerminated := TRUE;
    end; {Execute}
    
    procedure TGLRunThread.DoIt;
    {...........................................................................
    .....................}
    
    function AverageTime(TimeList : TList; TimeValue : Single; Samples : integer) : single;
      var
    	 lp1 : integer;
      begin
    	 TimeList.Add(Pointer(TimeValue));
    	 if (TimeList.Count > Samples) then
    		TimeList.Delete(0);
    	 Result  := 0;
    	 for lp1 := 0 to pred(TimeList.Count) do
    		Result  := Result + Single(TimeList[lp1]);
    	 Result  := Result / TimeList.Count;
      end; {AverageTime}
    
    {...........................................................................
    .....................}
    
    var
      StartTicks  : Single;
      DrawTime    : Single;
    begin
    	 //StartTicks        := GetTickCount;                                  // Get the start time.
    	 StartTicks        := GetTime;                                  // Get the start time.
    	 if Assigned(fThreadProc) then                                       // Do the drawing ...
    		Synchronize(fThreadProc);                                         // <------- The main draw routine
    	 //DrawTime          := Integer(GetTickCount-StartTicks);              // Get the draw time.
    	 DrawTime          := (GetTime-StartTicks);              // Get the draw time.
    
    	 fAverageDrawTime  := AverageTime(fAverageDrawList, DrawTime, 50);   // Work out the average draw time.
    
    	 if fUnlimited then begin                                            // Frame rate limited ?
    		fIdleTime         := 0;                                           // Set these to zero ... then ignore.
    		fAverageIdleTime  := 0;
    	 end else begin
    		fIdleTime         := (1/fMaxFrameRate) - DrawTime;        // Idle time is the difference between the
    		fAverageIdleTime  := 1/fMaxFrameRate - fAverageDrawTime;       // wanted frame duration and the draw time.
    	 end; {if}
    
    	 if (fIdleTime > 0) then                                             // If there is some idle time then delay
    		Sleep(Round(fIdleTime * 1000));                                                 // for the idle time by sleeping.
    
    	 inc(FrameCount);                                                    // Work out the frame rate ... effectively
    	 if (StartTicks - FrameTicks > 1) then begin                      // sample every second and count the number
    		fFrameRate  := (1*FrameCount) / (StartTicks-FrameTicks);       // of frames.
    		FrameCount  := 0;
    		//FrameTicks  := GetTickCount;
    		FrameTicks  := GetTime;
    	 end; {if}
    
    
    end;
    
    {---------------------------------------------------------------------------
    -----------------------}
    {ajGLThread}
    
    constructor TGLThread.Create(AOwner: TComponent);
    begin
    	inherited;
    	RunThread := TGLRunThread.Create(TRUE, ThreadProc);
    end;
    
    destructor TGLThread.Destroy;
    begin
    	Stop;
    	RunThread.Free;
    	inherited;
    end;
    
    function TGLThread.GetAverageDrawTime: Single;
    begin
    	Result := RunThread.AverageDrawTime;
    end;
    
    function TGLThread.GetFrameRate: Single;
    begin
    	Result := RunThread.FrameRate;
    end;
    
    function TGLThread.GetMaxFrameRate: Integer;
    begin
    	Result := RunThread.MaxFrameRate;
    end;
    
    procedure TGLThread.SetMaxFrameRate(Value: Integer);
    begin
    	RunThread.MaxFrameRate := Value;
    end;
    
    function TGLThread.GetRunning: Boolean;
    begin
    	Result := not RunThread.IsTerminated;
    end;
    
    function TGLThread.GetUnlimited: Boolean;
    begin
    	Result := RunThread.Unlimited;
    end;
    
    procedure TGLThread.SetUnlimited(Value: Boolean);
    begin
       RunThread.Unlimited := Value;
    end;
    
    procedure TGLThread.Start;
    begin
    	RunThread.Resume;
    end;
    
    procedure TGLThread.Stop;
    begin
    	if not RunThread.IsTerminated then
    	begin
    		RunThread.Terminate;
    		RunThread.WaitFor;
    	end;
    end;
    
    procedure TGLThread.ThreadProc;
    begin
    	if Assigned(FOnDraw) then
    		FOnDraw(Self);
    end;
    
    end.

  10. #10
    The Asphyre Sphinx seems to have a nice way to limit FPS without using a sleep function. Anyways VSync helps to avoid tearing,but I rarely see a games that has it turned on by default. And I wonder does anyone tried the way from GameDev.net

Page 1 of 2 12 LastLast

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •