¿Cómo puedo utilizar varios componentes GLSurfaceView en el mismo Layout?

Estoy escribiendo una API de visualización de información para Android y me encontré con un problema al intentar colocar dos unidades de un GLSurfaceView personalizado en un Layout. El GLSurfaceView personalizado en este punto es simplemente una extensión de GLSurfaceView para eliminar posibles errores causados ​​por métodos personalizados.

Cuando tengo los dos componentes agregados en el diseño e iniciar la aplicación se ejecuta. Pero nada se dibuja, parece que entra en un bucle infinito. Porque los mensajes de depuración dentro de los procesadores se imprimen en el LogCat. Sin embargo, funciona perfectamente bien si sólo uso uno de los componentes GLSurfaceView personalizados.

He leído que hay un problema con GLSurfaceView en múltiples actividades y supongo que también se aplica cuando se utilizan dos de esos componentes al mismo tiempo. He intentado el workaround fijado aquí pero no puedo parecer conseguirlo trabajar tampoco.

Apreciaría cualquier ayuda. Opto por usar openGL para el mejor rendimiento, pero si no puedo usar múltiples componentes a la vez supongo que tendré que usar Canvas en su lugar.

El manifiesto tiene la siguiente apariencia:

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:text="@string/hello" android:id="@+id/TextView01" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <com.syntronic.vtadlib.VisualizationView android:id="@+id/glview" android:layout_width="fill_parent" android:layout_height="300px" /> <TextView android:text="@string/hello" android:id="@+id/TextView02" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <com.syntronic.vtadlib.VisualizationView android:id="@+id/glview2" android:layout_width="fill_parent" android:layout_height="fill_parent" /> </LinearLayout> </LinearLayout> 

De la actividad el código es como esto:

 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mSurfaceView = (VisualizationView) findViewById(R.id.glview); mSurfaceView2 = (VisualizationView) findViewById(R.id.glview2); //Enables debug flags for Errors //mSurfaceView.setDebugFlags(GLSurfaceView.DEBUG_CHECK_GL_ERROR); //mSurfaceView2.setDebugFlags(GLSurfaceView.DEBUG_CHECK_GL_ERROR); mSurfaceView.setRenderer(new CoordinateSystemRenderer()); mSurfaceView2.setRenderer(new CoordinateSystemRenderer()); } @Override protected void onPause() { // TODO Auto-generated method stub super.onPause(); mSurfaceView.onPause(); mSurfaceView2.onPause(); } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); mSurfaceView.onResume(); mSurfaceView2.onResume(); } 

¿Estoy perdiendo algo obvio? ¿O alguien puede explicar por qué no funciona?

[UPDATE: Esta respuesta ya no es correcta, a partir de Android 5.0 (Lollipop) . Vea la respuesta de fadden para una discusión, y los acoplamientos. También era incorrecto a partir de Android 2.0, y al parecer sólo era un problema para las superficies OVERLAPPING incluso antes de entonces. ]

No puede colocar 2 SurfaceViews (SV) en una actividad. Para entender por qué usted debe saber cómo funciona SVs.

Cuando se crea y se coloca en la actividad que realmente no se colocará en la actividad (o parte superior de ella), sino que se creará detrás de la actividad actual con la vista "transparente" creada en esa actividad.

En Android 4.0 (API 14) hay una nueva vista llamada TextureView No hay forma de crear algo parecido a eso Ver en las plataformas más antiguas.

¿Cuál es la implementación de CoordinateSystemRenderer ?

Conocí el mismo requisito hoy y lo intenté, realmente funciona eso significa, puedes poner 2 GLSurfaceView en la misma actividad.

Algo necesita ser notado,

  1. En GLRender , cuando onSurfaceChanged se invoca, debe cambiar el tamaño de su ventana de visualización
  2. Con 2 GLSurfaceView , el hilo de render será 2, así que se sincronizará el problema. Depende de su implementación de onDrawFrame .

