【问题标题】:Frames appearing out of order on GLSurfaceViewGLSurfaceView 上出现乱序的帧
【发布时间】:2015-10-19 08:10:36
【问题描述】:

我正在使用 OpenGL ES 编写一个 Android 应用程序,并在 Android Studio 附带的 Nexus 5 模拟器中遇到了这个问题。我已经将我的代码简化为这个小应用程序,它只是简单地绘制一个来回移动的框:

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);
    }
}

我逐帧查看,似乎不是显示下一帧,而是显示前一帧,然后跳过它应该显示的帧并继续:

圆圈代表onDrawFrame中产生的帧,箭头代表时间流逝。

Video showing the problem

【问题讨论】:

  • 您在实际设备上见过这个吗? BufferQueue 机制非常简单,但 GLES 和模拟器 GPU 加速之间的联系并不简单。

标签: android animation opengl-es glsurfaceview doublebuffered


【解决方案1】:

我不太清楚OpenGL是如何使用线程的,但试试这个:

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

如果编译器同意并且 OpenGL 没有锁定,则使整个 onDrawFrame() 方法同步...

【讨论】:

  • 不幸的是,这并不能解决问题。我在 onDrawFrame 方法的顶部和底部放了一个 Log.i(...) ,并且从来没有重叠。即使有,也不会导致框在动画中间向后跳转(大约 step=0.5)。
  • GLSurfaceView 使用专用的渲染器线程。由于所有计算都在onDrawFrame() 内完成,因此不会出现线程安全问题。
猜你喜欢
  • 2015-08-04
  • 2013-12-21
  • 1970-01-01
  • 2021-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-14
  • 1970-01-01
相关资源
最近更新 更多