GLSurfaceView-как сделать полупрозрачный фон

Я пытаюсь визуализировать с помощью GLSurfaceView и docs я поставил формат:

getHolder().setFormat(PixelFormat.TRANSLUCENT);

Я использую GLSurfaceView.Рендерер, который рисует onDrawFrame:

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

однако рендеринг GL в GLSurfaceView не является полупрозрачным и полностью синим. Если я опущу glClear call, то он полностью черный.

как сделать рендеринг 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 ответов


ОК, после некоторых исследований, я могу ответить на это сам.

Я, наконец, сделал это, чтобы быть нарисованным с прозрачностью, используя SurfaceView.setZOrderOnTop (true). Но затем я потерял возможность разместить другие виды поверх моего GLSurfaceView.

Я закончил с двумя возможными результатами:

behindon top

слева находится стандартная поверхность GL под всеми другими видами, которая не может быть нарисована с прозрачностью, потому что поверхность GL рисуется перед окном приложения поверхность и GLSurfaceView просто пунши отверстия в своем положении так, что поверхность ГЛ будет увидена до конца.

справа-прозрачная поверхность GL, нарисованная с помощью setZOrderOnTop (true), таким образом, ее поверхность нарисована поверх окна приложения. Теперь он прозрачен, но нарисован поверх других представлений, размещенных на нем в иерархии представлений.

таким образом, кажется, что приложение имеет одно окно с поверхностью для иерархии представлений, а SurfaceView имеет собственную поверхность для GL, которая может быть включена сверху или снизу окна приложения. К сожалению, прозрачное представление GL не может быть правильно упорядочено внутри иерархии представлений с другими представлениями поверх нее.


вам нужен формат пиксела РГБА 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() );
}

вы думали об использовании 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)

Я не уверен, в чем проблема, но альтернативой может быть покрытие экрана полупрозрачным цветным прямоугольником и просто очистка бита буфера глубины.

есть ли альтернатива для GLES20.glClear (GLES20.GL_COLOR_BUFFER_BIT)?

в противном случае убедитесь, что ваш бит буфера глубины равен 1

Я вернусь позже, чтобы попытаться воссоздать проблему на моем телефоне немного, когда я могу.

редактировать: я просто понял, что причина, по которой он кажется синим, может быть в том, что вы установили его .5f, поэтому для него требуется только 2 вызова, чтобы получить полную непрозрачность 1f. это означает, что он занимает 30fps 1 / 15th секунды, чтобы полностью синий.

попробуйте снизить значение альфа-прозрачности до 0,01 f или 0,05 f


попробуйте использовать setZOrderMediaOverlay (true) для GLSurfaceView с аппаратным ускорением для действия, установленного в false. Это делает фон GLSurfaceView прозрачным. Но я не уверен, как аппаратное ускорение влияет на него.
наложение GLSurface поверх MapView без использования SetZOrderTop.
недавно я опубликовал вопрос, который все еще ищет лучшее решение