1
votes

My Android application show the unexpected behaviour for PowerVR SGX 544MP.

  • In case render setting to "RENDERMODE_WHEN_DIRTY" it seems that the depth buffer don't work, however, if the mode set "RENDERMODE_CONTINUOUSLY" the drawing come to right:

Wrong result:

  Wrong

Proper result:

  Proper


The emulator draw right in both case.
  • The default buffer of device is 24 bit, setting the buffer to same range as emulator (16bit) unchanged drawing. I tried the varying witn values of Near and Far of projection matrix but it was unsuccessful.

  • Only one of the my matrices have modification of near plane.The martix may make bad data in the depth buffer. I turn off the writing in the depth buffer before drawing using this matrix. In that case, I sets "GLES20.glDepthMask( false )" before to call "glDrawElements".


Initialisation OPENGL ES and work with VBOs are new for me, so perhaps my misunderstanding of trouble is more deep than that seems to me.

  • I sends to uniform different matrix values and draw with same VBOs.
  • I do "Enabling" for attributes globally only one time and I don't use Disable for them later.
    //MyGLSurfaceView
   public MyGLSurfaceView(Context context) {
        super(context);
        setEGLContextClientVersion(2);
    //    super.setEGLConfigChooser(8,8,8,8,16,0); // same result
        mRenderer = new MyGLRenderer(context);
        setRenderer(mRenderer);
        setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
   }

//MyGLRenderer
@Override
  public void onSurfaceCreated(GL10 unused, EGLConfig config) {
        GLES20.glClearColor(0.1f, 0.2f, 0.3f, 1.0f);
        GLES20.glEnable(GLES20.GL_BLEND);
        GLES20.glBlendEquation(GLES20.GL_FUNC_ADD);
        GLES20.glEnable(GLES20.GL_DEPTH_TEST);
        GLES20.glDepthRangef(0.f, 1.f);
        GLES20.glClearDepthf(1.f);
        GLES20.glEnable(GLES20.GL_CULL_FACE);
        GLES20.glFrontFace(GLES20.GL_CCW);
        GLES20.glDepthFunc(GLES20.GL_LEQUAL);
}
@Override
    public void onSurfaceChanged(GL10 unused, int width, int height) {
        // Adjust the viewport based on geometry changes,
        // such as screen rotation
        GLES20.glViewport(0, 0, width, height);
        float ratio = (float) width / height;
        perspectiveFieldOfViewRH(mProjectionMatrix, 0, 28.4f, ratio, 0.4f, 28.f);
}
 @Override
    public void onDrawFrame(GL10 unused) {
        GLES20.glDepthMask( true );
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
        int i,j;
        // turn off the writing. Only read
        GLES20.glDepthMask( false );
        GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ZERO);
        GLES20.glUseProgram(prg_shaderCube);
        // draw with modified projection matrix:
        for (i = 0; i < 4; i++){
            for (j = 0; j < 6; j++){
                System.arraycopy(arrFacesMatrices[i][j], 0, mModelMatrix, 0, 16);
                mModelMatrix[14] = translations[i];
                Matrix.multiplyMM(mMirrorFlankWithClippingMVP, 0, mMirrorFlankViewProjectionWithClippingMatrix, 0, mModelMatrix, 0);
                GLES20.glUniformMatrix4fv(u_changematrixCube, 1, false, mMirrorFlankWithClippingMVP, 0);
                GLES20.glUniformMatrix4fv(u_modelmatrixCube, 1, false, mModelMatrix, 0);
                GLES20.glCullFace(GLES20.GL_BACK);
                switch(pattern[i][j]){
                    case 0:
                        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo[0]);
                        GLES20.glVertexAttribPointer(attr_position_cube, 3, GLES20.GL_FLOAT, false, STRIDE_IN_FLAT, 0);
                        GLES20.glVertexAttribPointer(attr_color_cube, 3, GLES20.GL_FLOAT, false, STRIDE_IN_FLAT, 12);
                        GLES20.glVertexAttribPointer(attr_normal_cube, 3, GLES20.GL_FLOAT, false, STRIDE_IN_FLAT, 24);
                        GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, ibo[0]);
                        GLES20.glDrawElements(GLES20.GL_TRIANGLES, capacityFlat1, GLES20.GL_UNSIGNED_SHORT, 0);
                        break;
                    case 1:
                        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo[1]);
                        ....
                        break;
                        ....
                        ....
                }
            }
        }
        // others
        GLES20.glDepthMask( true );
        for (i = 3; i >= 0; i--){
            for (j = 0; j < 6; j++){
                System.arraycopy(arrFacesMatrices[i][j], 0, mModelMatrix, 0, 16);
                mModelMatrix[14] = translations[i];
                Matrix.multiplyMM(mMirrorFlankMVP, 0, mMirrorFlankViewProjectionMatrix, 0, mModelMatrix, 0);
                Matrix.multiplyMM(mMirrorDownMVP, 0, mMirrorDownViewProjectionMatrix, 0, mModelMatrix, 0);
                Matrix.multiplyMM(mMVP, 0, mViewMatrix, 0, mModelMatrix, 0);
                GLES20.glUniformMatrix4fv(u_modelmatrixCube, 1, false, mModelMatrix, 0);
                switch(pattern[i][j]){
                    case 0:
                        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo[0]);
                        GLES20.glVertexAttribPointer(attr_position_cube, 3, GLES20.GL_FLOAT, false, STRIDE_IN_FLAT, 0);
                        GLES20.glVertexAttribPointer(attr_color_cube, 3, GLES20.GL_FLOAT, false, STRIDE_IN_FLAT, 12);
                        GLES20.glVertexAttribPointer(attr_normal_cube, 3, GLES20.GL_FLOAT, false, STRIDE_IN_FLAT, 24);
                        GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, ibo[0]);
                        GLES20.glCullFace(GLES20.GL_FRONT);
                        GLES20.glUniformMatrix4fv(u_changematrixCube, 1, false, mMirrorFlankMVP, 0);
                        GLES20.glDrawElements(GLES20.GL_TRIANGLES, capacityFlat1, GLES20.GL_UNSIGNED_SHORT, 0);
                        GLES20.glUniformMatrix4fv(u_changematrixCube, 1, false, mMirrorDownMVP, 0);
                        GLES20.glDrawElements(GLES20.GL_TRIANGLES, capacityFlat1, GLES20.GL_UNSIGNED_SHORT, 0);
                        GLES20.glCullFace(GLES20.GL_BACK);
                        GLES20.glUniformMatrix4fv(u_changematrixCube, 1, false, mMVP, 0);
                        GLES20.glDrawElements(GLES20.GL_TRIANGLES, capacityFlat1, GLES20.GL_UNSIGNED_SHORT, 0);
                        break;
                    case 1:
                        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo[1]);
                        ....
                        break;
                        ....
                        ....
                }
            }
        }
}

