We can write opengl code on jni layer and draw 3d graphics. The following example is an example of drawing tetrahedron. The drawing code of the example is implemented on jni layer and is written in c + + language.
1. First, create the upper application related classes and organize the call paths.
This is mainly about creating activity classes, rendering classes and related auxiliary classes.
The main activity class code is as follows:
import android.app.Activity; import android.os.Bundle; public class GL10JNIActivity extends Activity { private GL10JNIView mView; @Override protected void onCreate(Bundle icicle) { super.onCreate(icicle); mView = new GL10JNIView(this); setContentView(mView); } @Override protected void onPause() { super.onPause(); mView.onPause(); } @Override protected void onResume() { super.onResume(); mView.onResume(); } }
Next, create the opengl view class with the following code:
import android.content.Context; import android.opengl.GLSurfaceView; public class GL10JNIView extends GLSurfaceView { private static final String LOG_TAG = GL10JNIView.class.getSimpleName(); private MyRenderer myRenderer; public GL10JNIView(Context context) { super(context); setEGLConfigChooser(8, 8, 8, 8, 16, 0); myRenderer = new MyRenderer(context); setRenderer(myRenderer); } }
Next, create the rendering class with the following code:
import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.content.Context; import android.opengl.GLSurfaceView.Renderer; public class MyRenderer implements Renderer { public MyRenderer(Context ctx) { } @Override public void onDrawFrame(GL10 gl) { GL10JNILib.step(); } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { GL10JNILib.resize(width, height); } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { GL10JNILib.init(); } }
Finally, the localization method corresponding to jni is declared, and the corresponding library generated by jni code is loaded. The code is as follows:
public class GL10JNILib { static { System.loadLibrary("gl10jni"); } /** * @param width the current view width * @param height the current view height */ public static native void resize(int width, int height); public static native void step(); public static native void init(); }
2. Write jni drawing code
Create a jni folder under the root directory of the android project. Create two new files, one is the Android.mk file, and the other is the code file we draw. The contents of the Android.mk file are as follows:
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := libgl10jni LOCAL_CFLAGS := -Werror LOCAL_SRC_FILES := gl_code.cpp LOCAL_LDLIBS := -llog -lGLESv1_CM include $(BUILD_SHARED_LIBRARY)
Finally, the corresponding drawing code, as follows:
#include <jni.h> #include <android/log.h> #include <GLES/gl.h> #include <GLES/glext.h> #include <stdio.h> #include <stdlib.h> #include <math.h> #define LOG_TAG "libgl2jni" #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) static void printGLString(const char *name, GLenum s) { const char *v = (const char *) glGetString(s); LOGI("GL %s = %s\n", name, v); } static void checkGlError(const char* op) { for (GLint error = glGetError(); error; error = glGetError()) { LOGI("after %s() glError (0x%x)\n", op, error); } } bool init() { printGLString("Version", GL_VERSION); printGLString("Vendor", GL_VENDOR); printGLString("Renderer", GL_RENDERER); printGLString("Extensions", GL_EXTENSIONS); glShadeModel(GL_SMOOTH); // Enable shadow smoothing glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Black background glClearDepthf(1.0f); // Setting Depth Cache glEnable(GL_DEPTH_TEST); // Enable depth testing glDepthFunc(GL_LEQUAL); // Types of in-depth testing glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Tell the system to correct perspective return true; } const GLfloat gVertices[] = { 0.0f, 1.0f, 0.0f, -1.0f,-1.0f, 1.0f, 1.0f,-1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,-1.0f, 1.0f, 1.0f,-1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f,-1.0f, -1.0f, -1.0f,-1.0f, -1.0f, 0.0f, 1.0f, 0.0f, -1.0f,-1.0f,-1.0f, -1.0f,-1.0f, 1.0f }; const GLfloat gColors[] = { 1.0f,0.0f,0.0f, 1.0f, 0.0f,1.0f,0.0f, 1.0f, 0.0f,0.0f,1.0f, 1.0f, 1.0f,0.0f,0.0f, 1.0f, 0.0f,0.0f,1.0f, 1.0f, 0.0f,1.0f,0.0f, 1.0f, 1.0f,0.0f,0.0f, 1.0f, 0.0f,1.0f,0.0f, 1.0f, 0.0f,0.0f,1.0f, 1.0f, 1.0f,0.0f,0.0f, 1.0f, 0.0f,0.0f,1.0f, 1.0f, 0.0f,1.0f,0.0f, 1.0f }; static GLfloat rtri; //Rotating variables of triangles static GLfloat rquad; //Rotating Variables of Quadrilateral const GLfloat PI = 3.1415f; static void _gluPerspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar) { GLfloat top = zNear * ((GLfloat) tan(fovy * PI / 360.0)); GLfloat bottom = -top; GLfloat left = bottom * aspect; GLfloat right = top * aspect; glFrustumf(left, right, bottom, top, zNear, zFar); } void resize(int width, int height) { if (height==0) // Prevent being divided by zero { height=1; // Set Height to 1 } glViewport(0, 0, width, height); // Reset the current viewport glMatrixMode(GL_PROJECTION); // Selective Projection Matrix glLoadIdentity(); // Reset projection matrix GLfloat ratio = (GLfloat)width/(GLfloat)height; // Set Size of Viewport _gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f); // glOrthof(-2.0f, 2.0f, -2.0f, 2.0f, -2.0f, 2.0f); glMatrixMode(GL_MODELVIEW); // Selecting Model Observation Matrix glLoadIdentity(); // Resetting Model Observation Matrix } void renderFrame() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear screen and deep cache glLoadIdentity(); // Resetting Model Observation Matrix glTranslatef(0.0f,0.0f, -6.0f); // Move into screen 6.0 glRotatef(rtri,0.0f,1.0f,0.0f); // Revolving around Y axis in Pyramid glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(4, GL_FLOAT, 0, gColors); glVertexPointer(3, GL_FLOAT, 0, gVertices); glDrawArrays(GL_TRIANGLES, 0, 12); rtri += 0.2f; // Increase the rotation variable of the triangle //LOGI("xxxxx"); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); glFlush(); } extern "C" { JNIEXPORT void JNICALL Java_com_test_fuyajun_GL10JNILib_resize(JNIEnv * env, jobject obj, jint width, jint height); JNIEXPORT void JNICALL Java_com_test_fuyajun_GL10JNILib_step(JNIEnv * env, jobject obj); JNIEXPORT void JNICALL Java_com_test_fuyajun_GL10JNILib_init(JNIEnv * env, jobject obj); }; JNIEXPORT void JNICALL Java_com_test_fuyajun_GL10JNILib_resize(JNIEnv * env, jobject obj, jint width, jint height) { resize(width, height); } JNIEXPORT void JNICALL Java_com_test_fuyajun_GL10JNILib_step(JNIEnv * env, jobject obj) { renderFrame(); } JNIEXPORT void JNICALL Java_com_test_fuyajun_GL10JNILib_init(JNIEnv * env, jobject obj) { init(); }
jni code is compiled into a library by using ndk-build tool, and then the android application is run.
Reproduced in: https://my.oschina.net/fuyajun1983cn/blog/263808