在上一篇文章中,介绍了在Android Native层初始化EGL及OpenGL ES的方法,其中,大量代码花费在EGL的初始化上面,非常的麻烦。在本文中,将展示利用GLSurfaceView来代替我们手动初始化EGL的过程。
用GLSurfaceView替换默认View
在创建一个新工程后,我们需要用GLSurfaceView来作为当前的activity view。GLSurfaceView中封装了EGL的相关功能,其中有两个重要的接口:setEGLContextClientVersion和setRenderer。
setEGLContextClientVersion用来设置OpenGL ES的版本,这里使用OpenGL ES 2.0.
实际的渲染工作是通过继承自GLSurfaceView.Renderer基类的实例来完成的,渲染实例通过setRenderer进行指定。
下面是Activity的代码
public class DemoActivity extends Activity
{
private GLSurfaceView view;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
view = new GLSurfaceView(this);
view.setEGLContextClientVersion(2);
view.setRenderer(new ApplicationRender());
setContentView(view);
}
}
在AndroidManifest.xml中需要指明使用了OpenGL ES 2.0的特性:
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
GLSurfaceView.Renderer
GLSurfaceView.Renderer中有3个其子类必须实现的虚方法:onSurfaceCreated、onSurfaceChanged和onDrawFrame。
onSurfaceCreated中进行一些初始化的工作,onSurfaceChanged中当窗口参数发生变化时进行一些更新操作,onDrawFrame是真正进行绘制的地方。这里可以直接利用Java层的OpenGL ES接口进行绘制,但本文着重要介绍的是如何在native层进行绘制,因此,我们在后面再详细介绍这三个方法的具体内容。
Native渲染
JNI层的完整代码如下
#include <jni.h> #include <GLES2/gl2.h> #include <GLES2/gl2ext.h> void InitializeOpenGL() { glClearColor(1.0f, 1.0f, 0.0f, 1.0f); } void resizeViewport(int newWidth, int newHeight) { glViewport(0, 0, newWidth, newHeight); } void renderFrame() { glClear(GL_COLOR_BUFFER_BIT); } JNIEXPORT void JNICALL Java_com_example_demo_LibraryClass_init(JNIEnv* env, jobject thiz) { InitializeOpenGL(); } JNIEXPORT void JNICALL Java_com_example_demo_LibraryClass_resize(JNIEnv* env, jobject thiz, jint width, jint height) { resizeViewport(width, height); } JNIEXPORT void JNICALL Java_com_example_demo_LibraryClass_render(JNIEnv* env, jobject thiz) { renderFrame(); } </gles2></gles2></jni>
这里我们可以看到,三个jni接口函数分别封装了三个内部函数与GLSurfaceView.Renderer中的三个抽象方法对应。
jni代码的编译方法见之前的文章,这里就不再赘述了。
剩下的工作就是在Java层加载编译出来的jni动态库文件,并在相应的位置调用相应的接口:
public class LibraryClass {
static {
System.loadLibrary("demo");
}
public static native void init();
public static native void resize(int width, int height);
public static native void render();
}
public class ApplicationRender implements GLSurfaceView.Renderer {
public void onDrawFrame(GL10 gl) {
LibraryClass.render();
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
LibraryClass.resize(width, height);
}
@Override
public void onSurfaceCreated(GL10 arg0,
javax.microedition.khronos.egl.EGLConfig arg1) {
// TODO Auto-generated method stub
LibraryClass.init();
}
}
结论
使用GLSurfaceView可以省却大量进行EGL初始化的冗余代码,简化了在native层进行渲染的过程。
参考文献:
https://software.intel.com/en-us/articles/setting-up-native-opengl-es-on-android-platforms