Search code examples
javaopengl3djoglframe-rate

Why does this code sometimes report 21.3 FPS when I ask for 30 FPS?


I have the code below (a bare-bones version of Nehe tutorial 1 ported to JOGL 2.0) that is requesting an FPSAnimator that animates 30 FPS. When I run the code, it prints 21.321962 or 21.413277 FPS. When creating the FPSAnimator, as you can see, I specify 30 frames per second is desired. This is on a modern machine with a Core i7 CPU, 24GB of RAM, and an ATI Radeon HD 5700 Series graphics card. 21.3 FPS does not appear to be a limit either. When I raise or lower the requested FPS, the reported FPS does go up and down (though it doesn't appear to be a linear relationship).

However, sometimes when I run the code on the same machine is gives me 30.30303 FPS. In both cases I have nothing but a few web browser tabs and eclipse open on the machine. It is also worth noting that this doesn't only happen in this simple example, it happens in all of my JOGL based applications. I have merely provided this simple example to demonstrate the issue.

I've seen this issue on a few machines. Maybe it's just my imagination, but it doesn't seem to occur on machines with NVidia GeForce cards, but I have seen it happen on machine's with ATI cards and NVidia Quadro FX cards.

What could be causing this difference?

public static void main(String[] args) {
    GLCanvas glCanvas;
    FPSAnimator animator;
    JFrame frame = new JFrame("JOGL HelloWorld");
    GLCapabilities caps = new GLCapabilities(null);

    caps.setDoubleBuffered(true);
    caps.setHardwareAccelerated(true);
    glCanvas = new GLCanvas(caps);
    glCanvas.setSize(800, 800);
    glCanvas.setIgnoreRepaint(true);
    glCanvas.addGLEventListener(new GLEventListener() {
        @Override
        public void reshape(GLAutoDrawable gLDrawable, int x, int y,
                int width, int height) {
        }

        @Override
        public void init(GLAutoDrawable gLDrawable) {
        }

        @Override
        public void dispose(GLAutoDrawable gLDrawable) {

        }

        @Override
        public void display(GLAutoDrawable gLDrawable) {
            FPSAnimator animator = (FPSAnimator) gLDrawable.getAnimator();
            System.out.println("animator.getLastFPS(): "
                    + animator.getLastFPS());
        }
    });

    frame.getContentPane().setLayout(new BorderLayout());
    frame.getContentPane().add(glCanvas, BorderLayout.CENTER);

    animator = new FPSAnimator(glCanvas, 30, false);
    frame.setSize(frame.getContentPane().getPreferredSize());
    frame.setVisible(true);
    animator.setUpdateFPSFrames(10, null);
    animator.start();
}

Solution

  • The problem probably is being caused by an inaccuracy related to java.util.Timer.schedule(), which JOGL uses when initialized with any two-param constructors, or when the 3rd param, which is a flag for using fixed-rate scheduling, is set to false.


    When the flag is set to true, FPSAnimator will use java.util.Timer.scheduleAtFixedRate() instead, being considerably more consistent and accurate in terms of FPS.

    In specifics, using the flag as true will be particularly better in higher FPS, as the default is weak to delays and would begin to suffer from drifting, while using fixed-rate scheduling will execute an animation the correct number of times over a lengthy period, regardless of delays [source].


    Note however that, according to the response to the ticket responsible for this functionality being implemented, it is unclear whether the flag will cause excessive CPU consumption.