2016-03-05 23 views
0

在我發佈的某款Android遊戲中,有一個長期問題,其中某些用戶在GLSurfaceView中看不到任何呈現遊戲玩法的地方。我從來沒有能夠在我自己的任何測試設備上重現這個問題,所以調試起來非常困難。使用OpenGL ES 2.0的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); 
     } 
    } 
} 

回答

0

如果我將Matrix.frustumM()呼叫更改爲Matrix.orthoM(),問題就消失了。除此之外,我仍然不確定爲什麼事情在某些設備上運行,而不是在其他設備上運行。如果有人能夠更好地理解這裏發生的事情,我願意接受另一個答案,但現在我已經解決了我的問題。

0

驅動程序可能是越野車。您可以聯繫司機的公司,提交錯誤報告

問自己以下問題:

  1. 手機是否有不同的驅動程序?它支持OpenGL ES 2.0嗎?
  2. GL運營是否成功?即glGetError()是否非零?
  3. glClearColor是否成功?嘗試將顏色清除爲紅色。你看到一個紅色的屏幕?
  4. 程序是否成功編譯?
+0

我編輯了這個問題來解決點2和3,我也認爲在發佈這個問題後測試。至於驅動程序問題,我實際上沒有任何直接訪問驅動程序信息的權限,但假設Google Play商店正確地過濾了所有內容,則我的所有用戶的設備都應具有OpenGL ES 2.0支持。 – Brucelet

+0

它可能是一個endianness(字節順序)的問題。驅動程序的字節順序可能與設備的字節順序不同。這不應該發生,但它值得檢查。嘗試將緩衝區設置爲LITTE_ENDIAN或BIG_ENDIAN。 – Swifter

+0

沒有endianness運氣,但我確實搞清楚了!看到我發佈的答案。 – Brucelet