Android: Grundlegendes zu OnDrawFrame, FPS und VSync (OpenGL ES 2.0)

Vor einiger Zeit habe ich ein zeitweiliges "Stottern" der Sprites erlebt, die in meinem Android-Spiel in Bewegung sind. Es ist ein wirklich einfaches 2D OpenGL ES 2.0 Spiel. (Dies ist ein laufendes Problem, das ich schon oft besucht habe.)

In meiner Spieleschleife habe ich 2 "Timer" - einen, der die Anzahl der Frames in der vorherigen Sekunde protokolliert, und einen anderen, der die Zeit (in Millisekunden) vom Ende der aktuellen onDrawFrame-Iteration bis zum Beginn der nächsten zählt .

Das habe ich gefunden:

Wenn ich nichts rendere, erhalte ich (größtenteils) 60fps und jedes Mal, wenn onDrawFrame aufgerufen wird, dauert es länger als 16,667ms. Wenn ich jetzt etwas rendere (egal ob 1 Quad oder 100 Quads, das Ergebnis ist dasselbe), erhalte ich (größtenteils) 60 fps, aber jetzt geben nur etwa 20% der onDrawFrame-Aufrufe an, dass sie länger dauern als 16,667ms vom letzten Anruf.

Ich verstehe nicht wirklich, warum dies geschieht, erstens, warum, wenn onDrawFrame nichts tut, es so "langsam" heißt - und, was noch wichtiger ist, warum ruft ein GL (ein einfaches Quad) immer noch die Zeit ab zwischen onDrawFrame-Aufrufen, die länger als 16,667 ms dauern (wenn auch viel seltener).

Ich sollte sagen, dass bei onDrawFrame-Berichten, die länger als 16,667 ms seit der letzten Iteration dauern, fast immer eine Verringerung der FPS (auf 58 oder 59) einhergeht, die FPS jedoch manchmal nicht die ganze Zeit über konstant bleibt. Und umgekehrt wird onDrawFrame manchmal, wenn die FPS sinken, innerhalb von 16,667 ms nach Abschluss der letzten Iteration aufgerufen.

So.....

Ich versuche, meine Spielschleife zu reparieren und diese "Stottern" zu beseitigen - einige andere Dinge, die zu beachten sind:

Wenn ich Methodenprofile erstelle, werden glSwapBuffers angezeigt, was manchmal viel Zeit in Anspruch nimmtWenn ich eine GL-Spur mache, werden die meisten Szenen in weniger als 1 ms gerendert, aber manchmal dauert der ungerade Frame 3,5-4 ms - dieselbe Szene. Es ändert sich nichts außer der Zeit, die es dauert Fast jedes Mal, wenn ein Frame gelöscht wird oder onDrawFrame eine lange Verzögerung (oder beides) meldet, tritt ein visueller Fehler auf, jedoch nicht jedes Mal. Große visuelle Störungen scheinen mit mehreren "verzögerten" OnDrawFrame-Aufrufen und / oder ausgelassenen Frames zusammenzufallen.Ich glaube nicht, dass dies aus zwei Gründen ein Problem der Szenenkomplexität ist: 1) Auch wenn ich meine Szene zweimal rendere, verschlimmert dies das Problem nicht. genau wie zuvor und 2) auch wenn ich die szene nackt ausziehe, bekomme ich trotzdem das problem.

Ich verstehe offensichtlich etwas falsch, daher wäre ein Vorstoß in die richtige Richtung sehr willkommen.

OnDrawFrame

@Override
public void onDrawFrame(GL10 gl) {

    startTime = System.nanoTime();        
    fps++;                        
    totalTime = System.nanoTime() - timeSinceLastCalled;    

    if (totalTime > 16667000) {     
        Log.v("Logging","Time between onDrawFrame calls: " + (totalTime /(double)1000000));
    }

    //Grab time
    newTime = System.currentTimeMillis() * 0.001;
    frameTime = newTime - currentTime; //Time the last frame took

    if (frameTime > 0.25)
        frameTime = 0.25;

    currentTime = newTime;
    accumulator += frameTime;

    while (accumulator >= dt){              
      saveGameState();
      updateLogic();
      accumulator -= dt;
    }

    interpolation = (float) (accumulator / dt);

    Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);

    render(interpolation);

    if (startTime > lastSecond + 1000000000) {          
        lastSecond = startTime;
        Log.v("Logging","fps: "+fps);
        fps=0;          
    }

    endTime = startTime;
    timeSinceLastCalled = System.nanoTime();        
}

Diese Spieleschleife ist diejenige, die in dieser exzellentenArtike.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage