2013-04-24 10 views
5

Piszę pewną aplikację OpenGL gdzie bym specjalnie lubią rysować ramki stopniowo. W tym celu chciałbym wyłączyć automatyczne usuwanie bufora, które rozumiem, jest domyślnym zachowaniem GLSurfaceView.Renderer.onDrawFrame(). Czy ktoś może mi pomóc, jak to zrobić? Muszę napisać aplikację w Javie, nie używając natywnego SDK.Automatyczny bufor jasne podczas korzystania z OpenGL na Androida

Rozumiem, że mógłbym to zrobić: -

(1) setting EGL_SWAP_BEHAVIOR_PRESERVED_BIT bit for EGL_SURFACE_TYPE attribute while doing [eglChooseConfig][1](), and 
(2) setting EGL_SWAP_BEHAVIOR attribute to EGL_BUFFER_PRESERVED by calling [eglSurfaceAttrib][2] on the EGLSurface object 

jednak wnoszę z doc Khronos, że: -

"EGL_SWAP_BEHAVIOR_PRESERVED_BIT are supported only if the EGL version is 1.4 or greater." 
"EGL_SWAP_BEHAVIOR is supported only if the EGL version is 1.2 or greater." 

Teraz rozumiem, że mogę uzyskać dostęp EGL w dwa sposoby, w mojej aplikacji Android: -

(1) use the Khronos API class [EGL10][3] in javax.microedition.khronos.egl package (EGL11 doesn't seem to be implemented yet) 
(2) use the Android API class [EGL14][4] in android.opengl package (similar to using class android.opengl.GLES20) 

problem z (1) jest to, że wersja jest < 1.4, więc nie obsługuje potrzebnej mi funkcjonalności. Problem z (2) jest to, że moja aplikacja po prostu zawiesza się w chwili, kiedy wywołać dowolną metodę w EGL14, a ja nie wiem, jak mam go używać (nie mogłem znaleźć jeden przykład program/tutorial jak EGL14 ma być używany w aplikacji). W szczególności chciałbym dowiedzieć się, jak ważny kontekst GL z EGL14: w przypadku EGL10 mogłem zrobić wywołując javax.microedition.khronos.egl.EGLContext.getGL(). Jednak nie widzę żadnej równoważnej metody w klasie android.opengl.EGLContext. W rzeczywistości wszystkie klasy związane z EGL w android.opengl z wyjątkiem EGL14 wydają się być w większości puste.

Moim najlepszym pomysłem było podążanie tą samą linią rozumowania, jak w przypadku GLES20: wywoływanie metod tylko wewnątrz metod GLSurfaceView.Renderer: onDrawFrame(), onSurfaceCreated(), onSurfaceChanged(), ponieważ te zaopatrzenie jest ważne GL (GL10) i EGL (EGLConfig) konteksty jako argumenty. Włożyłem więc następujący kod wewnątrz onDrawFrame(): -

public void onDrawFrame(GL10 gl) 
{ 
    ... 
    android.opengl.EGLDisplay d = null; 
    if ((d = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY)) == EGL14.EGL_NO_DISPLAY) { 
     Log.i("Triangle", "EGL14.eglGetDisplay() failed!"); 
    } else { 
     Log.i("Triangle", "EGL14.eglGetDisplay() succeeded!"); 
    } 
    ... 
} 

wierzę, że nie będzie musiał instancję EGL14 przed wywołaniem wyżej ponieważ wszystkie metody są statyczne. Jednak wywołanie funkcji EGL14.eglGetDisplay() powoduje awarię aplikacji.

Każda pomoc będzie mile widziane, dzięki :)

+0

Witam, byłem w obliczu tego samego problemu, a ja po prostu okazało się, że mój problem był wezwaniem do „glColorMask” , po usunięciu mojego wezwania do tej metody wszystko zostało rozwiązane. Prawdopodobnie przyczyna twojego problemu jest inna, ale na wszelki wypadek, gdy ci pomoże, podam ci wskazówkę. – PerracoLabs

