【问题标题】:Blending is wrong when displaying RGBA Bitmap Texture on OpenGL在 OpenGL 上显示 RGBA 位图纹理时混合错误
【发布时间】:2016-08-17 06:34:44
【问题描述】:

我正在使用纹理通过 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);

它并不能完全解决问题,但我没关系。

【问题讨论】:

    标签: android bitmap opengl-es opengl-es-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

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

    【讨论】:

    • 感谢您对我所怀疑的事情的确认。我尝试使用 GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA);它适用于我的情况。无论 alpha 等于 0.0、1.0 还是介于两者之间,它都会准确地绘制覆盖纹理。唯一剩下的一点是,当我想从 Fragment Shader 更改 Alpha 通道时,结果颜色出乎意料。不管怎样,对我来说没关系。
    • 这似乎很奇怪。这将返回 (s.RGB + (d.RGB * (1 - sA)) 的 RGB 颜色,因此源 RGB 颜色根本不会被 alpha 修改。只有在 (1) 你的预乘存储的输入纹理,或 (2) 您的源字形颜色为黑色(因此缩放值无论如何都为零)。
    【解决方案2】:

    你试过了吗:

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

    【讨论】:

    • 它不起作用,颜色意外混合。但我尝试了一些不同的方法,它工作正常 :) GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA);
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多