I've tweaked the native-activity NDK sample to incorporate the OpenGL code from the hello-gl2 example. I handle the APP_CMD_INIT_WINDOW
message and then attempt to create the shaders. The shader creation fails and I attempt to get information via getShaderInfoiv, but that silently fails as well.
So my question is - how can I create an OpenGL ES 2.0 shader in a pure native Android application?
P.S. I know shader creation can fail if you use the Java GLSurfaceView and don't create them in the correct thread, but looking at the native-activity sample, it only appears to have one thread!
It certainly is possible to create an OpenGL ES 2.0 shader in a native Android application. The key thing is to use proper OpenGL ES 2.0 context. I did something similar in my app namely initialized EGL context in native part and then created (and used) shaders in native code only. Based on what I managed to do I assume that what you want to do is also perfectly possible.
Since I had an entry point in Java code (did not use NativeAcvity mechanism) I also had to pass native window handle (EGLNativeWindowType
) from java to C++ in order to create EGL surface in native code. However, since you want to simply modify NativeActivity example then you can use engine->app->window
for creating EGL surface on as presented in NativeActivity main.c
sample.
OK, how to create proper OpenGL ES 2.0 context in native code? I have just made two changes to the main.c
file in NativeActivity sample and checked it worked.
Firstly, used the following EGL attributes
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
};
in eglChooseConfig(display, attribs, &config, 1, &numConfigs);
.
Secondly, later in creating context used
const EGLint attrib_list [] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
in context = eglCreateContext(display, config, NULL, attrib_list);
I left the rest of the code unchanged. I printed some info to make sure that OpenGL ES 2.0 is being used:
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 ... ]
Hope it helps!
I wonder why you decided to go to a full Native solution, usually what you do is to keep "native" only your "heavy component" such as your rendering engine, the AI engine, the physics engine and you keep the "Device layer" up to the Java part.
In this way, the huge advantage is portability. If you build everything in NDK, then you have to re-invent the wheel if you want to move your game/program to Iphone while if you keep the "core" in C and the additional layers in Java, you will have to rewrite only the easy part of the problem.
In this kind of solutions I have extensive experience since my 3D engine (PATRIA 3D) is built on native code able to be crossed ported from Android NDK to Iphone Objective C (plus Windows/Linux/Mac OSx). At the end of the day, my code is a fully compliant C89 + OpenGL2.0 able to be compiled straight forward (with minor changes) on Android (using android ndk-build) and Iphone (XCODE).
Following this approach, the engine and perform the actual drawing on the same thread, let me call it the main thread.
If you need multi threads in your application:
A - Keep the drawing on the main one (the main) B - Create the new threads in Java, don't do it in C (when you port to other platform, you build the multi threading on the new layer)
In regard to shaders, the solution in this way is very stright forward since the surface and the init of OpenGL is performed by Java using the standard EGL library.
Believe me, if you can write once and use on both platforms, Android and Iphone, you double the "customers" numbers, it is something you cannot ignore, it could potentially double your earnings.
I hope this helps in some way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With