下面是一个简单的 C 程序(没有 Manifest/Java 等),它旋转一个三角形 20 秒。这只是为了提供信息(不是创建 Android 应用程序的推荐方式)。它需要对“图形”组的访问权限(如果您通过 ADB 运行它就是这种情况)。
如何编译:
1) 从http://developer.android.com/tools/sdk/ndk/index.html获取android NDK
2) 安装工具链:
./android-ndk-r9b/build/tools/make-standalone-toolchain.sh \
--platform=android-17 --toolchain=arm-linux-androideabi-4.7 \
--system=linux-x86_64 --install-dir=where_you_want_to_install
3) 从设备获取 libui.so:
adb pull /system/lib/libui.so
4) 编译:
arm-linux-androideabi-gcc main.c -lGLESv1_CM -lEGL -landroid -L. -lui -o gles_test
要运行该程序,您将需要访问“图形”组,如果您通过 ADB 运行它就是这种情况(但如果您从终端运行它,例如 TerminalIDE 则不需要)
/* Program largely inspired from: */
/* http://jiggawatt.org/badc0de/android/index.html */
/* http://software.intel.com/en-us/articles/setting-up-native-opengl-es-on-android-platforms */
/* http://www.brucesutherland.co.uk/android-ndk/opengl-es-2-0-android-ndk-game-programming/ */
#include <stdio.h>
#include <stdlib.h>
#include <EGL/egl.h>
#include <GLES/gl.h>
#include <android/native_window.h>
#include <sys/types.h>
#include <sys/times.h>
/* returns current time in seconds */
double now() {
struct tms now_tms ;
return (double)(times(&now_tms)) / 100.0 ;
}
/* from libui.so (get it from the device using adb pull /system/lib/libui.so) */
extern NativeWindowType android_createDisplaySurface();
NativeWindowType displayWindow;
const EGLint config16bpp[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, 5,
EGL_GREEN_SIZE, 6,
EGL_BLUE_SIZE, 5,
EGL_NONE
};
const EGLint config24bpp[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_NONE
};
const EGLint config32bpp[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_NONE
};
GLfloat colors[3][4] = {
{1.0f, 0.0f, 0.0f, 1.0f},
{0.0f, 1.0f, 0.0f, 1.0f},
{0.0f, 0.0f, 1.0f, 1.0f}
};
GLfloat vertices[3][3] = {
{0.0f, 0.7f, 0.0f},
{-0.7f, -0.7f, 0.0f},
{0.7f, -0.7f, 0.0f}
};
void draw_tri() {
glViewport(
0,
0,
ANativeWindow_getWidth(displayWindow),
ANativeWindow_getHeight(displayWindow)
);
glRotatef(0.5, 0, 0, 1) ;
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glColorPointer(4, GL_FLOAT, 0, colors);
glVertexPointer(3, GL_FLOAT, 0, vertices);
/* Draw the triangle (3 vertices) */
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
}
int main(int argc, char** argv) {
EGLint majorVersion, minorVersion;
EGLContext eglContext;
EGLSurface eglSurface;
EGLConfig eglConfig;
EGLDisplay eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
EGLint format;
const EGLint* config = NULL ;
int numConfigs;
int windowFormat;
double start_time = now() ;
/*
* create a window surface that covers the entire screen.
* This function is from libui.
*/
displayWindow = android_createDisplaySurface();
eglInitialize(eglDisplay, &majorVersion, &minorVersion);
printf("GL version: %d.%d\n",majorVersion,minorVersion);
if(displayWindow == 0) {
printf("Could not create window\n") ;
printf("Started from an on-device shell ?\n") ;
printf("use: adb shell <path_to_exe>/%s\n",argv[0]) ;
exit(-1) ;
}
/* get the format of the window. */
windowFormat = ANativeWindow_getFormat(displayWindow) ;
printf("Window specs: %d*%d format=%d\n",
ANativeWindow_getWidth(displayWindow),
ANativeWindow_getHeight(displayWindow),
windowFormat
) ;
/* choose the config according to the format of the window. */
switch(windowFormat) {
case WINDOW_FORMAT_RGBA_8888:
config = config32bpp ;
break ;
case WINDOW_FORMAT_RGBX_8888:
config = config24bpp ;
break ;
case WINDOW_FORMAT_RGB_565:
config = config16bpp ;
break ;
default:
printf("Unknown window format\n") ;
exit(-1) ;
}
if (!eglChooseConfig(eglDisplay, config32bpp, &eglConfig, 1, &numConfigs)) {
printf("eglChooseConfig failed\n");
if (eglContext==0) printf("Error code: %x\n", eglGetError());
exit(-1) ;
}
eglContext = eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, NULL);
printf("GL context: %x\n", eglContext);
if (eglContext==0) {
printf("Error code: %x\n", eglGetError());
exit(-1) ;
}
eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, displayWindow, NULL);
printf("GL surface: %x\n", eglSurface);
if (eglSurface==0) {
printf("Error code: %x\n", eglGetError());
exit(-1);
}
eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
printf(
"Vendor: %s, Renderer: %s, Version: %s\n",
glGetString(GL_VENDOR),
glGetString(GL_RENDERER),
glGetString(GL_VERSION)
) ;
printf("Extensions: %s\n", glGetString(GL_EXTENSIONS)) ;
printf("Spinning triangle for 20s\n") ;
while (now() - start_time < 20.0) {
draw_tri();
eglSwapBuffers(eglDisplay, eglSurface);
}
printf("End (tap the screen of the phone to continue).\n") ;
return 0;
}