2017-04-03 5 views
1

Also hier ist der Deal. Ich verwende OpenGL API für Windows [Win32] seit etwa 3 Jahren. Ich habe mehrere Shader im selben geschrieben.mit NDK für Android OpenGL-Code schreiben

Jetzt möchte ich mein Projekt auf Android portieren. Meine Frage ist, wenn ich das Projekt mit C++ [NDK] schreiben möchte, und OpenGL ES verwenden ist es möglich?

Kurze Antwort Ich bekam war "Ja", aber, ist das ein richtiger Weg? Bin ich besser dran mit Java? Gibt es irgendwelche Leistungseinbußen, weil ich NDK verwende, da ich eine VR-basierte OpenGL-Anwendungsleistung anstrebe?

Ja, das sind mehrere Fragen, aber sie zeigen auf das ähnliche Problem, ist es praktisch, NDK für reale Projekte zu verwenden.

Antwort

1

Die kurze Antwort ist ja, Sie können NDK für reale Projekte verwenden. Wenn Sie NativeActivity verwenden, können Sie eine App ohne Java-Code haben. Viele Spiele sind mit Unity-Engine gebaut und haben alle OpenGL in C++ ohne Leistungsbeschwerden gemacht. Eigentlich the opposite is true, aber im wirklichen Leben ist die Leistungseinbuße von Java-GL-Wrapper ziemlich niedrig.

2

Es liegt an Ihnen, wie viel von Ihrer Anwendung Sie in C++ schreiben und wie viel Sie in Java schreiben. Jeder JNI-Aufruf hat einen zugeordneten Overhead. Daher sollten Sie dies im Hinterkopf behalten, wenn Sie Java und nativen Code teilen. Wenn Sie z. B. Ihre gesamte Rendering-Schleife in C++ schreiben, wird nur ein JNI-Aufruf pro Frame ausgeführt Render-Schleife, indem die OpenGL-API über den Java-Wrapper aufgerufen wird, kann Tausende von JNI-Aufrufen pro Frame zur Folge haben. Was als "richtig" angesehen werden kann, hängt von Ihren spezifischen Anforderungen ab.

Als Minimum müssen Sie erhalten entweder ein Surface (aus den SurfaceHolder, die von einem SurfaceView vorgesehen ist) oder ein SurfaceTexture (von TextureView erhalten) und über die JNI auf Ihre native Anwendung übergeben, wo Sie Verwenden Sie ANativeWindow_fromSurface oder ANativeWindow_fromSurfaceTexture (siehe here), um ein natives Fenster zu erhalten, mit dem Sie Ihre OpenGL ES-Oberfläche und den zugehörigen Kontext erstellen können. Wahrscheinlich möchten Sie Ihre JNI-Aufrufe in Java-Klassen kapseln, die auf die SurfaceHolder oder SurfaceTexture Rückrufe hören. Zum Beispiel:

public class GlSurfaceHolder { 
    private SurfaceHolder mSurfaceHolder; 
    private SurfaceHolder.Callback mSurfaceHolderCallback; 

    public GlSurfaceHolder(SurfaceHolder surfaceHolder) { 
     mSurfaceHolder = surfaceHolder; 
     mSurfaceHolderCallback = new SurfaceHolder.Callback() { 
      // JNI calls in here 
     } 

     mSurfaceHolder.addCallback(mSurfaceHolderCallback); 
    } 
}; 

Wenn Sie das Niveau der Kontrolle nicht benötigen, sollten Sie überlegen, GLSurfaceView verwenden, die eine SurfaceView ist, das seine eigene OpenGL ES Oberflächenschleife, Kontext und machen verwaltet. Der Nachteil von GLSurfaceView ist, dass es unnötigerweise eine ganze Ladung scheinbar nicht zusammenhängender Dinge koppelt. Das Entkoppeln dieser Funktionen ist nicht nur von der Perspektive des single responsibility principle sauberer, es ermöglicht Ihnen, Ihr Rendering potenziell in einem separaten Thread auszuführen (was natürlich eine Synchronisierung mit dem UI-Thread erfordert, aber möglicherweise Leistungsvorteile hat).

Wenn Sie sich nicht einmal um Ihre Anwendung auf Java-Seite kümmern, können Sie die NativeActivity Convenience-Klasse verwenden, die alle zuvor erwähnten Funktionen sowie einige andere Dinge in einer Android-Aktivität bündelt. Es ist die schnelle und schmutzige Option.