使用OpenGL ES 2.0的GLSurfaceView显示某些用户的空白屏幕

时间:2016-03-05 16:52:48

标签: android opengl-es opengl-es-2.0

我在我发布的一款Android游戏中遇到了长期存在的问题,其中某些用户在GLSurfaceView中看不到呈现游戏玩法的内容。我从来没有能够在我自己的任何测试设备上重现这个问题,因此调试起来非常困难。

最近,我能够与报告该错误的用户之一合作,以便将其隔离到相当小的代码子集中。不幸的是,它与基本的教程样本没有什么不同,所以我对可能出错的东西感到有些不知所措。

下面的代码应在屏幕中央绘制一个白色方块。它在我的测试设备上工作正常,但是对于这个用户来说是失败的(对于向我报告相同错误的众多其他用户来说也可能失败)。

我已经尝试了几种不同的测试。用户可以看到背景颜色的变化,因此不是所有GL呼叫的全面失败。另外,当我向glCheckError插入额外的调用时,我从未记录任何非零返回。

有没有人有任何想法或建议?

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        GLSurfaceView view = (GLSurfaceView) findViewById(R.id.gl);
        view.setEGLContextClientVersion(2);
        view.setRenderer(new GLRenderer());
        view.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);

        view.requestRender();
    }

    private static class GLRenderer implements GLSurfaceView.Renderer {
        public static final float SCALE = 480f;
        private float ratio;

        private int mProgram;
        private int mPositionHandle;
        private int mColorHandle;
        private int mMVPMatrixHandle;

        private final float[] mVMatrix = new float[16];   // View matrix
        private final float[] mPMatrix = new float[16];   // Projection matrix
        private final float[] mVPMatrix = new float[16];  // V * P
        private final float[] mMMatrix = new float[16];   // Object transformation matrix (position/rotation)
        private final float[] mMVPMatrix = new float[16]; // VP * M

        private final float[] foregroundColor = {1f, 1f, 1f, 1f};
        private final float[] backgroundColor = {0f, 0f, 0f, 1f};

        private static final int COORDS_PER_VERTEX = 3;
        private static final int VERTEX_STRIDE = COORDS_PER_VERTEX * 4; // 4 bytes per vertex

        private final float[] points = {
                -20, -20, 0,
                -20, 20, 0,
                20, -20, 0,
                20, 20, 0
        };
        private final short[] drawOrder = {
                0, 1, 2, 3
        };

        private final FloatBuffer vertexBuffer = buildFloatBuffer(points);
        private final ShortBuffer drawListBuffer = buildShortBuffer(drawOrder);

        private static FloatBuffer buildFloatBuffer(float[] array) {
            FloatBuffer buffer = ByteBuffer.allocateDirect(
                    // (# of coordinate values * 4 bytes per float)
                    array.length * 4)
                    .order(ByteOrder.nativeOrder())
                    .asFloatBuffer()
                    .put(array)
                    ;
            buffer.position(0);
            return buffer;
        }

        private static ShortBuffer buildShortBuffer(short[] array) {
            ShortBuffer buffer = ByteBuffer.allocateDirect(
                    // (# of coordinate values * 2 bytes per short)
                    array.length * 2)
                    .order(ByteOrder.nativeOrder())
                    .asShortBuffer()
                    .put(array)
                    ;
            buffer.position(0);
            return buffer;
        }

        private static final String vertexShaderCode =
                "uniform mat4 uMVPMatrix;" +
                "attribute vec4 vPosition;" +
                "void main() {" +
                "  gl_Position = uMVPMatrix * vPosition;" +
                "}";


        private static final String fragmentShaderCode =
                "precision mediump float;" +
                "uniform vec4 vColor;" +
                "void main() {" +
                "  gl_FragColor = vColor;" +
                "}";

        private static int loadShader(int type, String shaderCode){
            // create a vertex shader type (GLES20.GL_VERTEX_SHADER)
            // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
            int shader = GLES20.glCreateShader(type);

            // add the source code to the shader and compile it
            GLES20.glShaderSource(shader, shaderCode);
            GLES20.glCompileShader(shader);

            return shader;
        }

        @Override
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
            GLES20.glClearColor(backgroundColor[0], backgroundColor[1], backgroundColor[2], backgroundColor[3]);

            int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER,
                    vertexShaderCode);
            int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,
                    fragmentShaderCode);

            mProgram = GLES20.glCreateProgram();
            GLES20.glAttachShader(mProgram, vertexShader);
            GLES20.glAttachShader(mProgram, fragmentShader);
            GLES20.glLinkProgram(mProgram);
            GLES20.glUseProgram(mProgram);

            mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
            mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
            mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
        }

        @Override
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            ratio = 1f * width / height;

            GLES20.glViewport(0, 0, width, height);

            Matrix.frustumM(mPMatrix, 0, -ratio * SCALE/2, ratio * SCALE/2, -SCALE/2, SCALE/2, 3, 7);
            Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0, 0, 0, 0, -1, 0);
            Matrix.multiplyMM(mVPMatrix, 0, mPMatrix, 0, mVMatrix, 0);
        }

        @Override
        public void onDrawFrame(GL10 gl) {
            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

            GLES20.glEnableVertexAttribArray(mPositionHandle);

            GLES20.glUniform4fv(mColorHandle, 1, foregroundColor, 0);
            draw(0, 0, 0);

            GLES20.glDisableVertexAttribArray(mPositionHandle);
        }

        private void draw(float x, float y, float a) {
            Matrix.setIdentityM(mMMatrix, 0);
            Matrix.translateM(mMMatrix, 0, x, y, 0);
            Matrix.rotateM(mMMatrix, 0, a, 0, 0, 1);
            Matrix.multiplyMM(mMVPMatrix, 0, mVPMatrix, 0, mMMatrix, 0);

            GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);

            GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
                    GLES20.GL_FLOAT, false, VERTEX_STRIDE,
                    vertexBuffer);

            GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP,
                    drawListBuffer.capacity(), GLES20.GL_UNSIGNED_SHORT,
                    drawListBuffer);
        }
    }
}

2 个答案:

答案 0 :(得分:0)

司机可能有错误。您可以联系驱动公司并提交错误报告

问自己以下问题:

  1. 手机有不同的驱动程序吗?它支持OpenGL ES 2.0吗?
  2. GL运营是否成功?即glGetError()是否为非零?
  3. glClearColor是否成功?尝试将颜色清除为红色。你看到红屏吗?
  4. 程序是否成功编译?

答案 1 :(得分:0)

如果我将Matrix.frustumM()来电更改为Matrix.orthoM(),问题就会消失。除此之外,我仍然不确定为什么事情在某些设备而不是其他设备上运行。如果有人出现谁更好地了解这里发生的事情,我愿意接受另一个答案,但是现在我已经解决了我的问题。