GLSurfaceView - 如何制作半透明背景

时间:2013-07-26 10:10:06

标签: android background opengl-es-2.0 transparent

我尝试使用GLSurfaceView进行渲染,并通过docs设置格式:

getHolder().setFormat(PixelFormat.TRANSLUCENT);

我使用GLSurfaceView.Renderer,它绘制onDrawFrame:

GLES20.glClearColor(0, 0, 1, .5f);
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);

但是,GLSurfaceView中的GL渲染不是半透明的,并且是完全蓝色的。如果我省略了glClear调用,那么它就完全是黑色。

如何使GL渲染具有透明背景,以便与后面绘制的视图混合?

enter image description here

编辑:这是我的GLSurfaceView:

class GLView extends GLSurfaceView{
   MyRenderer r;
   public GLView(Context ctx){
      super(ctx);
      setEGLContextClientVersion(2);

      getHolder().setFormat(PixelFormat.TRANSLUCENT);

      setEGLConfigChooser(8, 8, 8, 8, 16, 0);
      r = new MyRenderer(getContext());
      setRenderer(r);
   }
}

5 个答案:

答案 0 :(得分:6)

好的,经过一些研究后我可以自己回答。

我终于使用SurfaceView.setZOrderOnTop(true)以透明度绘制。但后来我失去了在GLSurfaceView上放置其他视图的可能性。

我结束了两个可能的结果:

behind on top

左侧是所有其他视图下方的标准GL曲面,无法使用透明度绘制,因为GL曲面在应用程序的窗口表面之前绘制,而GLSurfaceView仅在其punches hole位置绘制,以便可以看到GL曲面通过

右边是用setZOrderOnTop(true)绘制的透明GL表面,因此其表面绘制在应用程序窗口的顶部。现在它是透明的,但是在视图层次结构中放置在其上的其他视图之上。

因此,应用程序似乎有一个窗口,其视图层次结构具有表面,而SurfaceView具有自己的GL表面,可能位于应用程序窗口的顶部或下方。遗憾的是,透明的GL视图无法在视图层次结构中正确排序,其中包含其他视图。

答案 1 :(得分:5)

您需要RGBA 8888像素格式才能实现半透明:

private void init( boolean translucent, int depth, int stencil )
{
    /* By default, GLSurfaceView() creates a RGB_565 opaque surface.
     * If we want a translucent one, we should change the surface's
     * format here, using PixelFormat.TRANSLUCENT for GL Surfaces
     * is interpreted as any 32-bit surface with alpha by SurfaceFlinger.
     */
    this.getHolder().setFormat( PixelFormat.RGB_565 );
    if ( translucent )
    {
        this.getHolder().setFormat( PixelFormat.TRANSLUCENT );
    }

    setEGLContextFactory( new ContextFactory() );

    /* We need to choose an EGLConfig that matches the format of
     * our surface exactly. This is going to be done in our
     * custom config chooser. See ConfigChooser class definition
     * below.
     */
    setEGLConfigChooser( translucent ?
                         new ConfigChooser( 8, 8, 8, 8, depth, stencil ) :
                         new ConfigChooser( 5, 6, 5, 0, depth, stencil ) );

    setRenderer( new Renderer() );
}

答案 2 :(得分:1)

您是否考虑过将LayerDrawable与setAlpha一起使用?这是一个我有两个图像的例子......一个是透明的(由setAlpha),另一个不是。 'calendar_cell'是实心的,位于背面,然后是透明的框,用于显示其后面的日历单元格。这样,您可以根据需要堆叠任意数量的图像,为它们提供不同的透明度。

Drawable []layers = new Drawable [2];
int imageResource1 = mContext.getResources().getIdentifier("drawable/calendar_cell", null, mContext.getPackageName());
Drawable background = v.getResources().getDrawable(imageResource1);
                        layers [0]= background;

int imageResource = mContext.getResources().getIdentifier("drawable/box_" + box, null, mContext.getPackageName());
Drawable boxImg = v.getResources().getDrawable(imageResource);
    boxImg.setAlpha(100);
    layers [1]= boxImg;

LayerDrawable layerDrawable = new LayerDrawable (layers);
v.setBackground(layerDrawable)

答案 3 :(得分:0)

我不确定问题究竟是什么,但另一种选择可能是用半透明的彩色矩形覆盖屏幕,只清除深度缓冲位。

Is there any alternative for GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)?

否则确保深度缓冲位为1

我会稍后再回来尝试在我可以的时候在手机上重新创建问题。

编辑:我刚刚意识到它出现蓝色的原因可能是你将它设置为.5f所以它只需要2次调用就可以获得完整的1f不透明度。这意味着需要以30fps的1/15秒才能完全变蓝。

尝试将Alpha透明度值降低到0.01f或0.05f

答案 4 :(得分:0)

尝试将setZOrderMediaOverlay(true)用于具有硬件加速的GLSurfaceView,并将Activity设置为false。这使得GLSurfaceView背景透明化。但我不确定硬件加速会如何影响它。
Overlaying a GLSurface on top of a MapView without using SetZOrderTop。 我最近发布了一个问题,仍在寻找更好的解决方案