使用 NDK for Android 编写 OpenGL 代码



所以这是交易。 我已经在Windows [Win32]上使用OpenGL API大约3年了。 我在同一种着色器中编写了多个着色器。

现在我想在Android上移植我的项目。 我的问题是,如果我想使用 C++ [NDK] 编写项目,并使用 OpenGL ES 可以吗?

我得到的简短回答是"是",但是,这是一种正确的方式吗? 我使用Java更好吗?是否有任何性能下降,因为我使用的是NDK,因为我的目标是基于VR的OpenGL应用程序性能是主要因素?

是的,这是多个问题,但它们指向类似的问题,将 NDK 用于现实生活中的项目是否可行。

这取决于你用C++编写多少应用程序,以及用Java编写多少应用程序。每个 JNI 调用都有一个关联的开销,因此在决定如何拆分 Java 和本机代码时,您可能需要牢记这一点(例如,在 C++ 中编写整个渲染循环每帧只会产生一个 JNI 调用,而通过 Java 包装器调用 OpenGL API 来编写渲染循环可能会在每帧产生数千次 JNI 调用)。什么可能被认为是"正确的"取决于您的具体要求。

至少,您需要获取Surface(从SurfaceView提供的SurfaceHolder)或SurfaceTexture(从TextureView获得),并通过 JNI 将其传递给本机应用程序,您可以在其中使用ANativeWindow_fromSurfaceANativeWindow_fromSurfaceTexture(请参阅此处)来获取本机窗口,您可以使用该窗口创建 OpenGL ES 图面和上下文。您可能希望将 JNI 调用封装在侦听SurfaceHolderSurfaceTexture回调的 Java 类中。例如:

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的缺点是它不必要地耦合了一大堆表面上不相关的东西。从单一责任原则的角度来看,解耦这些函数不仅更整洁,它还允许您在单独的线程中执行渲染(这当然需要与 UI 线程同步,但可能会带来性能优势)。

如果你甚至不关心任何运行Java端的应用程序,你可以使用NativeActivity方便类,它将前面提到的所有函数以及其他一些东西捆绑到Android Activity中。这是快速而肮脏的选择。

简短的回答是肯定的,您可以将 NDK 用于现实生活中的项目。如果您使用 NativeActivity,则可以拥有一个完全没有 Java 代码的应用程序。许多游戏都是使用 Unity 引擎构建的,并且所有 OpenGL 都是在C++完成的,没有性能问题。实际上,情况正好相反,但在现实生活中,Java-to-GL包装器的性能损失非常低。

最新更新