Learning opengl 中关于文字渲染的部分,写的非常详细,但是在android jni环境下如何利用opengl的能力,渲染出文字,找了一圈,确实没有特别讲这块的内容,这里涉及到几点比较重要的点,首先如何把surface设置到c++层,其次如何家在freetype库,第三,渲染文字shader在android下如何写。
创建Native C++项目
名字可以随便起,不过语言最好选择Kotilin,跑起来的话
修改activity_main.xml
删除label组建,添加一个surfaceview,代码如下
<SurfaceView
android:id="@+id/surfaceView"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
修改MainActivity.kt获取surface view
glSurfaceView = findViewById<SurfaceView>(R.id.surfaceView)
glSurfaceView.holder.addCallback(object : SurfaceHolder.Callback {
override fun surfaceCreated(holder: SurfaceHolder) {
nativeSetView(glSurfaceView.holder.surface)
}
override fun surfaceChanged(surfaceHolder: SurfaceHolder, i: Int, width: Int, height: Int) {
}
override fun surfaceDestroyed(holder: SurfaceHolder) {
}
})
添加native函数nativeSetView
添加以后,android studio会把函数名设置为红色,如果鼠标移上去,ide会提示你是不是要建立对应的c++调用函数,这是最简单的方式。
external fun nativeSetView(surface: Surface)
创建后的函数中获取ANativeWindow
这里需要在文件中建立一个全局变量来保证各个函数能用到这个变量。
g_window = ANativeWindow_fromSurface(env, surface);
渲染一个纯色
继续添加以下代码,glClearColor之前的代码都是套路的代码,都是准备opengl的各个环境。
EGLDisplay mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (mDisplay == EGL_NO_DISPLAY) {
printf("egl display failed");
}
if (EGL_TRUE != eglInitialize(mDisplay, 0, 0)) {
printf("eglInitialize failed");
}
EGLConfig eglConfig;
EGLint configNum;
EGLint configSpec[] = {
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_NONE
};
if (EGL_TRUE != eglChooseConfig(mDisplay, configSpec, &eglConfig, 1, &configNum)) {
printf("eglChooseConfig failed");
}
EGLSurface mWinSurface = eglCreateWindowSurface(mDisplay, eglConfig, mWindow, 0);
if (mWinSurface == EGL_NO_SURFACE) {
printf("eglCreateWindowSurface failed");
}
const EGLint ctxAttr[] = {
EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE
};
EGLContext context = eglCreateContext(mDisplay, eglConfig, EGL_NO_CONTEXT, ctxAttr);
if (context == EGL_NO_CONTEXT) {
printf("eglCreateContext failed");
}
if (EGL_TRUE != eglMakeCurrent(mDisplay, mWinSurface, mWinSurface, context)) {
printf("eglMakeCurrent failed");
}
//draw call
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
eglSwapBuffers(mDisplay, mWinSurface);