Odpowiedz

0

Zamiast EGL bezpośrednio, można przedłużyć GLSurfaceView i nazywają setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); na init.

To ustawienie zapobiega ponownemu rysowaniu ramki GLSurfaceView do czasu wywołania metody requestRender(), która jest bardziej wydajna w przypadku tej przykładowej aplikacji.

Zobacz dokumentację Android 1, jak skonfigurować GLES z Javą.

Building an OpenGL ES Environment

+1

Dzięki za odpowiedź, ale myślę, że źle zrozumiałeś moje pytanie. Nie chcę kontrolować, kiedy nowa ramka jest narysowana (w sposób ciągły lub na żądanie). To, czego chcę, to to, że gdy nowa ramka zostanie narysowana, nie powinna automatycznie czyścić zawartości poprzedniej ramki (tak jak domyślne zachowanie onDrawFrame()). Innymi słowy, zawartość już narysowana w jednej ramce powinna zostać zachowana, a następna ramka powinna zostać narysowana na górze poprzedniej ramki. –

+0

Czy możesz po prostu zastąpić na DrawFrame, aby nic nie robić? Jeśli jego domyślnym działaniem jest wywołanie glClear. – torbjoernwh

1

Wersja EGL realizowana może być wyższa niż interfejs, którego używasz. Rzeczywista wersja jest zwracana przez EGL10.eglInitialize(). Jeśli to [1,4] lub wyższy, można przekazać [EGL10.EGL_SURFACE_TYPE, EGL14.EGL_SWAP_BEHAVIOR_PRESERVED_BIT] podczas rozmowy EGL10.eglChooseConfig(). Używanie EGL14 definicji EGL14 z EGL14 jest tutaj tylko int zdefiniowane przez specyfikację EGL.

Jak EGL14.eglGetDisplay() awarii aplikacji. Czy rzuca wyjątek, który nie zostanie złapany?Może warto zgłosić błąd (z tak dużą ilością szczegółów na temat tego, co robisz i na jakim urządzeniu) pod numerem https://code.google.com/p/android/issues/list.

0

budować na Jesse Halla rozwiązania:

import javax.microedition.khronos.egl.EGL10; 
import javax.microedition.khronos.egl.EGLConfig; 
import javax.microedition.khronos.egl.EGLDisplay; 
import android.opengl.EGL14; 

Można mieć wewnętrzną klasę w swojej GLSurfaceView podklasy, która implementuje EGLConfigChooser:

private static class MyEGLConfigChooser implements GLSurfaceView.EGLConfigChooser { 
    public EGLConfig chooseConfig (EGL10 egl, EGLDisplay display) { 
     EGLConfig [] configs = new EGLConfig[1]; 
     int [] num_config = new int[1]; 
     int [] attrib_list = new int[] { 
      EGL10.EGL_RED_SIZE, 8, 
      EGL10.EGL_GREEN_SIZE, 8, 
      // ... + anything else you want ... 
      EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT | EGL14.EGL_SWAP_BEHAVIOR_PRESERVED_BIT, 
      EGL10.EGL_NONE, 
     }; 

     if (egl.eglChooseConfig(display, attrib_list, configs, configs.length, num_config) && num_config[0] > 0) { 
      // We just pick the first here, but you could interrogate all 
      return configs[0]; 
     } 

     return null; 
    } 
} 

w twojej konstruktora GLSurfaceView podklasy, dodać:

setEGLConfigChooser(new MyEGLConfigChooser()); 

Następnie w impl ementation twoich GLSurfaceView.Renderer, gdy zmiany powierzchniowe, można ustawić atrybuty go:

public void onSurfaceChanged(GL10 gl, int width, int height) { 
    EGL14.eglSurfaceAttrib(EGL14.eglGetCurrentDisplay(), 
          EGL14.getCurrentSurface(EGL14.EGL_DRAW), 
          EGL14.EGL_SWAP_BEHAVIOR, 
          EGL14.EGL_BUFFER_PRESERVED); 
} 
Powiązane problemy