0
votes

I'm using a Texture to draw Bitmap by OpenGL.

TextureId was generated like that:

        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureIdForDrawingBitMap);
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);

And this code below I used to draw the frame:

        //Enable blend for display a RGBA bitmap
        GLES20.glEnable(GLES20.GL_BLEND);
        GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);

        GLES20.glUseProgram(ShaderHelper.programTexture);
        GLES20.glEnableVertexAttribArray(ShaderHelper.a_Position_Texture);
        GLES20.glEnableVertexAttribArray(ShaderHelper.a_texCoord_Texture);
        GLES20.glVertexAttribPointer(ShaderHelper.a_Position_Texture, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer);
        GLES20.glVertexAttribPointer(ShaderHelper.a_texCoord_Texture, 2, GLES20.GL_FLOAT, false, 0, uvBuffer);

        GLES20.glUniform1f(ShaderHelper.alphaFactor_Image, alphaFactor);
        GLES20.glUniformMatrix4fv(ShaderHelper.u_MVPMatrix_Texture, 1, false, mPVMatrix, 0);
        GLES20.glUniform1i(ShaderHelper.u_texture_Texture, 0);
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureIdForDrawingBitMap);

        //Upload bitmap to texture
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0,  GLES20.GL_RGBA, mBitmap, 0);

        GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length, GLES20.GL_UNSIGNED_SHORT, indicesBuffer);
        GLES20.glDisableVertexAttribArray(ShaderHelper.a_Position_Texture);
        GLES20.glDisableVertexAttribArray(ShaderHelper.a_texCoord_Texture);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);

All I need is drawing a bitmap over a background (which was drawn before). The overlay bitmap has RGBA format.

The code above works perfectly when the bitmap just only contains colors with alpha equals 0 or 255. (If alpha == 0, the pixel is transparent, alpha == 1, the pixel is opaque).

However, when alpha equals 100 (for example), the pixel displays not correct. If hex value of color is 0xAAFFFFFF, the result when displayed seems to 0xAA000000.

I think maybe blendFunction does not only blend alpha chanel, but it also blends RGB chanel (base on value of alpha chanel).

What can I do for solving this problem? I just want to draw my overlay bitmap on OpenGL like I used to do with Paint and Canvas.

=========================== UPDATE SOLUTION ========================

I tried to use

          GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA); 

And It works in my case. It draws the overlay texture exactly whether alpha equals 0.0, 1.0 or between those. The only remain point is when I want change alpha channel from Fragment Shader, the result color is unexpected. In this case, I used:

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

It does not totally solve the problem, but it's okay with me.

2

2 Answers

1
votes

I think maybe blendFunction does not only blend alpha chanel, but it also blends RGB chanel (base on value of alpha chanel)

Correct, blending will affect all four channels. If you only blended the alpha channel then you wouldn't get the effect you wanted (the color value for your text sprite would be written as white to all pixels, irrespective of where the font glyph actually is).

What can I do for solving this problem?

If you want either totally transparent or totally opaque then the obvious answer is only pass in alpha values which are either 0.0 (transparent) or (1.0) opaque, which will work fine (as you have already noted).

You can round partial values to 0.0 or 1.0 in your shader, if really needed.

It is possible to set different blending for color and alpha channels via an extension:

https://www.khronos.org/registry/gles/extensions/OES/OES_blend_equation_separate.txt

... but I don't actually think that is what you want.

1
votes

Have you tried:

 GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_COLOR);