Hay una prueba rápida para usar la demostración de Android API en SDK GLSurfaceViewActivity

 /* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.android.apis.graphics; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.opengl.GLSurfaceView; /** * Render a pair of tumbling cubes. */ public class CubeRenderer implements GLSurfaceView.Renderer { boolean isReverse = false; public CubeRenderer(boolean useTranslucentBackground, boolean isReverse) { mTranslucentBackground = useTranslucentBackground; mCube = new Cube(); this.isReverse = isReverse; } public CubeRenderer(boolean useTranslucentBackground) { this(useTranslucentBackground, false); } public void onDrawFrame(GL10 gl) { /* * Usually, the first thing one might want to do is to clear the screen. The most efficient way of doing this is * to use glClear(). */ gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); /* * Now we're ready to draw some 3D objects */ gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadIdentity(); gl.glTranslatef(0, 0, -3.0f); gl.glRotatef(mAngle, 0, 1, 0); gl.glRotatef(mAngle * 0.25f, 1, 0, 0); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_COLOR_ARRAY); mCube.draw(gl); gl.glRotatef(mAngle * 2.0f, 0, 1, 1); gl.glTranslatef(0.5f, 0.5f, 0.5f); mCube.draw(gl); if (isReverse) { mAngle -= 1.2f; } else { mAngle += 1.2f; } } public void onSurfaceChanged(GL10 gl, int width, int height) { System.out.println("Joey's Log width : " + width + " height : " + height); gl.glViewport(0, 0, width, height); /* * Set our projection matrix. This doesn't have to be done each time we draw, but usually a new projection needs * to be set when the viewport is resized. */ float ratio = (float) width / height; gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity(); gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10); } public void onSurfaceCreated(GL10 gl, EGLConfig config) { /* * By default, OpenGL enables features that improve quality but reduce performance. One might want to tweak that * especially on software renderer. */ gl.glDisable(GL10.GL_DITHER); /* * Some one-time OpenGL initialization can be made here probably based on features of this particular context */ gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST); if (mTranslucentBackground) { gl.glClearColor(0, 0, 0, 0); } else { gl.glClearColor(1, 1, 1, 1); } gl.glEnable(GL10.GL_CULL_FACE); gl.glShadeModel(GL10.GL_SMOOTH); gl.glEnable(GL10.GL_DEPTH_TEST); } private boolean mTranslucentBackground; private Cube mCube; private float mAngle; } ------------------------------------------------------------------------------------------ /* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.android.apis.graphics; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.opengl.GLSurfaceView; /** * Render a pair of tumbling cubes. */ public class CubeRenderer implements GLSurfaceView.Renderer { boolean isReverse = false; public CubeRenderer(boolean useTranslucentBackground,boolean isReverse) { mTranslucentBackground = useTranslucentBackground; mCube = new Cube(); this.isReverse = isReverse; } public CubeRenderer(boolean useTranslucentBackground) { this(useTranslucentBackground, false); } public void onDrawFrame(GL10 gl) { /* * Usually, the first thing one might want to do is to clear * the screen. The most efficient way of doing this is to use * glClear(). */ gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); /* * Now we're ready to draw some 3D objects */ gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadIdentity(); gl.glTranslatef(0, 0, -3.0f); gl.glRotatef(mAngle, 0, 1, 0); gl.glRotatef(mAngle*0.25f, 1, 0, 0); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_COLOR_ARRAY); mCube.draw(gl); gl.glRotatef(mAngle*2.0f, 0, 1, 1); gl.glTranslatef(0.5f, 0.5f, 0.5f); mCube.draw(gl); if (isReverse) { mAngle -= 1.2f; } else { mAngle += 1.2f; } } public void onSurfaceChanged(GL10 gl, int width, int height) { System.out.println("Joey's Log width : " + width + " height : " + height); gl.glViewport(0, 0, width, height); /* * Set our projection matrix. This doesn't have to be done * each time we draw, but usually a new projection needs to * be set when the viewport is resized. */ float ratio = (float) width / height; gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity(); gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10); } public void onSurfaceCreated(GL10 gl, EGLConfig config) { /* * By default, OpenGL enables features that improve quality * but reduce performance. One might want to tweak that * especially on software renderer. */ gl.glDisable(GL10.GL_DITHER); /* * Some one-time OpenGL initialization can be made here * probably based on features of this particular context */ gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST); if (mTranslucentBackground) { gl.glClearColor(0,0,0,0); } else { gl.glClearColor(1,1,1,1); } gl.glEnable(GL10.GL_CULL_FACE); gl.glShadeModel(GL10.GL_SMOOTH); gl.glEnable(GL10.GL_DEPTH_TEST); } private boolean mTranslucentBackground; private Cube mCube; private float mAngle; } 

Hay mucho que va detrás del GLSurfaceView incluyendo la gestión de GLContext, estoy bastante seguro de que no será capaz de hacer que funcione, incluso si tiene éxito que podría entrar en más inesperado problemas más adelante. Así que realmente creo que no es la arquitectura de aplicación correcta.

