天天看點

OpenGL ES :java.lang.IllegalArgumentException: Must use a native order direct Buffer

首次使用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 * );
        // 數組排列用nativeOrder
        mbb.order(ByteOrder.nativeOrder());
        intBuffer = mbb.asIntBuffer();
        intBuffer.put(a);
        intBuffer.position();
        return intBuffer;
    }
}
           

實際使用時,采用如下方式

private int one = ;
 private IntBuffer triggerBuffer = BufferUtil.iBuffer(new int[]{
            , one, , //上
            -one, -one, ,//左
            one, -one, });//右