在OpenGL

时间:2016-08-17 06:34:44

标签: android bitmap opengl-es opengl-es-2.0

我使用纹理通过OpenGL绘制位图。

TextureId的生成方式如下:

        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);

下面我用这个代码绘制框架:

        //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);

我只需要在背景上绘制一个位图(之前绘制过)。叠加位图具有RGBA格式。

当位图只包含alpha等于0或255的颜色时,上面的代码非常有效。(如果alpha == 0,则像素是透明的,alpha == 1,像素是不透明的。)

但是,当alpha等于100(例如)时,像素显示不正确。如果颜色的十六进制值为0xAAFFFFFF,则显示的结果似乎为0xAA000000。

我想也许blendFunction不仅可以混合alpha chanel,还可以混合RGB chanel(基于alpha chanel的值)。

我可以做些什么来解决这个问题?我只想在OpenGL上绘制我的叠加位图,就像我以前使用Paint和Canvas一样。

===========================更新解决方案================== ==

我尝试使用

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

它适用于我的情况。它精确地绘制叠加纹理,无论alpha等于0.0,1.0还是介于这些之间。唯一值得注意的是当我想要从Fragment Shader更改alpha通道时,结果颜色是意外的。在这种情况下,我使用了:

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

它并没有完全解决问题,但对我来说没问题。

2 个答案:

答案 0 :(得分:1)

  

我认为也许blendFunction不仅可以混合alpha chanel,还可以混合RGB chanel(基于alpha chanel的值)

正确,混合会影响所有四个频道。如果您只混合了Alpha通道,那么您将无法获得所需的效果(文本精灵的颜色值将被写为所有像素的白色,而不管字体字形实际位于何处)。

  

我可以做些什么来解决这个问题?

如果你想要完全透明或完全不透明,那么显而易见的答案只能传递0.0(透明)或(1.0)不透明的alpha值,这样可以正常工作(正如你已经注意到的)。

如果确实需要,您可以在着色器中将部分值舍入为0.0或1.0。

可以通过扩展名为颜色和Alpha通道设置不同的混合:

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

...但我实际上并不认为这就是你想要的。

答案 1 :(得分:1)

你试过了吗?

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