user1995270
user1995270

Reputation: 13

OpenGL ES 2.0 Not rendering correctly

This is supposed to render a cube. It looks like some parts of the rear faces are rendering in front of the ones closest to the camera. This happens even if I set it farther away. This is from my renderer:

public void onDrawFrame(GL10 unused) {

    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

    // Set the camera position
    Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

    Matrix.setIdentityM(mModelMatrix, 0);
    Matrix.setRotateM(mModelMatrix, 0, mAngle, 0f, 1f, 0.0f);

    Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mModelMatrix, 0);
    Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix,   0);

    // Draw object
    cube.draw(mMVPMatrix, context);

    mAngle++;
}

and my object's draw method

public void draw(float[] mvpMatrix, Context context) {
    GLES20.glUseProgram(mProgram);

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

    GLES20.glVertexAttribPointer(mTexHandle, 2,
                                 GLES20.GL_FLOAT, false,
                                 8, textureBuffer);

    GLES20.glEnableVertexAttribArray(mPositionHandle);
    GLES20.glEnableVertexAttribArray(mTexHandle);

    GLES20.glActiveTexture ( GLES20.GL_TEXTURE0 );
    GLES20.glBindTexture ( GLES20.GL_TEXTURE_2D, mTextureID);
    GLES20.glUniform1i ( mSampler, 0 );

    mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");

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

    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);

    GLES20.glDisableVertexAttribArray(mPositionHandle);
    GLES20.glDisableVertexAttribArray(mTexHandle);
}

and my shaders:

    String vertexShaderCode =
         "uniform mat4 uMVPMatrix;" +
         "uniform float u_offset;      \n" +
         "attribute vec4 a_position;   \n" +
         "attribute vec2 a_texCoord;   \n" +
         "varying vec2 v_texCoord;     \n" +
         "void main()                  \n" +
         "{                            \n" +
         "   gl_Position = uMVPMatrix *  a_position; \n" +
         "   gl_Position.x += u_offset;\n" +
         "   v_texCoord = a_texCoord;  \n" +
         "}                            \n";




String fragmentShaderCode = 
      "precision mediump float;                            \n" +
      "varying vec2 v_texCoord;                            \n" +
      "uniform sampler2D s_texture;                        \n" +
      "void main()                                         \n" +
      "{                                                   \n" +
      "  gl_FragColor = texture2D(s_texture, v_texCoord);  \n" +
      "}                                                   \n";

and the result

Picture: https://i.sstatic.net/f7pYc.png

Thanks

Upvotes: 1

Views: 675

Answers (2)

Mike
Mike

Reputation: 157

I'm not sure about Android-specific code as I program on iOS, but it's my understanding from reading "OpenGL ES 2.0 Programming Guide" (by Munshi et al.) that very little differs. Here's what my code looks like from a recent small project:

After setting up your framebuffer and color-renderbuffer, as you've already done, set up the depth buffer.

GLuint depthRenderbuffer;

GLint backingWidth, backingHeight;

glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);

glGenRenderbuffers(1, &depthRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);

glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, backingWidth, backingHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer);

It's a good idea to include the part about setting the depthbuffer dimensions based off the color-renderbuffer, using glGetRenderbufferParameteriv(), because it ensures that no matter what, they're going to match.

One side note, on iOS it's recommended to setup the color-renderbuffer storage directly from the underlying iOS drawing layer, however in setting up the depth-renderbuffer it requires the call to glRenderbufferStorage() instead, as I've shown above.

You'll also want to include the following lines of code to your draw routine:

glClearDepthf(1.0);
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

If you don't make the call to glEnable(GL_DEPTH_TEST), it seems to glitch at first and then work just fine, at least on my implementation in iOS. The glClearDepthf(1.0) clears it all the way to the far-plane, as opposed to a value of 0.0 which clears it to the front-plane.

It looks like you may have some Android-specific code, but hopefully this gets you off to the right start. Cheers!

Upvotes: 0

radical7
radical7

Reputation: 9114

Assuming you're using the depth buffer, you don't seem to be clearing it in your onDrawFrame function. Try:

GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT|GLES20.GL_DEPTH_BUFFER_BIT);

Upvotes: 2

Related Questions