我已经调整了本机活动NDK示例以合并来自hello-gl2示例的OpenGL代码。我处理APP_CMD_INIT_WINDOW
消息,然后尝试创建着色器。着色器创建失败,我尝试通过getShaderInfoiv获取信息,但是也会无声地失败。
所以我的问题是 - 如何在纯原生Android应用程序中创建OpenGL ES 2.0着色器?
P.S。我知道如果使用Java GLSurfaceView并且不在正确的线程中创建它们,则着色器创建可能会失败,但是查看本机活动示例,它似乎只有一个线程!
答案 0 :(得分:12)
当然可以在原生Android应用程序中创建OpenGL ES 2.0着色器。关键是要使用适当的OpenGL ES 2.0上下文。我在我的应用程序中做了类似的事情,即在本机部分初始化EGL上下文,然后仅在本机代码中创建(和使用)着色器。基于我的设法,我认为你想做的事情也是完全可能的。
由于我在Java代码中有一个入口点(没有使用NativeAcvity机制),我还必须将本机窗口句柄(EGLNativeWindowType
)从java传递给C ++,以便在本机代码中创建EGL表面。但是,由于您只想修改NativeActivity示例,因此可以使用engine->app->window
创建EGL表面,如NativeActivity main.c
示例中所示。
好的,如何在本机代码中创建适当的OpenGL ES 2.0上下文?我刚刚对NativeActivity示例中的main.c
文件进行了两处更改,并检查了它是否有效。
首先,使用以下EGL属性
const EGLint attribs[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, //important
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_NONE
};
eglChooseConfig(display, attribs, &config, 1, &numConfigs);
中的。
其次,稍后使用
创建上下文const EGLint attrib_list [] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
context = eglCreateContext(display, config, NULL, attrib_list);
中的
我保留了其余的代码。我打印了一些信息以确保使用OpenGL ES 2.0:
I/native-activity( 955): Details: [Version: OpenGL ES 2.0 1403843], [Vendor: Qualcomm], [Renderer: Adreno 205], [Extensions: GL_AMD_compressed_3DC_texture GL_AMD_compressed_ATC_texture ... ]
希望它有所帮助!
答案 1 :(得分:3)
我想知道为什么你决定转到一个完整的Native解决方案,通常你所做的就是保持“原生”只是你的“重组件”,比如渲染引擎,AI引擎,物理引擎,你保持“设备层“直到Java部分。
通过这种方式,巨大的优势是便携性。如果您在NDK中构建所有内容,那么如果您想将游戏/程序移动到Iphone,则必须重新发明轮子,而如果您将“核心”保留在C中并使用Java中的附加层,则必须仅重写问题的简单部分。
在这种解决方案中,我有丰富的经验,因为我的3D引擎(PATRIA 3D)是基于本机代码构建的,能够从Android NDK交叉移植到Iphone Objective C(加上Windows / Linux / Mac OSx)。在一天结束时,我的代码是完全兼容的C89 + OpenGL2.0,能够在Android(使用android ndk-build)和Iphone(XCODE)上直接编译(稍作修改)。
按照这种方法,引擎并在同一个线程上执行实际绘图,让我称之为主线程。
如果您的应用程序中需要多线程:
A - 将图纸保留在主图纸上(主图) B - 在Java中创建新线程,不要在C中创建(当您移植到其他平台时,在新层上构建多线程)
关于着色器,这种方式的解决方案非常直接,因为OpenGL的表面和init是由Java使用标准EGL库执行的。
相信我,如果你可以写一次并在Android和Iphone这两个平台上使用,你可以将“客户”数字加倍,这是你不能忽视的,它可能会使你的收入增加一倍。
我希望这会有所帮助。