OpenGL ES 2.0 PNG alpha通道

Dae*_*eKo 8 png transparency android alpha opengl-es

我刚刚学习使用OpenGL ES 2.0 for Android.我一直试图在屏幕中间只显示一个纹理,这很容易,但我似乎无法让PNG alpha正常工作.图像将以黑色背景显示,或者整个图像将略微混合到背景颜色中,具体取决于我使用的设置.

为了达到这一点,我所遵循的实际教程从未使用过透明度,因此我尝试使用搜索到的代码,并且可能只是错过了一个重要的步骤.我已经搜索了很多来解决这个问题,但我还没有看到任何答案,我的设置没有.我已经尝试过glBlendFunc的所有组合以及没有运气的东西.

我想如果我试图粘贴可能与此相关的所有代码,问题看起来会非常臃肿,所以我很乐意发布你们要求的任何代码.我非常感谢我接下来应该尝试的任何想法.

编辑:: 这是我的片段着色器,这是我认为的原因.这是我从来没有真正找到一个体面的例子来处理透明度,而其他一切都与我在别处看到的一致.

        final String fragmentShader =           
        "precision mediump float;       \n"  
        + "varying vec2 v_Color;          \n"     
        + "uniform sampler2D s_baseMap;   \n"
        + "void main()                    \n"     
        + "{                              \n"
        + "  vec4 baseColor;              \n"
        + "  baseColor = texture2D( s_baseMap, v_Color );   \n"
        + "   gl_FragColor = baseColor;     \n"    
        + "}                              \n"; 
Run Code Online (Sandbox Code Playgroud)

它从来没有明确地对alpha做任何事情,它来自一个完全不使用它的例子,但我仍然不太了解片段着色器,因为它似乎"有点"工作时它将图像混合到背景,我认为它以某种形式使用alpha并且我只是设置了错误.

编辑:: 这是"loadTexture"方法.它与我试图从中学习的openGL ES 2.0书中的示例大致相同,只是进行了一些改动,使图像更接近正常工作.

    private int loadTexture ( InputStream is )
{
    int[] textureId = new int[1];
    Bitmap bitmap;
    bitmap = BitmapFactory.decodeStream(is);
    byte[] buffer = new byte[bitmap.getWidth() * bitmap.getHeight() * 4];

    for ( int y = 0; y < bitmap.getHeight(); y++ )
        for ( int x = 0; x < bitmap.getWidth(); x++ )
        {
            int pixel = bitmap.getPixel(x, y);
            buffer[(y * bitmap.getWidth() + x) * 4 + 0] = (byte)((pixel >> 16) & 0xFF);
            buffer[(y * bitmap.getWidth() + x) * 4 + 1] = (byte)((pixel >> 8) & 0xFF);
            buffer[(y * bitmap.getWidth() + x) * 4 + 2] = (byte)((pixel >> 0) & 0xFF);
        }

    ByteBuffer byteBuffer = ByteBuffer.allocateDirect(bitmap.getWidth() * bitmap.getHeight() * 4);
    byteBuffer.put(buffer).position(0);

    GLES20.glGenTextures ( 1, textureId, 0 );
    GLES20.glBindTexture ( GLES20.GL_TEXTURE_2D, textureId[0] );

    GLES20.glTexImage2D ( GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, bitmap.getWidth(), bitmap.getHeight(), 0, 
                          GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, byteBuffer );

    GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR );
    GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR );
    GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE );
    GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE );

    return textureId[0];
}
Run Code Online (Sandbox Code Playgroud)

我理解代码在做什么,但不可否认它仍然让我感到困惑,所以我可能因为缺乏知识而遗漏了一些明显的东西.

我没有看到我的代码中的任何其他部分似乎可能导致我遇到的问题,但编程总是充满了意外(特别是在OpenGL的世界中),所以如果你认为别的东西是原因我也一定会为你发布.对不起,所有的烦恼!

idu*_*olz 9

更改

 for ( int y = 0; y < bitmap.getHeight(); y++ )
    for ( int x = 0; x < bitmap.getWidth(); x++ )
    {
        int pixel = bitmap.getPixel(x, y);
        buffer[(y * bitmap.getWidth() + x) * 4 + 0] = (byte)((pixel >> 16) & 0xFF);
        buffer[(y * bitmap.getWidth() + x) * 4 + 1] = (byte)((pixel >> 8) & 0xFF);
        buffer[(y * bitmap.getWidth() + x) * 4 + 2] = (byte)((pixel >> 0) & 0xFF);
    }
Run Code Online (Sandbox Code Playgroud)

 for ( int y = 0; y < bitmap.getHeight(); y++ )
    for ( int x = 0; x < bitmap.getWidth(); x++ )
    {
        int pixel = bitmap.getPixel(x, y);
        buffer[(y * bitmap.getWidth() + x) * 4 + 0] = (byte)((pixel >> 16) & 0xFF);
        buffer[(y * bitmap.getWidth() + x) * 4 + 1] = (byte)((pixel >> 8) & 0xFF);
        buffer[(y * bitmap.getWidth() + x) * 4 + 2] = (byte)((pixel >> 0) & 0xFF);
        buffer[(y * bitmap.getWidth() + x) * 4 + 3] = (byte)((pixel >> 24) & 0xFF);
    }
Run Code Online (Sandbox Code Playgroud)

包括alpha信息然后简单地添加

GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
GLES20.glEnable(GLES20.GL_BLEND); 
Run Code Online (Sandbox Code Playgroud)

在绘制纹理之前.完成后,请务必禁用GL_BLEND.


tre*_*nki 3

您很可能希望用作glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)混合函数,并且必须确保还将纹理的 alpha 值写入gl_FragColor片段着色器输出变量。

为了使所有这些工作正常,您上传的纹理数据必须包含 Alpha 值,并且您必须使用支持 Alpha 通道(RGBA、RGBA8 等)的纹理格式。

您可以通过简单地将 alpha 值路由到 RGB 颜色分量并检查获得的图像来验证这一点。

编辑:

在您的图像加载代码中,您忘记复制 Alpha 通道!尝试一下davebytes给出的建议。