转发,请保持地址:http://blog.csdn.net/stalendp/article/details/8710062
========
前一段时间,在准备游戏开发的过程中,自己尝试着去了解游戏引擎,也做了一些试验;期间遇到了很多问题,现在把一些解决方案以及相关知识点整理出来。这里是第一篇。
========
这篇文章是为了解决Android SDK2.2中使用OpenGL VBO技术时遇到的bug,如果你并不关心2.2版本,或者不直接使用OpenGL的VBO技术,那就可以忽略这篇文章。不过这篇文章还提醒一点的是,不管什么样的软件,多多少少都会有些问题的,这个时候就需要多多思考,通过搜索引擎的帮助来解决问题,这样不仅解决了问题,而且还掌握了很多东西。
传统的OpenGL绘制方式,是每一条命令绘制命令都会有CPU向GPU发送数据的操作。OpenGL VBO(Vertex Buffer Object)通过加载的方式,把需要绘制的数据预先加载到GPU,能够减少程序对GPU发送的数据量,从而提高游戏的性能。
这个VBO的bug是glDrawElements和glVertexAttribPointer的VBO版本没有被映射,导致Java端调用失败。不知道是什么原因导致了这个结果,这个bug感觉有些低级,有个老外这样嘲讽google的开发人员:
I don’t know if it’s because they didn’t run their unit tests, or if the developer was sloppy with their code generation tools, or if everyone was on 8 cups of coffee and burning the midnight oil to get things out the door. I don’t know why the API is broken, but the fact is that it’s broken.
其实解决方案很简单,就是用JNI实现一个java端映射就可以了,具体如下:
===============
JNI源代码编写
===============
- 编写java端
public class GLES20Fix { native public static void glDrawElements( int mode, int count, int type, int offset); native public static void glVertexAttribPointer( int index, int size, int type, boolean normalized, int stride, int offset); private GLES20Fix() {} static { System.loadLibrary("GLES20Fix"); }}
- 生成头文件:
javac -cp . stalendp/game/extend/opengl/GLES20Fix.java
javah -jni stalendp.game.extend.opengl.GLES20Fix
- 实现接口
#include "stalendp_game_extend_opengl_GLES20Fix.h"#include <GLES2/gl2.h> JNIEXPORT void JNICALL Java_stalendp_game_extend_opengl_GLES20Fix_glDrawElements (JNIEnv *env, jclass c, jint mode, jint count, jint type, jint offset) {glDrawElements(mode, count, type, (void*) offset);} JNIEXPORT void JNICALL Java_stalendp_game_extend_opengl_GLES20Fix_glVertexAttribPointer (JNIEnv *env, jclass clazz, jint index, jint size, jint type, jboolean normalized, jint stride, jint offset) {glVertexAttribPointer( index, size, type, normalized, stride, (void*)offset);}
- 编译链接
- 调用
===============
NDK的编译链接
===============
- NDK编译需要三种类型的资源,1)源文件,2)mk文件,3)properties文件
- 编译使用命令 ndk-build
- 编译目录的结构:假设根目录为root, root/jni放置源文件和mk文件,在root下放置properties文件(其中包含编译目标平台);在root下运行ndk-build命令,此命令会根据properties和jni下的mk文件进行编译链接,编译结果放在root/obj目录下,链接结果放在root/libs文件夹下
目录结构一览
-------------------------------------------
root /jni
Android.mk
abc.h
abc.c
/libs
/armeabi
libGLES20Fix.so
/obj
/local
/armeabi
…...
project.properties
-------------------------------------------
mk文件一览:
-------------------------------------------
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := GLES20Fix
LOCAL_CFLAGS := -Werror
LOCAL_SRC_FILES := abc.c
LOCAL_LDLIBS := -lGLESv2
include $(BUILD_SHARED_LIBRARY)
-------------------------------------------
properties文件一览:
-------------------------------------------
target=android-8
-------------------------------------------
相关参考:
- http://stackoverflow.com/questions/8552365/vertex-buffer-objects-vbo-not-working-on-android-2-3-3-using-gles20
- https://code.google.com/p/gdc2011-android-opengl/
- http://www.learnopengles.com/android-lesson-seven-an-introduction-to-vertex-buffer-objects-vbos/