Android OpenGL ES Прозрачный фон

Я создаю приложение для Android, которое использует OpenGL. Как бы то ни было, фон для GLSurfaceView динамически генерируется моим кодом и загружается как текстура и рисуется с помощью glDrawTexfOES. Что "нормально", но я могу просто отображать изображение гораздо плавно на свою поверхность (без OpenGL). Есть ли способ сделать фон GLSurfaceView прозрачным? Я слышал некоторые слухи, что это можно сделать с помощью setEGLConfigChooser, но я не нашел подтверждения. В конечном счете, я хотел бы взять поверхность, на которую я рисую, и поместить ее GLSurfaceView для достижения многоуровневого эффекта.

Я знаю, что это сложно, и, возможно, это невозможно, но любой вход оценивается. Спасибо заранее.

Ответ 1

Просто некоторые простые изменения, которые я сделал, чтобы заставить это работать.

На моем 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);
}

На моем GLSurfaceView:

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

Ответ 2

Для вашего GLSurfaceView также требуется setZOrderOnTop(true);

Ответ 3

Я использую свой собственный класс GLSurfaceView для отображения диаграмм (прозрачный фон/наложение). Мой расширенный GLSurfaceView встроен через XML в окно popover.

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

В качестве части действия я добавил этот код:

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

И последнее, но не менее важное: мой 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);     
    } 
}

Мой класс рендера GLPieChartRenderer вообще не вызывает glClearColor.

Ответ 4

Пример кода в конце означает включение прозрачности с помощью GLSurfaceView. Но прежде чем использовать прозрачность с помощью GLSurfaceView, рассмотрите следующие отрицательные моменты.

  • Включение прозрачности требует использования setZOrderOnTop на GLSurfaceView. Это помешает вам помещать любые другие виды (например, TextView) поверх прозрачного GLSurfaceView. Даже навигационные ящики не могут скользить над прозрачным GLSurfaceView (игнорируя трюки). Прозрачный или нет, GLSurfaceView может существовать только выше или ниже других видов Android, а не между ними.
  • Прозрачность требует, чтобы вы использовали setEGLConfigChooser и setFormat, как показано ниже. Это означает, что вы не можете получить то, что было бы стандартным форматом, выбранным системой, который был бы лучшим для этого конкретного устройства. Что еще более важно, вам нужно будет убедиться, что устройство имеет поддерживаемый формат и выбрали альтернативы, если ожидаемый формат отсутствует, как в этом gsoc example.

Другие варианты прозрачности.

  1. Запуск Tracer для opengl в Android, покажет, что фоновые изображения для действий рисуются как текстуры opengl. Поэтому вместо того, чтобы сделать GLSurfaceView прозрачным, если возможно, вы также можете сделать свой фон текстурой opengl в GLSurfaceView.
  2. Кроме того, альфа-канал или прозрачность на поверхности не являются предварительным требованием для альфа-смешивания в opengl. Оба они независимы.
  3. TextureView (трюк) является хорошей альтернативой, если ваш компонент opengl должен быть встроен между другими представлениями. Эта игра breakout является очень хорошим примером для рисунка GLSurfaceView 2d в Android.

Ниже образец с макетом xml и кодом для прозрачного GLSurfaceView с фоном.

  • Макет xml файла с цветным фоном green

    <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>
    
  • Файл 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 );
                }
            });
        }
    }
    

Ответ 5

вы должны убедиться, что фон активности прозрачен!

Если фокус активности непрозрачен, скажем, белый по умолчанию, то даже когда представление содержимого (glsurfaceview) является полупрозрачным, оно отображает белый фон активности в качестве фона.

Вы можете установить прозрачность фона в Android.manifest, где он объявлен, см. официальную демонстрацию API TranslucentGLSurfaceViewActivity для справки