Android OpenGL ES 透明背景

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2034822/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 04:17:54  来源:igfitidea点击:

Android OpenGL ES Transparent Background

androidopengl-esbackgroundtransparent

提问by mattbasta

I'm building an Android app that takes advantage of OpenGL. As it stands, the background for the GLSurfaceViewis dynamically generated by my code and loaded in as a texture and drawn with glDrawTexfOES. Which is "ok", but I can simply display the image much more smoothly to its own surface (without OpenGL). Is there any way that I can make the background of a GLSurfaceViewtransparent? I've heard some rumors that this can be done with setEGLConfigChooser, but I haven't found any confirmation. Ultimately, I'd like to take a surface which I'm drawing to and put the GLSurfaceViewover it to achieve a layered effect.

我正在构建一个利用 OpenGL 的 Android 应用程序。就目前而言, 的背景GLSurfaceView由我的代码动态生成并作为纹理加载并使用glDrawTexfOES. 这是“好的”,但我可以简单地将图像更平滑地显示到它自己的表面(没有 OpenGL)。有什么办法可以使背景GLSurfaceView透明?我听说过一些传言说这可以用 来完成setEGLConfigChooser,但我还没有找到任何确认。最终,我想取一个我正在绘制的表面并将其GLSurfaceView放在上面以实现分层效果。

I know this is a tricky and is quite possibly infeasible, but any input is appreciated. Thanks in advance.

我知道这是一个棘手的问题,而且很可能是不可行的,但任何输入都值得赞赏。提前致谢。

回答by mattbasta

Just some simple changes that I did to get this to work.

我只是做了一些简单的改变来让它发挥作用。

On my GLSurfaceView.Renderer:

在我的GLSurfaceView.Renderer

public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    gl.glDisable(GL10.GL_DITHER);
    gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,
            GL10.GL_FASTEST);

     gl.glClearColor(0,0,0,0);
     gl.glEnable(GL10.GL_CULL_FACE);
     gl.glShadeModel(GL10.GL_SMOOTH);
     gl.glEnable(GL10.GL_DEPTH_TEST);
}

On my GLSurfaceView:

在我的GLSurfaceView

setEGLConfigChooser(8, 8, 8, 8, 16, 0);
getHolder().setFormat(PixelFormat.TRANSLUCENT);

回答by Napalm

Your GLSurfaceViewalso requires setZOrderOnTop(true);

GLSurfaceView还需要setZOrderOnTop(true);

回答by Michael Biermann

I use my own GLSurfaceView class to display charts (transparent background / overlay). My extended GLSurfaceView is embed via XML into a popover window.

我使用自己的 GLSurfaceView 类来显示图表(透明背景/叠加)。我的扩展 GLSurfaceView 通过 XML 嵌入到弹出窗口中。

<com.dsignmatters.iq_fitfunlite.GLPieChartView          
    android:id="@+id/gameprogress_chart"
    android:layout_height="wrap_content" 
    android:layout_width="wrap_content"
    ...

As part of the activity I added this code:

作为活动的一部分,我添加了以下代码:

mGamesuccessPieChart = (GLSurfaceView) gameprogressView.findViewById(R.id.gameprogress_chart);
mGamesuccessPieChart.setZOrderOnTop(true);

Last but not least my GLSurfaceView looks like this:

最后但并非最不重要的是我的 GLSurfaceView 看起来像这样:

public class GLPieChartView extends GLSurfaceView {
    public GLPieChartView(Context context) {
        super(context);
        initGL();
    }

    public GLPieChartView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initGL();
    }

    void initGL() {
        setEGLContextClientVersion(2);
        setEGLConfigChooser(8,8,8,8,16,0);
        setRenderer(new GLPieChartRenderer());
        setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
        getHolder().setFormat(PixelFormat.TRANSLUCENT);     
    } 
}

My renderer class GLPieChartRendererdoes not call glClearColorat all.

我的渲染器类GLPieChartRenderer根本不调用glClearColor

回答by Kiran

Code sample at the end is for enabling transparency with GLSurfaceView. But before using transparency with GLSurfaceView, consider the following negative points.

最后的代码示例是使用GLSurfaceView. 但是在将透明度与 一起使用之前GLSurfaceView,请考虑以下负面因素。

  1. Enabling transparency requires that you use setZOrderOnTopon GLSurfaceView. That will prevent you from placing any other views ( e.g. TextView) on top of your transparent GLSurfaceView. Even Navigation drawers cannot slide above the transparent GLSurfaceView( ignoring tricks). Transparent or not, GLSurfaceViewcan only exist above or below other android views and not in between them.
  2. Transparency requires that you use setEGLConfigChooserand setFormatas in below example. That means, you cannot get what would have been default format chosen by system which would have been the best for that particular device. More importantly, you will need to ensure that the device has the supported format and chose alternatives if expected format isn't present as in this gsoc example.
  1. 启用透明度要求您使用setZOrderOnTopon GLSurfaceView。这将阻止您将任何其他视图(例如TextView)放在透明的顶部GLSurfaceView。即使导航抽屉也不能在透明上方滑动GLSurfaceView(忽略技巧)。透明与否,GLSurfaceView只能存在于其他 android 视图的上方或下方,不能存在于它们之间。
  2. 透明度要求您使用setEGLConfigChoosersetFormat,如下例所示。这意味着,您无法获得系统选择的最适合该特定设备的默认格式。更重要的是,您需要确保设备具有受支持的格式,并在此 gsoc示例中不存在预期格式时选择替代格式。

Other options to transparency.

