首次使用OpenGL ES开发时,经常会出现以下问题:
java.lang.IllegalArgumentException: Must use a native order direct Buffer
at com.google.android.gles_jni.GLImpl.glVertexPointerBounds(Native Method
原因:
在Android1.6版本以上运行就会出现,是因为 OpenGL是一个非常底层的画图接口,它所使用的缓冲区存储结构是和java程序中不相同的。Java是大端字节序(BigEdian),而OpenGL所需要的数据是小端字节序(LittleEdian)。所以,我们需要 Java 的缓冲区转化为 OpenGL 可用的缓冲区。
补充说明:
(1)大端排序(BigEdian):高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。
(2)小端排序(LittleEdian):低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
举一个例子,比如数字0x12 34 56 78在内存中的表示形式为:
1)大端模式:
低地址 —————–> 高地址
0x12 | 0x34 | 0x56 | 0x78
2)小端模式:
低地址 —————–> 高地址
0x78 | 0x56 | 0x34 | 0x12
解决方案:
我们知道是因为采用大小端模式不同,导致出现该问题的,那么我可以对缓存区数据,人为更改数据高低端地址的存储,将Java的大端模式更改为适用OpenGL的小端模式。
public class BufferUtil {
public static IntBuffer intBuffer;
public static IntBuffer iBuffer(int[] a) {
// 先初始化buffer,数组的长度*4,因为一个int占4个字节
ByteBuffer mbb = ByteBuffer.allocateDirect(a.length * 4);
// 数组排列用nativeOrder
mbb.order(ByteOrder.nativeOrder());
intBuffer = mbb.asIntBuffer();
intBuffer.put(a);
intBuffer.position(0);
return intBuffer;
}
}
实际使用时,采用如下方式
private int one = 0x100000;
private IntBuffer triggerBuffer = BufferUtil.iBuffer(new int[]{
0, one, 0, //上
-one, -one, 0,//左
one, -one, 0});//右