2015-07-28 2 views
0

J'écris une application Android en utilisant OpenGL ES et j'ai rencontré ce problème dans l'émulateur Nexus 5 fourni avec Android Studio. J'ai réduit mon code à cette petite application, qui tire simplement une boîte va et vient:Les cadres apparaissent en désordre sur GLSurfaceView

package net.jesbus.stuttertest; 

import android.app.Activity; 
import android.opengl.GLSurfaceView; 
import android.os.Bundle; 

import java.nio.ByteBuffer; 
import java.nio.ByteOrder; 
import java.nio.FloatBuffer; 
import java.nio.ShortBuffer; 

import javax.microedition.khronos.egl.EGLConfig; 
import javax.microedition.khronos.opengles.GL10; 

public class MainActivity extends Activity 
{ 
    @Override 
    protected void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 

     // Create GLSurfaceView 
     GLSurfaceView glsv = new GLSurfaceView(this); 
     glsv.setEGLConfigChooser(8, 8, 8, 8, 16, 0); 

     // Create GLSurfaceView.Renderer 
     glsv.setRenderer(new GLSurfaceView.Renderer() 
     { 
      float step = 0; 
      boolean direction = false; 
      ShortBuffer iBuff; 
      FloatBuffer vBuff; 
      @Override 
      public void onSurfaceCreated(GL10 gl, EGLConfig config) 
      { 
       // Generate vertices index buffer 
       short[] pIndex = {0, 1, 2, 3}; 
       ByteBuffer pbBuff = ByteBuffer.allocateDirect(pIndex.length * 2); 
       pbBuff.order(ByteOrder.nativeOrder()); 
       iBuff = pbBuff.asShortBuffer(); 
       iBuff.put(pIndex); 
       iBuff.position(0); 

       // Generate vertices buffer 
       float[] vs = new float[] 
         { 
           -1, +1, 0, 
           +1, +1, 0, 
           -1, -1, 0, 
           +1, -1, 0, 
         }; 
       ByteBuffer bBuff = ByteBuffer.allocateDirect(vs.length * 4); 
       bBuff.order(ByteOrder.nativeOrder()); 
       vBuff = bBuff.asFloatBuffer(); 
       vBuff.put(vs); 
       vBuff.position(0); 
      } 

      @Override 
      public void onDrawFrame(final GL10 gl) 
      { 
       // Animation calculation 
       step += direction ? 0.02f : -0.02f; 
       if (step > 1) direction = false; 
       else if (step < 0) direction = true; 

       // Set background color 
       gl.glClearColor(0.7f, 0.7f, 1, 1); 

       // Clear screen 
       gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); 

       // Set matrix to correct location 
       gl.glLoadIdentity(); 
       gl.glTranslatef(-1 + step * 2, 0, 0); 
       gl.glScalef(0.25f, 0.4f, 1); 

       // Draw box 
       gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); 
       gl.glFrontFace(GL10.GL_CW); 
       gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vBuff); 
       gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 4, GL10.GL_UNSIGNED_SHORT, iBuff); 
       gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); 
      } 

      @Override 
      public void onSurfaceChanged(GL10 gl, int width, int height) 
      { 
      } 
     }); 
     setContentView(glsv); 
    } 
} 

Je l'ai regardé image par image, et il semble qu'au lieu de montrer l'image suivante, elle montre la précédente cadre, puis saute le cadre il était censé montrer et continue:

Wrong order of frames

les cercles représentent les cadres produits dans onDrawFrame, et les flèches représentent l'écoulement du temps.

Video showing the problem

+0

Avez-vous vu ceci sur un appareil actuel? Le mécanisme de BufferQueue est assez simple, mais la connexion entre GLES et l'accélération GPU de l'émulateur est non triviale. – fadden

Répondre

0

Je ne sais pas exactement comment le filetage est utilisé OpenGL, mais essayez ceci:

// Animation calculation 
    synchronized (this) { 
     step += direction ? 0.02f : -0.02f; 
     if (step > 1) direction = false; 
     else if (step < 0) direction = true; 
    } 

ou faire toute méthode onDrawFrame() synchronisée si les consentements du compilateur et OpenGL ne se verrouille pas ...

+0

Malheureusement, cela ne résout pas le problème. J'ai mis un Log.i (...) en haut et en bas de la méthode onDrawFrame, et il n'y a jamais de chevauchement. Même s'il y en avait, cela ne ferait pas reculer la boîte au milieu de l'animation (autour de l'étape = 0.5). –

+0

GLSurfaceView utilise un thread de rendu dédié. Puisque tous les calculs sont effectués dans 'onDrawFrame()', il n'y a aucun risque de problème de sécurité. – fadden