2017-04-03 42 views
1

所以這裏是交易。 我一直在Windows [Win32]上使用OpenGL API約3年。 我寫了多個着色器在相同的。使用Android的NDK編寫OpenGL代碼

現在我想在Android上移植我的項目。 我的問題是,如果我想使用C++ [NDK]編寫項目,並使用OpenGL ES,有可能嗎?

簡短的回答我得到了'是',但是,這是一個正確的方式? 我最好用Java嗎?是否有任何性能下降,因爲我使用NDK,因爲我瞄準基於VR的OpenGL應用程序性能是主要因素?

是的,這些是多個問題,但他們指出了類似的問題,是否將NDK用於實際項目是實用的。

回答

1

簡短的回答是肯定的,你可以使用NDK進行真實項目。如果你使用NativeActivity,你可以擁有一個沒有Java代碼的應用程序。許多遊戲都是用Unity引擎構建的,並且所有的OpenGL都是用C++完成的,沒有性能問題。實際上,the opposite is true,但在現實生活中Java-to-GL包裝的性能損失相當低。

2

這取決於你用C++編寫的應用程序的多少以及用Java編寫的多少。每個JNI調用都有相關的開銷,因此當決定如何分割Java和本地代碼時,您可能需要記住這一點(例如,使用C++編寫整個渲染循環將會導致每幀只有一個JNI調用,同時編寫通過Java封裝器調用OpenGL API渲染循環可能會導致每幀數以千計的JNI調用)。什麼可能被認爲是「正確的」取決於你的具體要求。

至少,你將需要獲得無論是Surface(從由SurfaceView提供的SurfaceHolder)或SurfaceTexture(從TextureView獲得),並通過JNI傳遞到你的本地應用程序,在那裏你可以使用ANativeWindow_fromSurfaceANativeWindow_fromSurfaceTexture(請參閱here)獲取本機窗口,您可以使用該窗口創建OpenGL ES曲面和上下文。您可能希望將Java JNI調用封裝在Java類中,該類可以監聽SurfaceHolderSurfaceTexture回調。例如:

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); 
    } 
}; 

如果不需要此級別的控制,你可以考慮使用GLSurfaceView,這是管理自己的OpenGL ES的表面,背景和渲染循環SurfaceViewGLSurfaceView的缺點是它不必要地耦合整個負載的表面上不相關的東西。從single responsibility principle的角度來看,解耦這些函數不僅更加簡潔,還允許您在單獨的線程中執行渲染(當然這需要與UI線程同步,但可能會帶來性能方面的好處)。

如果你甚至不關心任何運行Java端的應用程序,你可以使用NativeActivity便利類,它將前面提到的所有功能以及其他一些東西捆綁到一個Android活動中。這是快速和骯髒的選擇。