【问题标题】:GLSurfaceView - how to make translucent backgroundGLSurfaceView - 如何制作半透明背景
【发布时间】:2018-05-30 08:48:04
【问题描述】:

我尝试使用 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 渲染具有透明背景,以便与在其后面绘制的视图混合?

编辑:这是我的 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);
   }
}

【问题讨论】:

    标签: android background opengl-es-2.0 transparent


    【解决方案1】:

    好的,经过一番研究,我可以自己回答这个问题。

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

    我以两种可能的结果结束:

    左侧是所有其他视图下方的标准 GL 表面,不能以透明度绘制,因为 GL 表面是在应用程序的窗口表面之前绘制的,而 GLSurfaceView 只是在其位置punches hole,因此可以看到 GL 表面。

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

    所以看起来应用程序有一个带有表面的窗口作为其视图层次结构,而 SurfaceView 有自己的 GL 表面,它可能位于应用程序窗口的顶部或下方。不幸的是,透明 GL 视图无法在视图层次结构中正确排序,其他视图位于其之上。

    【讨论】:

    • 你为什么不奖励你的赏金?
    • 我不能给自己的答案颁奖,其他的答案也不让我满意。
    【解决方案2】:

    半透明需要 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() );
    }
    

    【讨论】:

    • 从我的问题中可以看出,我设置了 PixelFormat.TRANSLUCENT。
    • 你设置成8888了吗?
    • 是的,也试过这个。但是文档提到应该设置 PixelFormat.TRANSLUCENT。
    • 能否请您显示您的getHolder().setFormat(PixelFormat.TRANSLUCENT) 周围的所有代码?
    • 能否请您检查一下这个解决方案:stackoverflow.com/a/3190604/1065190 和这个stackoverflow.com/a/2196281/1065190 有帮助吗?
    【解决方案3】:

    您是否考虑过将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)
    

    【讨论】:

      【解决方案4】:

      我不确定到底是什么问题,但另一种方法是用半透明的彩色矩形覆盖屏幕并清除深度缓冲区位。

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

      否则请确保您的深度缓冲区位为 1

      我稍后会回来尝试在我的手机上重现问题。

      编辑:我刚刚意识到它显示为蓝色的原因可能是您将其设置为 0.5f,因此只需 2 次调用即可使其完全达到 1f 不透明度。这意味着它需要 30fps 1/15 秒才能完全变蓝。

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

      【讨论】:

      • 理论错误,即使将 alpha 设置为 0 也没有改变。也许你认为清除增加了以前清除的价值。但是,Surface Flinger 应该正确组成屏幕表面,包括 GL 表面的 Alpha 通道。
      【解决方案5】:

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

      【讨论】:

        猜你喜欢
        • 2011-06-15
        • 2013-09-06
        • 1970-01-01
        • 2021-12-09
        • 2023-03-23
        • 1970-01-01
        • 1970-01-01
        • 2015-11-12
        相关资源
        最近更新 更多