Opengl es 2.0 draw bitmap overlay on video

I see two things that seems wrong to me.

  1. You are trying to bind everything at the same time, and hope that one call to GLES20.glDrawArrays() will draw everything.

  2. You have only one shader, where you should have two : one for doing video texture rendering, and another for your bitmap layer rendering.

What you must know is that a frame can be draw by multiple call to glDrawArrays, each call will just paint a little part over previously drawn stuff (basically).


The first part of rendering a frame in your case should look to this :

init

loadShaderForVideo()

loadShaderForBitmapLayer()

prepareYourArraysEtc()

...

#loop

GLClear()

updateVideoTexture()

drawFrame(){
   drawVideo()
   drawBitmap()
}
drawVideo(){

    bindYourActiveTextureToVideo()

    setYourVertexAttribAndUniform()

    GLES20.glDrawArrays()

}

drawBitmap() {

    bindYourActiveTextureToBitmap()

    setYourVertexAttribAndUniform() // This should be the same as above for video
    // Considering you want to draw above your video, consider activating the blending for transparency :

    GLES20.glEnable(GLES20.GL_BLEND);
    GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);

    GLES20.glDrawArrays()

}

Concerning the shader, just take a look at these :

A common Vertex Shader for both :

public static final String vertexDefaultShaderCode =
        "uniform mat4 uVPMatrix;" +
                "uniform mat4 uModelMatrix;" + // uniform = input const
                "attribute vec3 aPosition;" +  // attribute = input property different for each vertex
                "attribute vec2 aTexCoordinate;" +
                "varying vec2 vTexCoordinate;" +// varying = output property different for each pixel

                "void main() {" +
                "vTexCoordinate = aTexCoordinate;" +
                "gl_Position = uVPMatrix * uModelMatrix * vec4(aPosition,1.0);" +
                "}";

Then a basic fragment shader ( for your bitmap 2D texture ) :

    public static final String fragmentDefaultShaderCode =
        "precision mediump float;" +
                "uniform sampler2D uTexture;" +
                "varying vec2 vTexCoordinate;" +

                "void main() {" +
                "  gl_FragColor = texture2D(uTexture, vTexCoordinate);" +
                "}";

Then a different version for video rendering :

    public static final String fragmentExternalShaderCode =
        "#extension GL_OES_EGL_image_external : require\n" +
                "precision mediump float;" +
                "uniform samplerExternalOES sTexture;" +
                "varying vec2 vTexCoordinate;" +

                "void main() {" +
                "  gl_FragColor = texture2D(sTexture, vTexCoordinate);" +
                "}";

Thus you will need two Programs, one with the defaultVertexShader + defaultFragmentShader and another with defaultVertexShader + fragmentExternalShaderCode.

I hope that only these modifications will solve your problem.

Regards