【问题标题】:OpenGL ES 2.0 - Create Bitmap on runtime, use as texture - with transparencyOpenGL ES 2.0 - 在运行时创建位图,用作纹理 - 具有透明度
【发布时间】:2014-05-30 12:59:17
【问题描述】:

目前我正在研究具有透明度的动态纹理(即在运行时创建)。我当前创建的位图如下所示:

b = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
final Canvas c = new Canvas(b);
c.drawColor(0, PorterDuff.Mode.CLEAR);
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
c.save();
c.translate(paddingLeft, paddingTop);
view.draw(c);
c.restore();

因为我正在创建一个视图,我需要它作为位图,然后将其用作平面的纹理。这工作得很好,我收到一个位图。如果我将它添加到 ImageView 中并将其放在我的布局之上,它也是透明的,据我所知。

我在我的GLSurfaceViewsetEGLConfigChooser(8,8,8,8,16,0); 中使用getHolder().setFormat(PixelFormat.TRANSLUCENT);

纹理的生成是这样的:

GLES20.glGenTextures(1, textureHandle, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
// GLES20 tex parameters here as well... (min/mag filter)
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, bmp, 0);

在片段着色器中,我 - 出于测试目的 - 只是应用

gl_FragColor = texture2D(u_Texture, v_TexCoordinate);

所以没有灯光,只取纹理的颜色。

但它不是透明的,它有黑色边框 - 因为我将位图创建为 2 的幂。这意味着,如果我的视图大小是例如300x300,纹理为 512x512,带有透明边框 - 在 OpenGL ES 2.0 中绘制为黑色。

在我的渲染器中,我启用混合如下:

GLES20.glClearColor(0, 0, 0, 0);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glEnable(GLES20.GL_CULL_FACE);
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
GLES20.glCullFace(GLES20.GL_BACK);
GLES20.glDepthFunc(GLES20.GL_LEQUAL);

但我不确定这是否是正确的搅拌机功能。

所以最后,透明度被忽略,显示为黑色。

任何想法我可能会错过/做错什么?非常感谢。

【问题讨论】:

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


    【解决方案1】:

    如果我理解您的操作正确,那么听起来问题实际上并不在于纹理。这是您添加到不透明的 2 次幂的填充。

    我最初以为您没有清除整个位图,但c.DrawColor() 调用您应该 解决这个问题。可以肯定的是,您可以在创建位图后立即尝试以下操作,看看是否有所不同:

    b.eraseColor(Color.TRANSPARENT);
    

    我能想到的另一种方法更简洁更好:在渲染过程中,不要使用您添加的纹理部分来填充大小。您可以通过调整纹理坐标以仅对包含您的视图的纹理部分进行采样来做到这一点。使用示例中的尺寸(300x300 视图绘制到 512x512 纹理中),您用于渲染的纹理坐标范围在每个方向上应该是 0.0f300.0f / 512.0f,而不是通常的 0.0f1.0f .

    你使用的混合功能看起来不错。

    【讨论】:

    • 没错,它是从 OpenGL 显然不被视为透明的填充。我已经尝试了几种使位图透明的方法,但都没有奏效,所以接下来我将尝试更改纹理坐标!感谢您的提示。
    • 有效!只需计算百分比偏移 (0..1),更新纹理缓冲区,添加适当的缩放比例,不再需要透明度。
    【解决方案2】:

    将 alpha 纹理从 Android Bitmap 类加载到 OpenGL ES 并不能真正正常工作,因为 Bitmap 预乘 alpha 而 OpenGL ES 采用非预乘格式。当您进行更多混合时,您会看到这个问题。在为 OpenGL ES 加载纹理时,可以在着色器代码中反转预乘或避免使用 Bitmap 类。这个here 有更多内容。

    【讨论】:

      猜你喜欢
      • 2013-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-24
      • 2011-05-19
      • 1970-01-01
      相关资源
      最近更新 更多