Es posible que desee investigar la superposición / subconjunto de sus modelos en el área "correcta" de la pantalla con una pantalla completa GLSurfaceView. Es posible que desee montar algún tipo de marco de diseño para hacer esto más simple, o tal vez utilizando múltiples vistas en la pantalla completa GLSurfaceView. No han probado estos en OpenGL ES, pero generalmente cualquiera de estos métodos sería el utilizado para procesar múltiples vistas del mismo o incluso muchos modelos diferentes en una sola aplicación en un sistema de escritorio en lugar de utilizar GLContexts múltiples (si eso es lo que es Pasando por detrás de las escenas aquí).

Aquí está una manera alternativa de hacerlo. Descargue el ejemplo de los documentos Android aquí: http://developer.android.com/shareables/training/OpenGLES.zip En este archivo zip verá 2 proyectos. Abra el proyecto: HelloOpenGLES20 y reemplace la clase 'MyGLRenderer' por la que aparece a continuación y ejecute el proyecto.

 package com.example.android.opengl; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.opengl.GLES20; import android.opengl.GLSurfaceView; import android.opengl.Matrix; import android.util.Log; public class MyGLRenderer implements GLSurfaceView.Renderer { private static final String TAG = "MyGLRenderer"; private Triangle[] mTriangle = new Triangle[2]; private final float[] mMVPMatrix = new float[16]; private final float[] mProjectionMatrix = new float[16]; private final float[] mViewMatrix = new float[16]; private final float[] mRotationMatrix = new float[16]; private float mAngle; @Override public void onSurfaceCreated(GL10 unused, EGLConfig config) { GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); mTriangle[0] = new Triangle(); mTriangle[1] = new Triangle(); } @Override public void onDrawFrame(GL10 unused) { final float[] scratch = new float[16]; GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f); Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0); for(int i = 0; i < 2; i++) { if(i % 2 == 0) { Matrix.setRotateM(mRotationMatrix, 0, mAngle / 2f, 0, 0, 1.0f); } else { Matrix.setRotateM(mRotationMatrix, 0, mAngle / 4f, 0, 0, 1.0f); } Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0); mTriangle[i].draw(scratch); }//End for(int i = 0; i < 2; i++) }//End public void onDrawFrame(GL10 unused) @Override public void onSurfaceChanged(GL10 unused, int width, int height) { GLES20.glViewport(0, 0, width, height); float ratio = (float) width / height; Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7); } public static int loadShader(int type, String shaderCode){ int shader = GLES20.glCreateShader(type); GLES20.glShaderSource(shader, shaderCode); GLES20.glCompileShader(shader); return shader; } public static void checkGlError(String glOperation) { int error; while((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) { Log.e(TAG, glOperation + ": glError " + error); throw new RuntimeException(glOperation + ": glError " + error); } } public float getAngle() { return mAngle; } public void setAngle(float angle) { mAngle = angle; } } 

Por lo que entiendo, OpenGLES está diseñado para utilizar sólo una vista, pero con potencialmente múltiples objetivos de renderizado. Aunque debo admin no estoy seguro de que lo que estás tratando de hacer está mal o no. Soy un poco un newb para OpenGLES yo mismo. Tengo una biblioteca abierta de OpenGL en bitbucket. Usted puede ser capaz de obtener algunas ideas de ella: https://bitbucket.org/warwick/hacergestov2 , es una biblioteca de gestos.

Puede tener varias GLSurfaceViews activas y visibles en una actividad. Cada vista obtiene su propio contexto GL.

  • Android sólo juego en OpenGL: rendimiento en C ++ (NDK) vs Java (Dalvik)
  • Android, Transparente sub-GLSurfaceView en el diseño?
  • Cómo utilizar correctamente glDiscardFramebufferEXT
  • ¿Hay alguna forma de ignorar las imágenes libgdx Limitación? (las imágenes deben ser potencia de dos)
  • 'Texture2D': No se encontró ninguna función sobrecargada equivalente OpenGL ES2 Android (JAVA)
  • DrawerLayout ListView no dibujado con GLSurfaceVer como contenido
  • Simulación de swaps de paletas con Shaders OpenGL (en LibGDX)
  • ¿Coordenadas OpenGL para coincidir con las coordenadas de la pantalla?
  • Sombras de OpenGL ES para los sprites 2D
  • Android: LibGDX 2D consumo de memoria del juego
  • Alternativa para glBlitFrameBuffer () en OpenGL ES 2.0
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.