1

I have an OpenGL window within my Delphi application, which I want to render with fixed or uncapped FPS, depending on the choice of the user. Rendering the window every (e.g. 30 FPS) seems to work, what doesn't work is computing these FPS and displaying it. This is weird, since it works for the uncapped part. Here is the code, I also tried it with TStopWatch, but I am running into the same issue, which I explain below.

procedure TFoMain.IdleHandler(Sender: TObject; var Done: Boolean);
begin
  if Self.FPS <> 0 then begin
    if (GetTickCount - PrevTime >= (1000 / FPS)) then begin
      StartTime := GetTickCount;
      Render();
      PrevTime := GetTickCount;
      DrawTime := PrevTime - StartTime;
      Inc(TimeCount, DrawTime);
      Inc(FrameCount);
    end;
  end

  else begin
    StartTime := GetTickCount;
    Render();
    PrevTime := GetTickCount;
    DrawTime := PrevTime - StartTime;
    Inc(TimeCount, DrawTime);
    Inc(FrameCount);
  end;

  if (TimeCount >= 1000) then begin
    Frames := FrameCount;
    TimeCount := TimeCount - 1000;
    FrameCount:= 0;
  end;

  Done := false;
end;

As for the FPS variable, I define frames to be uncapped when FPS is set to 0. Here is the issue that I am having: In uncapped FPS-mode, everything works fine, but as soon as I switch to capped FPS, for some reason StartTime and PrevTime is always equal, therefore DrawTime becomes 0. This leads to the fact, that TimeCount does not increase and I never get into the if-condition, in which I check whether TimeCount >= 1000 and set the Frames variable, which I am displaying in my window.

I am very confused, since for uncapped and capped FPS it is the same exact code snippet, how can I get such different values for these variables? I thought maybe it is an issue with GetTickCount, but it's not, since I am getting the same outcome with TStopWatch.

Can someone please tell me what I am doing wrong or how to do it correctly?

Phil
  • 11
  • 2
  • What is `DrawTime` in the uncapped mode? GetTickCount only has resolution of 1ms, so if `Render` is faster than that you will find the time delta to be zero. It should be the same for both branches, however, assuming you're rendering the same thing. Note that GetTickCount rolls over at 2^32, so not correcting for this is a bug. `TStopwatch` is a better solution. – J... Apr 29 '21 at 17:43
  • How do you limit FPS in your case? Nothing in your shown code suggest this capability. Most commonly FPS are limited by measuring how much time was needed to render last frame and then wait enough time before render cycle beings. So you calculate wait time by using `WaitTime := (1000 / FPS) - RenderTime`. – SilverWarior Apr 29 '21 at 23:23

1 Answers1

0

I can't explain why you are seeing different operation when FPS is set to zero, but as you point out that PrevTime and StartTime come out the same I would try a different approach:

Initialise NextTick and TimeStart to 0

procedure TFoMain.IdleHandler(Sender: TObject; var Done: Boolean);
begin
  ThisTick:=GetTickCount();
  if(TimeStart=0) then TimeStart:=ThisTick;

  if ((Self.FPS=0) Or (ThisTick>=NextTick)) then begin
    Render();
    Inc(FrameCount);
    if(FPS<>0) then NextTick:=ThisTick+(1000/FPS);
  end;

  if(GetTickCount()-TimeStart>=1000) then begin
    Frames := FrameCount;
    TimeStart:=TimeStart+1000;
    FrameCount:=0;
  end;

  Done := false;
end;

This ignores the elapsed time, and instead uses the GetTickCount to respond at the appropriate times. As pointed out in the comments to your OP this does not account for wrapping of GetTickCount()!

Rob Lambden
  • 2,175
  • 6
  • 15