当前位置: 代码迷 >> Android >> 手游开发常识(一)--VBO在Android2.2的bug
  详细解决方案

手游开发常识(一)--VBO在Android2.2的bug

热度:37   发布时间:2016-05-01 11:09:22.0
手游开发知识(一)--VBO在Android2.2的bug

转发,请保持地址: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

-------------------------------------------


相关参考:

  1. http://stackoverflow.com/questions/8552365/vertex-buffer-objects-vbo-not-working-on-android-2-3-3-using-gles20
  2. https://code.google.com/p/gdc2011-android-opengl/
  3. http://www.learnopengles.com/android-lesson-seven-an-introduction-to-vertex-buffer-objects-vbos/