android - programacion - ¿Cómo puedo usar varios componentes de GLSurfaceView en el mismo diseño?
manual de programacion android pdf (6)
¿Cuál es la implementación para CoordinateSystemRenderer
?
Hoy GLSurfaceView
con el mismo requisito y lo intenté, en realidad funciona, lo que significa que puedes poner 2 GLSurfaceView
en la misma actividad.
Algo hay que tener en cuenta,
- En
GLRender
, cuando se invocaonSurfaceChanged
, debe cambiar el tamaño de su ventanaonSurfaceChanged
- Con 2
GLSurfaceView
, el subproceso de procesamiento será 2, por lo que se producirá un problema de sincronización. Depende de su implementación deonDrawFrame
.
Hay una prueba rápida para usar la demostración de la API de Android 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;
}
Estoy escribiendo una API de visualización de información para Android y me encontré con un problema al intentar colocar dos unidades de una GLSurfaceView
personalizada en un diseño. El Custom GLSurfaceView
en este punto es simplemente una extensión del GLSurfaceView
para eliminar posibles fallas causadas por métodos personalizados.
Cuando tengo ambos componentes agregados en el diseño e inicio 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 Renderers se imprimen en LogCat. Sin embargo, funciona perfectamente bien si solo uso uno de los componentes personalizados de GLSurfaceView
.
Leí que hay un problema al usar GLSurfaceView
en múltiples actividades y supongo que también se aplica cuando se usan dos de esos componentes al mismo tiempo. He intentado la solución publicada here pero parece que tampoco puedo hacer que funcione.
Apreciaría cualquier ayuda. Elijo usar OpenGL para un mejor rendimiento, pero si no puedo usar varios componentes a la vez, supongo que tendré que usar Canvas en su lugar.
El manifiesto se ve como sigue:
<?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 así:
@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();
}
¿Me estoy perdiendo algo obvio? ¿O alguien puede explicar por qué no funciona?
Aquí hay una forma alternativa de hacerlo. Descargue la muestra de los documentos de 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'' con mi lista 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 usar solo una vista pero con potencialmente múltiples objetivos de Render. Aunque debo administrarme, no estoy seguro de que lo que intentas hacer esté mal o no. Soy un poco nuevo para OpenGLES. Tengo una biblioteca de código abierto OpenGL en bitbucket. Puede obtener algunas ideas de él: https://bitbucket.org/warwick/hacergestov2 , es una biblioteca de gestos.
Es posible que desee investigar la superposición / subyacente de sus modelos en el área ''correcta'' de la pantalla utilizando una pantalla completa GLSurfaceView. Es posible que desee armar algún tipo de marco de diseño para hacer esto más simple, o tal vez usar múltiples Viewports en la pantalla completa GLSurfaceView. No he intentado esto en OpenGL ES, pero en general, cualquiera de estos métodos sería el usado para renderizar múltiples vistas del mismo o incluso muchos modelos diferentes en una sola aplicación en un sistema de escritorio en lugar de usar múltiples GLContexts (si eso es lo que es pasando detrás de las escenas aquí).
Hay muchas cosas detrás de GLSurfaceView, incluida la administración de GLContext. Estoy bastante seguro de que no podrá hacer que funcione, incluso si tiene éxito, podría tener más problemas inesperados más adelante. Así que realmente creo que no es la arquitectura de aplicación correcta.
Puede tener múltiples GLSurfaceViews
activas y visibles en una actividad. Cada vista tiene su propio contexto GL.
[ACTUALIZACIÓN: Esta respuesta ya no es correcta, a partir de Android 5.0 (Lollipop) . Vea la respuesta de fadden para una discusión y enlaces. También era incorrecto a partir de Android 2.0, y aparentemente era solo un problema para las superficies OVERLAPPING incluso antes de esa fecha. ]
No puede colocar 2 SurfaceViews (SV) en una actividad. Para entender por qué debes saber cómo funcionan los SV.
Cuando lo creas y colocas en la actividad, en realidad no se colocará en la actividad (o encima 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 manera de crear algo así en las plataformas anteriores.