现在的位置: 首页 > 综合 > 正文

Android 如何使用NDK开发OPenGL ES

2013年10月08日 ⁄ 综合 ⁄ 共 5709字 ⁄ 字号 评论关闭

  Android
SDK 
提供了一套 OpenGL ES 接口,该接口是基于 Java 的,速度非常 慢,往往很难满足需要。写此文章的目的是为了使用Android
提供的NDK 工具来使用C/C++ 原生代码。因最近在研究Android OpenGL ES 部分,就以使用C++ 来书写opengles 代码, 然后通过JNI 提供给java调用。重要的是避免了调用
Android SDK OpenGL
ES 
接口,是速度大大提高 。


   首先告知大家我使用的平台:(本文将省略如何安装Eclipse ,ADT,及如何配置Android sdk等..)
   Linux Fedora 12 ,Eclipse Helios版本,Android SDK 2.2,Android
NDK r4(目前最新)

  安装NDK: 首先去官网下载Android
NDK ,在此给提供一个免翻墙的网站:         
http://androidappdocs.appspot.com/sdk/ndk/index.html ,并将其加压到任意目录(后文以#NDK
来代表解压目录)

      本文不会大多关注代码部分的讲解,我会将主要代码贴出,并在此文的提供给大家源码下载.文中有关于android.mk 代码的编写,可自行参考#NDK/doc/ANDROID-MK.TXT 文档。
 
     1,在Eclipse 下新建Android 项目 (名字:OpenGl_Jni  包:com.opengl.jni) 新建以下四个类
Activity 类 :

package com.opengl.jni;
import android.app.Activity;
import android.os.Bundle;
public class GLActivity extends Activity {
    /** Called when the activity is first created. */
private GLCanvas mCanvas;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mCanvas = new GLCanvas(getApplication());
        
        setContentView(mCanvas);
    }
...........................
}

GlCanvas 类继承GLSurfaceView类:

package com.opengl.jni;
public class GLCanvas extends GLSurfaceView {

private static final String TAG = "GLCanvas";
private static final boolean DEBUG = false;

public GLCanvas(Context context) {
super(context);
// TODO Auto-generated constructor stub
init(false, 0, 0);
}

public GLCanvas(Context context, boolean translucent, int depth, int stencil) {
super(context);
init(translucent, depth, stencil);
}
................
}

GLRenderer 类实现GLSurfaceView.Renderer 接口 :如下

    public class GLRenderer implements GLSurfaceView.Renderer{

public void onDrawFrame(GL10 gl) {
// TODO Auto-generated method stub
GLJniLib.step();
}

public void onSurfaceChanged(GL10 gl, int width, int height) {
// TODO Auto-generated method stub
GLJniLib.init(width, height);
}

public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// TODO Auto-generated method stub
}

}

GLJniLib 类 :

package com.opengl.jni;

public class GLJniLib {

    static {
        System.loadLibrary("gljni");
    }

   /**
    * @param width the current view width
    * @param height the current view height
    */
    public static native void init(int width, int height);
    public static native void step();
    public static native void setBackColor(float r,float g,float b);
}


2,在OpenGl_Jni项目根目录下 新建jni 文件夹 ,并在jni 文件夹下 建立Android.mk 及gl_code.cpp 文件 ,如下:
Anddroid.mk  内容如下 :
LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := libgljni
LOCAL_CFLAGS    := -Werror
LOCAL_SRC_FILES := gl_code.cpp
LOCAL_LDLIBS    := -llog -lGLESv2

include $(BUILD_SHARED_LIBRARY)

gl_code.cpp  内容如下 :

// OpenGL ES 2.0 code

#include <jni.h>
#include <android/log.h>

#include <GLES2/gl2.h>
#include <GLES2/gl2ext.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);
}
}

static const char gVertexShader[] = "attribute vec4 vPosition;\n"
"void main() {\n"
"  gl_Position = vPosition;\n"
"}\n";

static const char gFragmentShader[] = "precision mediump float;\n"
"void main() {\n"
"  gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
"}\n";

GLuint loadShader(GLenum shaderType, const char* pSource) {
GLuint shader = glCreateShader(shaderType);
if (shader) {
glShaderSource(shader, 1, &pSource, NULL);
glCompileShader(shader);
GLint compiled = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (!compiled) {
GLint infoLen = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen) {
char* buf = (char*) malloc(infoLen);
if (buf) {
glGetShaderInfoLog(shader, infoLen, NULL, buf);
LOGE("Could not compile shader %d:\n%s\n",
shaderType, buf);
free(buf);
}
glDeleteShader(shader);
shader = 0;
}
}
}
return shader;
}

GLuint createProgram(const char* pVertexSource, const char* pFragmentSource) {
GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
if (!vertexShader) {
return 0;
}

GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
if (!pixelShader) {
return 0;
}

GLuint program = glCreateProgram();
if (program) {
glAttachShader(program, vertexShader);
checkGlError("glAttachShader");
glAttachShader(program, pixelShader);
checkGlError("glAttachShader");
glLinkProgram(program);
GLint linkStatus = GL_FALSE;
glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
if (linkStatus != GL_TRUE) {
GLint bufLength = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
if (bufLength) {
char* buf = (char*) malloc(bufLength);
if (buf) {
glGetProgramInfoLog(program, bufLength, NULL, buf);
LOGE("Could not link program:\n%s\n", buf);
free(buf);
}
}
glDeleteProgram(program);
program = 0;
}
}
return program;
}

GLuint gProgram;
GLuint gvPositionHandle;

bool setupGraphics(int w, int h) {
printGLString("Version", GL_VERSION);
printGLString("Vendor", GL_VENDOR);
printGLString("Renderer", GL_RENDERER);
printGLString("Extensions", GL_EXTENSIONS);

LOGI("setupGraphics(%d, %d)", w, h);
gProgram = createProgram(gVertexShader, gFragmentShader);
if (!gProgram) {
LOGE("Could not create program.");
return false;
}
gvPositionHandle = glGetAttribLocation(gProgram, "vPosition");
checkGlError("glGetAttribLocation");
LOGI("glGetAttribLocation(\"vPosition\") = %d\n",
gvPositionHandle);

glViewport(0, 0, w, h);
checkGlError("glViewport");
return true;
}

const GLfloat gTriangleVertices[] = { 0.0f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f };
      GLfloat vVertices[] = {0.0f, 0.5f, 0.0f,
                            -0.5f, -0.5f, 0.0f,
                             0.5f, -0.5f, 0.0f};

// by gaoxi.xie
float _red = 0.9f;
float _green = 0.2f;
float _blue = 0.2f;

void setBackColor(float r, float g, float b) {
_red = r;
_green = g;
_blue = b;
}

void renderFrame() {

static float grey;
grey += 0.01f;
if (grey > 1.0f) {
grey = 0.0f;
}
glClearColor(grey, grey, grey, 1.0f);
checkGlError("glClearColor");
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
checkGlError("glClear");

glUseProgram(gProgram);
checkGlError("glUseProgram");

glVertexAttribPointer(gvPositionHandle, 2

抱歉!评论已关闭.