1

I have a short question. I am learning SFML and I made few apps by using it. Someday I learned about using fixed time step while coding games and it would be great if it worked. BUT. Even though I am making simple project like square moving from left to right side of the window - it is lagging! What could be a cause of this problem? This is my code:

#include <SFML/Graphics.hpp>

int main()
{
    sf::RenderWindow window(sf::VideoMode(800, 600), "Window");
    window.setVerticalSyncEnabled(true);
    sf::Event event;
    sf::Clock clock;
    sf::Time accumulator = sf::Time::Zero;
    const sf::Time timePerFrame = sf::seconds(1.f / 60.f);
    sf::RectangleShape square;
    square.setSize(sf::Vector2f(32, 32));
    square.setOrigin(16, 16);
    square.setPosition(400, 300);
    square.setFillColor(sf::Color::Red);
    int direction = 1;
    int speed = 300;
    while(window.isOpen())
    {
        while(window.pollEvent(event))
        {
            if(event.type == sf::Event::Closed)
            {
                window.close();
            }
        }
        while(accumulator >= timePerFrame)
        {
            if(square.getPosition().x <= 16 || square.getPosition().x >= 784) direction *= (-1);
            square.move(sf::Vector2f(speed * direction * timePerFrame.asSeconds(), 0));
            accumulator -= timePerFrame;
        }
        accumulator += clock.restart();
        window.clear(sf::Color::Black);
        window.draw(square);
        window.display();
    }
    return 0;
}

As you can see I know about vertical synchronization, but it doesnt help so much. Is my fixed time step loop wrong? Any help is appreciated!

1 Answers1

1

Have you tried not enabling vertical sync? Both vertical sync and the timestep you have implemented may interfere with each other by both trying to control the framerate at the same time. On the SFML tutorial page for windows they state:

"Never use both setVerticalSyncEnabled and setFramerateLimit at the same time! They would badly mix and make things worse."

As you can see here from the source code for SFML:

void Window::setFramerateLimit(unsigned int limit)
{
    if (limit > 0)
        m_frameTimeLimit = seconds(1.f / limit);
    else
        m_frameTimeLimit = Time::Zero;
}

void Window::display()
{
    // Display the backbuffer on screen
    if (setActive())
        m_context->display();

    // Limit the framerate if needed
    if (m_frameTimeLimit != Time::Zero)
    {
        sleep(m_frameTimeLimit - m_clock.getElapsedTime());
        m_clock.restart();
    }
}

SFML's setFramerateLimit function is implemented in much the same way as your timestep, and thus I don't believe the situation would be any different here.

Upon testing your code on my machine I did see a slight lag on the square, however, disabling vertical sync fixed the issue.

Edit: It turns out this issue is more complex than I originally thought (and I also overlooked the obvious need for vsync if there's tearing). After days of research and messing around with the code, I've learned of a few things that fix the issue:

  • Disabling vsync (though of course we already know this)
  • Recording the program with Fraps
  • Calling glFinish() after window.display()
  • Creating a window in either fullscreen, or borderless (with sf::Style::None) at the same size as the desktop
  • Disabling Windows Aero theme (though of course this only applies to Windows)

All of those except the first will fix it even when vsync is enabled. The main problem here seems to be that vsync doesn't work correctly in windowed mode, apparently it's a limitation due to how the program has to share screen space with other programs that don't necessarily have vsync enabled.

So my suggestion:

  • Use glFinish() after every display() call if using windowed mode, although this has a penalty, it halts the CPU and synchronizes it with the GPU and monitor when it could be processing asynchronously and uninterrupted, but if your program isn't particularly CPU intensive then this shouldn't be much of an issue. In SFML you can include "SFML/OpenGL.hpp" to get access to this function. Although if you are using Windows (Vista and 7 I believe, I don't know how 8 or 10 handles things though) then while using an Aero theme vsync is apparently automatically enabled and you may not have tearing to begin with. What operating system are you using?
  • Use fullscreen and just accept that there will be stuttering in windowed mode. It may not even be noticeable in an actual game or other graphical application, as opposed to a rigid high contrast square moving continuously back and forth on a blank background. I know that in the game I am working on right now I have the same problem, but I hardly ever noticed it.
  • Read up on the issue and see if you can find a true fix. Admittedly using glFinish is somewhat of a kludge, and dealing with stuttering or tearing in windowed mode may not be acceptable. I'm not entirely sure how glFinish manages to eliminate the stutter, and it's usually never recommended to call that function anyway.

Some further reading:

Community
  • 1
  • 1
  • It was a mistake not to read how this function was implemented. Thank you, I am sure now, that I should not use fixed time step with vertical synchronization in the same time. But there is one more thing and it is screen tearing. If vertical synchronization is disabled, visual artifacts are becoming visable. I found some video on youtube which shows same problem: [link](https://www.youtube.com/watch?v=Kvgz_hQCkZ4). Any suggestion? – Paul Newman Sep 28 '16 at 08:40
  • Actually you could update your physics, logic etc as much as possible and still render at 60 or 30 fps. This is a great reading about this : http://gafferongames.com/game-physics/fix-your-timestep/ – cmourglia Sep 29 '16 at 05:51
  • @Zouch The issue I see here is how is vsync supposed to be enabled to fix screen tearing while also keeping a smooth animation, since here it seems that vsync is causing an unusual stuttering. I can't speak for the asker, but I've played around with the examples given on that post and it doesn't seem to fix the issue (though I probably need more time to look things over). I'm honestly at a loss now as well. – Jeremiah Lister Sep 29 '16 at 07:50
  • You can call glFinish() to avoid screen tearing (see http://stackoverflow.com/a/21282439/4717805 for example) – cmourglia Sep 29 '16 at 07:56
  • The problem is I want to use fixed time step in my program, but it looks like it can't be used with vertical synchronization. If vertical synchronization is enabled, application is lagging, but if it is disabled, there is tearing. Any suggestion? – Paul Newman Sep 29 '16 at 10:30
  • @PaulNewman See edit, I added some information that may help. – Jeremiah Lister Oct 01 '16 at 09:12