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的世界中),所以如果你认为别的东西是原因我也一定会为你发布.对不起,所有的烦恼!
更改
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.
您很可能希望用作glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)混合函数,并且必须确保还将纹理的 alpha 值写入gl_FragColor片段着色器输出变量。
为了使所有这些工作正常,您上传的纹理数据必须包含 Alpha 值,并且您必须使用支持 Alpha 通道(RGBA、RGBA8 等)的纹理格式。
您可以通过简单地将 alpha 值路由到 RGB 颜色分量并检查获得的图像来验证这一点。
编辑:
在您的图像加载代码中,您忘记复制 Alpha 通道!尝试一下davebytes给出的建议。
| 归档时间: |
|
| 查看次数: |
9925 次 |
| 最近记录: |