I would prefer to work on a mode RENDERMODE_WHEN_DIRTY,and I would like to understand what is happening with my depth buffer?

2
I edited your question to include the images, but block quotes (text that starts with "> ...") are making it really hard for me to read. Those are designed for quoting other sources. You might consider editing parts of the question to use headings (e.g. "###Sub-heading") instead.Andon M. Coleman
Have you tried it on the other Android device like Adreno GPU device? In my understanding, The difference between CONTINUOUSLY and WHEN_DIRTY is just timing of calling eglSwapBuffers. It sounds PowerVR driver issue.Kazuki Sakamoto
• GPU Adreno 205 hasn't this problemnailer

2 Answers

0
votes

The following is not as conclusive as I normally like answers to be. Particularly, I have no explanation why this would behave differently between RENDERMODE_WHEN_DIRTY and RENDERMODE_CONTINUOUSLY. But there is one point in your question that is worth explaining anyway.

Only one of the my matrices have modification of near plane. The matrix may make bad data in the depth buffer.

You'll have to be very careful here. The range between near and far plane gets mapped to the range of the depth buffer. So if you use a standard projection matrix, and change the near plane, this mapping will change.

In other words, say you use a vertex at a given z-value (in eye coordinates) for your rendering while your projection matrix was set up with a near value of near1. Now you set the projection matrix with near value near2, and use a vertex with the same z-value. This vertex will now be mapped to a different depth buffer value. So depending on your projection, the same vertex will be mapped to different depth buffer values. Or a vertex that is farther away from the camera can end up with a smaller (closer) depth buffer value because you changed your projection matrix.

You could try to compensate for this by setting the depth range accordingly. But even that seems tricky if you use a perspective projection, because the mapping of eye space depth is to depth buffer values is not linear.

If you need to clip away close parts of some of your geometry, you're probably better off keeping the projection matrix unchanged, and clipping explicitly. OpenGL ES does not support arbitrary clip planes, so the easiest approach is to pass the distance to the fragment shader, and discard the clipped fragments there. Or if it's anyway possible, have logic in your app code to avoid rendering the geometry that would be clipped.

0
votes

Adding of calling the glSurfaceView.requestRender() improve a performance. My focus on depth buffer dragged away from realy cause of problem.