透明度的其他选项

  1. Running Tracerfor opengl in Android, will show that, background images for activities are drawn as opengl textures. So instead of making GLSurfaceViewtransparent, if possible, you can as well render your background as an opengl texture in GLSurfaceView.
  2. Also, alpha channel or transparency on the surface is not pre requirement for alpha blending in opengl. Both are independent.
  3. TextureView(trick) is good alternative if your opengl component is to be embedded between other views. This breakoutgame is a very good example for GLSurfaceView2d drawing in Android.
  1. Tracer在 Android 中运行opengl,将显示活动的背景图像绘制为 opengl 纹理。因此GLSurfaceView,如果可能的话,您可以将背景渲染为 GLSurfaceView 中的 opengl 纹理,而不是透明。
  2. 此外,表面上的 alpha 通道或透明度不是 opengl 中 alpha 混合的先决条件。两者都是独立的。
  3. TextureView如果您的 opengl 组件要嵌入在其他视图之间,则(技巧) 是不错的选择。这个突破性游戏是GLSurfaceView在 Android 中进行2d 绘图的一个很好的例子。

Below sample with layout xml and code for transparent GLSurfaceViewwith background.

下面的示例带有布局 xml 和透明GLSurfaceView背景代码。

  1. Layout xml file with greencolor background

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:background="#00FFFF">
    
    <android.opengl.GLSurfaceView
        android:id="@+id/mySurfaceView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    
    </RelativeLayout>
    
  2. MainActivity.java file. Change ALPHAvariable from 0.0 to 1.0 to see surface color redmixing with background activity color green

    package com.example.transparentsurfaceview;
    
    import android.app.Activity;
    import android.graphics.PixelFormat;
    import android.opengl.GLES20;
    import android.opengl.GLSurfaceView;
    import android.os.Bundle;
    
    import javax.microedition.khronos.egl.EGLConfig;
    import javax.microedition.khronos.opengles.GL10;
    
    public class MainActivity extends Activity {
    
        private GLSurfaceView mSurfaceView;
        private static float ALPHA = 0.5f;
        private static float RED   = 1.0f;
        private static float GREEN = 0.0f;
        private static float BLUE  = 0.0f;
    
        protected void onCreate( Bundle savedInstanceState ) {
            super.onCreate( savedInstanceState );
            setContentView( R.layout.activity_main );
            mSurfaceView = (GLSurfaceView)findViewById( R.id.mySurfaceView );
    
            mSurfaceView.setEGLContextClientVersion( 2 );
            mSurfaceView.setZOrderOnTop( true );
            mSurfaceView.setEGLConfigChooser( 8, 8, 8, 8, 16, 0 );
            mSurfaceView.getHolder().setFormat( PixelFormat.RGBA_8888 );
    
            mSurfaceView.setRenderer( new GLSurfaceView.Renderer() {
                public void onSurfaceCreated( GL10 gl10, EGLConfig eglConfig ) {
                    GLES20.glClearColor( RED, GREEN, BLUE, ALPHA );
                }
    
                public void onSurfaceChanged( GL10 gl10, int i, int i2 ) {}
    
                public void onDrawFrame( GL10 gl10 ) {
                    GLES20.glClear( GLES20.GL_COLOR_BUFFER_BIT );
                }
            });
        }
    }
    
  1. 具有green彩色背景的布局 xml 文件

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:background="#00FFFF">
    
    <android.opengl.GLSurfaceView
        android:id="@+id/mySurfaceView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    
    </RelativeLayout>
    
  2. MainActivity.java 文件。将ALPHA变量从 0.0更改为 1.0 以查看表面颜色red与背景活动颜色的混合green

    package com.example.transparentsurfaceview;
    
    import android.app.Activity;
    import android.graphics.PixelFormat;
    import android.opengl.GLES20;
    import android.opengl.GLSurfaceView;
    import android.os.Bundle;
    
    import javax.microedition.khronos.egl.EGLConfig;
    import javax.microedition.khronos.opengles.GL10;
    
    public class MainActivity extends Activity {
    
        private GLSurfaceView mSurfaceView;
        private static float ALPHA = 0.5f;
        private static float RED   = 1.0f;
        private static float GREEN = 0.0f;
        private static float BLUE  = 0.0f;
    
        protected void onCreate( Bundle savedInstanceState ) {
            super.onCreate( savedInstanceState );
            setContentView( R.layout.activity_main );
            mSurfaceView = (GLSurfaceView)findViewById( R.id.mySurfaceView );
    
            mSurfaceView.setEGLContextClientVersion( 2 );
            mSurfaceView.setZOrderOnTop( true );
            mSurfaceView.setEGLConfigChooser( 8, 8, 8, 8, 16, 0 );
            mSurfaceView.getHolder().setFormat( PixelFormat.RGBA_8888 );
    
            mSurfaceView.setRenderer( new GLSurfaceView.Renderer() {
                public void onSurfaceCreated( GL10 gl10, EGLConfig eglConfig ) {
                    GLES20.glClearColor( RED, GREEN, BLUE, ALPHA );
                }
    
                public void onSurfaceChanged( GL10 gl10, int i, int i2 ) {}
    
                public void onDrawFrame( GL10 gl10 ) {
                    GLES20.glClear( GLES20.GL_COLOR_BUFFER_BIT );
                }
            });
        }
    }
    

回答by bismack163

you should make sure the activity background is transparent!

你应该确保活动背景是透明的!

If the activity's background is opaque, say white by default, then even when the content view (the glsurfaceview) is translucent, it will display the activity's white background as its background.

如果活动的背景是不透明的,默认情况下为白色,那么即使内容视图(glsurfaceview)是半透明的,它也会显示活动的白色背景作为其背景。

You can set the activity background transparency in the Android.manifest where it is declared, see the official API demo TranslucentGLSurfaceViewActivity for help

可以在Android.manifest中设置activity的背景透明度,帮助查看官方API演示TranslucentGLSurfaceViewActivity