2011-12-18 241 views
9

在Android上,我試圖獲得一個運行簡單的OpenGL ES 2.0應用程序,該應用程序使用頂點緩衝區對象,但是失敗了。在Android 2.3.3上不支持頂點緩衝區對象(VBO),使用GLES20

我開始這個項目:

​​

一切都很好地解釋和作品描述。精細。

我添加了一些代碼,用glDrawElements命令替代glDrawArrays來做渲染。 我成功了。

現在下一步:我想使用頂點緩衝區對象來做同樣的事情。

所以我添加這樣的:

  1. 新瓦爾:

    私人INT [] mVBOid =新INT [2]; // VBO和索引緩衝區對象所需的2個ID private ShortBuffer mIndices; //指數使用

  2. 添加代碼來創建VBO:

    ByteBuffer vbb = ByteBuffer.allocateDirect(
          triangleCoords.length * SIZEOF_FLOAT); 
        vbb.order(ByteOrder.nativeOrder());// use the device hardware's native byte order 
        mTriangleVB = vbb.asFloatBuffer(); // create a floating point buffer from the ByteBuffer 
        mTriangleVB.put(triangleCoords); // add the coordinates to the FloatBuffer 
        mTriangleVB.position(0);   // set the buffer to read the first coordinate 
    
        ByteBuffer ibb = ByteBuffer.allocateDirect(
          indices.length * SIZEOF_SHORT); 
        ibb.order(ByteOrder.nativeOrder()); // use the device hardware's native byte order 
        mIndices = ibb.asShortBuffer();  // create a short buffer from the ByteBuffer 
        mIndices.put(indices);    // add the indices to the Buffer 
        mIndices.position(0);    // set the buffer to read the first index 
    
        GLES20.glGenBuffers(2, mVBOid, 0); 
    
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVBOid[0]); 
        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, 
          numComponentsPerVertex * SIZEOF_FLOAT, 
          mTriangleVB, 
          GLES20.GL_STATIC_DRAW); 
    
        GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mVBOid[1]); 
        GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, 
          mNumIndices * SIZEOF_SHORT, 
          mIndices, 
          GLES20.GL_STATIC_DRAW); 
    
  3. 添加代碼來繪製幾何圖形:

    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVBOid[0]); 
        GLES20.glVertexAttribPointer(maPositionHandle, nc, GLES20.GL_FLOAT, false, stride, 0); 
        GLES20.glEnableVertexAttribArray(maPositionHandle); 
    
        GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mVBOid[1]); 
        GLES20.glDrawElements(GLES20.GL_TRIANGLE_FAN, mNumIndices, GLES20.GL_UNSIGNED_SHORT, 0); 
    

注:由於首先實現的新功能在不使用VBO的情況下使用glDrawElements渲染幾何圖形正在工作,我知道mTriangleVB和mIndices變量已正確填充所需的數據。 另外maPositionHandle和muMVPMatrixHandle是正確的。 在我的代碼我檢查GL錯誤 - 沒有發現

我的問題:VBO技術不工作;屏幕上除了清晰的顏色外沒有任何東西可以看到。 在更復雜的應用程序,我得到更多的問題:其他

  • 幾何形狀而不使用了正確呈現不可見維也納組織,在引入基於VBO幾何

  • 分割故障occasionaly報道。試圖得到確切的原因,我評論了很多代碼,並最終發現,即使幾何不完全呈現,也會發生崩潰。 崩潰的原因必須是VBO的初始化 - 雖然崩潰不會立即發生,但會在一段時間後發生。
    但我仍然不明白爲什麼它不工作。

這裏有一些更多的信息:

  1. 我的環境:

    • 的Android 2.3.3
    • 構建目標:Android 2.3的。3
    • Android SDK工具:啓15
    • 的Android SDK平臺工具:啓示錄9
    • 設備:華爲的Ideos X3智能手機
  2. 完整的源爲SimpleOpenGLES20Renderer類。
    該代碼是基於該樣品:
    http://developer.android.com/resources/tutorials/opengl/opengl-es20.html

package com.hugo.simplegles20; 

import java.nio.ByteBuffer; 
import java.nio.ByteOrder; 
import java.nio.FloatBuffer; 
import java.nio.ShortBuffer; 

import javax.microedition.khronos.egl.EGLConfig; 
import javax.microedition.khronos.opengles.GL10; 

import android.opengl.GLES20; 
import android.opengl.GLSurfaceView; 
import android.opengl.Matrix; 
import android.util.Log; 


public class SimpleOpenGLES20Renderer implements GLSurfaceView.Renderer { 

    public float mAngle; 

    static String TAG = "SimpleTest"; 

    final int SIZEOF_FLOAT = Float.SIZE/8; 
    final int SIZEOF_SHORT = Short.SIZE/8; 


    private int[] mVBOid = new int[2];  // 2 ids needed for VBO and index buffer oject 


    enum TestType { 
     USE_ARRAY,   // (almost) the original code 
     USE_ELEMENTS,  // rendering, using glDrawElements call 
     USE_VBO_ELEMENTS // using a vertex buffer object (VBO) 
    } 
    private TestType mUsage = TestType.USE_VBO_ELEMENTS; 


    private boolean mFourComponents = true; 

    private int mNumIndices = 0; 

    private FloatBuffer mTriangleVB; 
    private ShortBuffer mIndices; 
    private final String vertexShaderCode = 
     // This matrix member variable provides a hook to manipulate 
     // the coordinates of the objects that use this vertex shader 
     "uniform mat4 uMVPMatrix; \n" + 

     "attribute vec4 vPosition; \n" + 
     "void main(){    \n" + 

     // the matrix must be included as a modifier of gl_Position 
     " gl_Position = uMVPMatrix * vPosition; \n" + 

     "} \n"; 

    private final String fragmentShaderCode = 
     "precision mediump float; \n" + 
     "void main(){    \n" + 
     " gl_FragColor = vec4 (0.63671875, 0.76953125, 0.22265625, 1.0); \n" + 
     "}       \n"; 

    private int mProgram; 

    private int maPositionHandle; 

    private int muMVPMatrixHandle; 

    private float[] mMVPMatrix = new float[16]; 
    private float[] mMMatrix = new float[16]; 
    private float[] mVMatrix = new float[16]; 
    private float[] mProjMatrix = new float[16]; 

    public static void checkGLError(String msg) { 
     int e = GLES20.glGetError(); 
     if (e != GLES20.GL_NO_ERROR) { 
      Log.d(TAG, "GLES20 ERROR: " + msg + " " + e); 
      Log.d(TAG, errString(e)); 
     } 
    } 
    public static String errString(int ec) { 
     switch (ec) { 
     case GLES20.GL_NO_ERROR: 
      return "No error has been recorded."; 
     case GLES20.GL_INVALID_ENUM: 
      return "An unacceptable value is specified for an enumerated argument."; 
     case GLES20.GL_INVALID_VALUE: 
      return "A numeric argument is out of range."; 
     case GLES20.GL_INVALID_OPERATION: 
      return "The specified operation is not allowed in the current state."; 
     case GLES20.GL_INVALID_FRAMEBUFFER_OPERATION: 
      return "The command is trying to render to or read from the framebuffer" + 
      " while the currently bound framebuffer is not framebuffer complete (i.e." + 
      " the return value from glCheckFramebufferStatus is not" + 
      " GL_FRAMEBUFFER_COMPLETE)."; 
     case GLES20.GL_OUT_OF_MEMORY: 
      return "There is not enough memory left to execute the command." + 
        " The state of the GL is undefined, except for the state" + 
        " of the error flags, after this error is recorded."; 
     default : 
      return "UNKNOW ERROR"; 
     } 
    } 

    @Override 
    public void onSurfaceCreated(GL10 uu, EGLConfig config) { 
     // Set the background frame color 
     GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f); 
     checkGLError("onSurfaceCreated 1"); 

     initShapes(); 

     Log.d(TAG, "load vertex shader"); 
     int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode); 
     Log.d(TAG, "load fragment shader"); 
     int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode); 

     mProgram = GLES20.glCreateProgram();    // create empty OpenGL Program 
     checkGLError("onSurfaceCreated 2"); 
     GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program 
     checkGLError("onSurfaceCreated 3"); 
     GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program 
     checkGLError("onSurfaceCreated 4"); 
     GLES20.glLinkProgram(mProgram);     // creates OpenGL program executables 
     checkGLError("onSurfaceCreated 5"); 

     // get handle to the vertex shader's vPosition member 
     maPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition"); 
     checkGLError("onSurfaceCreated 6"); 
     muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); 
     checkGLError("onSurfaceCreated 7"); 
    } 

    @Override 
    public void onSurfaceChanged(GL10 unused, int width, int height) { 
     GLES20.glViewport(0, 0, width, height); 

     float ratio = (float) width/height; 

     // this projection matrix is applied to object coordinates 
     // in the onDrawFrame() method 
     Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7); 
     Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f); 
    } 
    @Override 
    public void onDrawFrame(GL10 uu) { 
     GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); 
     checkGLError("onDrawFrame 1"); 

     // Add program to OpenGL environment 
     GLES20.glUseProgram(mProgram); 
     checkGLError("onDrawFrame 2"); 

     // Use the mAngle member as the rotation value 
     Matrix.setRotateM(mMMatrix, 0, mAngle, 0, 0, 1.0f); 

     // Apply a ModelView Projection transformation 
     Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mMMatrix, 0); 
     Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0); 

     GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0); 
     checkGLError("onDrawFrame 3"); 

     int nc = mFourComponents ? 4 : 3; 
     int stride = nc * SIZEOF_FLOAT; 

     switch (mUsage) { 
     case USE_ARRAY: 
      // Prepare the triangle data 
      GLES20.glVertexAttribPointer(maPositionHandle, nc, GLES20.GL_FLOAT, false, stride, mTriangleVB); 
      checkGLError("onDrawFrame 4"); 
      GLES20.glEnableVertexAttribArray(maPositionHandle); 
      checkGLError("onDrawFrame 5"); 

      // Draw the triangle 
      GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, mNumIndices); 
      checkGLError("onDrawFrame 6"); 
      break; 
     case USE_ELEMENTS: 
      // Prepare the triangle data 
      GLES20.glVertexAttribPointer(maPositionHandle, nc, GLES20.GL_FLOAT, false, stride, mTriangleVB); 
      checkGLError("onDrawFrame 7"); 
      GLES20.glEnableVertexAttribArray(maPositionHandle); 
      checkGLError("onDrawFrame 8"); 

      // Draw the triangle 
      // int indicesSizeInBytes = SIZEOF_SHORT * mNumIndices; 
      GLES20.glDrawElements(GLES20.GL_TRIANGLE_FAN, mNumIndices, GLES20.GL_UNSIGNED_SHORT, mIndices); 
      checkGLError("onDrawFrame 9"); 
      break; 
     case USE_VBO_ELEMENTS: 
      GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVBOid[0]); 
      checkGLError("onDrawFrame 14"); 
      GLES20.glVertexAttribPointer(maPositionHandle, nc, GLES20.GL_FLOAT, false, stride, 0); 
      checkGLError("onDrawFrame 15"); 
      GLES20.glEnableVertexAttribArray(maPositionHandle); 
      checkGLError("onDrawFrame 16"); 

      GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mVBOid[1]); 
      checkGLError("onDrawFrame 17"); 
      GLES20.glDrawElements(GLES20.GL_TRIANGLE_FAN, mNumIndices, GLES20.GL_UNSIGNED_SHORT, 0); 
      checkGLError("onDrawFrame 18"); 
      break; 
     } 
    } 

    private void initShapes(){ 

     float triangleCoords3[] = { 
       // X, Y, Z 
       -0.5f, -0.5f, 0, 
       -0.5f, 0.5f, 0, 
       -0.2f, -0.2f, 0, 
       0.5f, -0.5f, 0 
      }; 
     float triangleCoords4[] = { 
       // X, Y, Z, W 
       -0.5f, -0.5f, 0, 1, 
       -0.5f, 0.5f, 0, 1, 
       -0.2f, -0.2f, 0, 1, 
       0.5f, -0.5f, 0, 1 
      }; 

     short[] indices = {0,1,2,3}; 

     float[] triangleCoords; 

     int numComponentsPerVertex; 
     if (mFourComponents) { 
      triangleCoords = triangleCoords4; 
      numComponentsPerVertex = 4; 
     } else { 
      triangleCoords = triangleCoords3; 
      numComponentsPerVertex = 3; 
     } 

     mNumIndices = triangleCoords.length/numComponentsPerVertex; 

     Log.d(TAG, "Components per Vertex: " + numComponentsPerVertex); 
     Log.d(TAG, "Number of Indices : " + mNumIndices); 

     switch (mUsage) { 
     case USE_ARRAY: 
     { 
      Log.d(TAG, "using array"); 
      // initialize vertex Buffer for triangle 
      ByteBuffer vbb = ByteBuffer.allocateDirect(
        // (# of coordinate values * 4 bytes per float) 
        triangleCoords.length * SIZEOF_FLOAT); 
      vbb.order(ByteOrder.nativeOrder());// use the device hardware's native byte order 
      mTriangleVB = vbb.asFloatBuffer(); // create a floating point buffer from the ByteBuffer 
      mTriangleVB.put(triangleCoords); // add the coordinates to the FloatBuffer 
      mTriangleVB.position(0);   // set the buffer to read the first coordinate 
      break; 
     } 
     case USE_ELEMENTS: 
     { 
      Log.d(TAG, "using VBO elements"); 
      // initialize vertex Buffer for triangle 
      ByteBuffer vbb = ByteBuffer.allocateDirect(
        // (# of coordinate values * 4 bytes per float) 
        triangleCoords.length * SIZEOF_FLOAT); 
      vbb.order(ByteOrder.nativeOrder());// use the device hardware's native byte order 
      mTriangleVB = vbb.asFloatBuffer(); // create a floating point buffer from the ByteBuffer 
      mTriangleVB.put(triangleCoords); // add the coordinates to the FloatBuffer 
      mTriangleVB.position(0);   // set the buffer to read the first coordinate 

      vbb = ByteBuffer.allocateDirect(
        // (# of coordinate values * 2 bytes per short) 
        indices.length * SIZEOF_SHORT); 
      vbb.order(ByteOrder.nativeOrder()); // use the device hardware's native byte order 
      mIndices = vbb.asShortBuffer();  // create a short buffer from the ByteBuffer 
      mIndices.put(indices);    // add the indices to the Buffer 
      mIndices.position(0);    // set the buffer to read the first index 
      break; 
     } 
     case USE_VBO_ELEMENTS: 
     { 
      Log.d(TAG, "using VBO elements"); 
      ByteBuffer vbb = ByteBuffer.allocateDirect(
        // (# of coordinate values * 4 bytes per float) 
        triangleCoords.length * SIZEOF_FLOAT); 
      vbb.order(ByteOrder.nativeOrder());// use the device hardware's native byte order 
      mTriangleVB = vbb.asFloatBuffer(); // create a floating point buffer from the ByteBuffer 
      mTriangleVB.put(triangleCoords); // add the coordinates to the FloatBuffer 
      mTriangleVB.position(0);   // set the buffer to read the first coordinate 

      ByteBuffer ibb = ByteBuffer.allocateDirect(
        indices.length * SIZEOF_SHORT); 
      ibb.order(ByteOrder.nativeOrder()); // use the device hardware's native byte order 
      mIndices = ibb.asShortBuffer();  // create a short buffer from the ByteBuffer 
      mIndices.put(indices);    // add the indices to the Buffer 
      mIndices.position(0);    // set the buffer to read the first index 

      GLES20.glGenBuffers(2, mVBOid, 0); 
      checkGLError("initShapes 4"); 

      GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVBOid[0]); 
      checkGLError("initShapes 5"); 
      GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, 
        numComponentsPerVertex * SIZEOF_FLOAT, 
        mTriangleVB, 
        GLES20.GL_STATIC_DRAW); 
      checkGLError("initShapes 6"); 

      GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mVBOid[1]); 
      checkGLError("initShapes 7"); 
      GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, 
        mNumIndices * SIZEOF_SHORT, 
        mIndices, 
        GLES20.GL_STATIC_DRAW); 
      checkGLError("initShapes 8"); 
      break; 
     } 
     } 
    } 

    private int loadShader(int type, String shaderCode){ 

     // create a vertex shader type (GLES20.GL_VERTEX_SHADER) 
     // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER) 
     int shader = GLES20.glCreateShader(type); 
     checkGLError("loadShader 1"); 

     // add the source code to the shader and compile it 
     GLES20.glShaderSource(shader, shaderCode); 
     checkGLError("loadShader 2"); 
     GLES20.glCompileShader(shader); 
     checkGLError("loadShader 3"); 

     // Get the compilation status. 
     final int[] compileStatus = new int[1]; 
     GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compileStatus, 0); 
     checkGLError("loadShader 4"); 

     // If the compilation failed, delete the shader. 
     if (compileStatus[0] == 0) 
     { 
      Log.e(TAG, "Error compiling shader: " + GLES20.glGetShaderInfoLog(shader)); 
      GLES20.glDeleteShader(shader); 
      checkGLError("loadShader 5"); 
      shader = 0; 
     } 

     return shader; 
    } 
} 

  1. 崩潰轉儲: 12-18 14:59:02.790:I/DEBUG(85): * * * * * * * * * * * * * * * *

    12-18 14:59:02.790:I/DEBUG(85):構建指紋:「華爲/ U8510/hwu8510:2.3.3/HuaweiU8510/C169B831:用戶/ ota-rel-keys,釋放密鑰'

    12-18 14:59:02.790:I/DEBUG(85):pid:1638,tid: 1646 >>> com.gles20.step1 < < < 12 -18 14:59:02.790:I/DEBUG(85):信號11(SIGSEGV),代碼1(SEGV_MAPERR),故障地址00368000 12-18 14:59:02.790:I/DEBUG(85):r0 44affc80 r1 00367ff0 r2 0004f03c r3 00000000 12-18 14:59:02.790:I/DEBUG(85):r4 00000000 r5 00000000 r6 00000000 r7 00000028 12-18 14:59:02.790:I/DEBUG(85):r8 00000000 r9 00000000 10 00000000 fp 00000000 12-18 14:59:02.790 I/DEBUG(85):ip 00368000 sp 443ef9d0 lr 80e02a08 pc afd0cd7c cpsr 20000010 12-18 14:59:02.790:I/DEBUG(85):d0 c420e36a40000000 d1 3f800000c4a0e36a 12-18 14:59:02.790:I/DEBUG(85):d2 000000003f800000 d3 000000003f800000 12-18 14:59:02.790:I/DEBUG(85):d4 0000000000000000 d5 0000000000000000 12-18 14 :59:02.790:I/DEBUG(85):d6 3f80000000000000 d7 3f8000003f800000 12-18 14:59:02.790:I/DEBUG(85):d8 0000000000000000 d9 0000000000000000 12-18 14:59:02.800:I/DEBUG(85):d10 0000000000000000 d11 0000000000000000 12-18 14:59: 02.800:I/DEBUG(85):d12 0000000000000000 d13 0000000000000000 12-18 14:59:02.800:I/DEBUG(85):d14 0000000000000000 d15 0000000000000000 12-18 14:59:02.800:I/DEBUG(85) :scr 20000010 12-18 14:59:02.860:I/DEBUG(85):#00 pc 0000cd7c /system/lib/libc.so 12-18 14:59:02.860:I/DEBUG(85):# 01 pc 00002a04 /system/lib/libgsl.so 12-18 14:59:02.860:I/DEBUG(85):#02 pc 00089de0 /system/lib/egl/libGLESv2_adreno200.so 12-18 14:59: 02.860:I/DEBUG(85):#03 pc 00091a4a /system/lib/egl/libGLESv2_adreno200.so 12-18 14:59:02.860:I/DEBUG(85): #04 pc 000612ca /system/lib/egl/libGLESv2_adreno200.so 12-18 14:59:02.860:I/DEBUG(85):#05 pc 0006138a /system/lib/egl/libGLESv2_adreno200.so 12-18 14 :59:02.860:I/DEBUG(85):#06 pc 00063d94 /system/lib/egl/libGLESv2_adreno200.so 12-18 14:59:02。860:I/DEBUG(85):#07 pc 000836aa /system/lib/egl/libGLESv2_adreno200.so 12-18 14:59:02.860:I/DEBUG(85):#08 pc 0003fd66/system/lib/libandroid_runtime .so 12-18 14:59:02.860:I/DEBUG(85):#09 pc 00012174 /system/lib/libdvm.so 12-18 14:59:02.860:I/DEBUG(85):code around PC: 12-18 14:59:02.860:I/DEBUG(85):afd0cd5c e0422003 e2522020 3a000008 e3c1c01f 12-18 14:59:02.860:I/DEBUG(85):afd0cd6c e28cc040 e8b10ff0 f5dcf040 e2522020 12-18 (85):afd0cd8c e312001f 0a00000c e1b0ce02 28b100f0 12-18 14:59:02.860:I/DEBUG(85):afd0cd7c 849c3020 e8a00ff0 2afffff9 e2822020 12-18 14:59:02.860: I/DEBUG(85):afd0cd9c 48b10300 28a000f0 48a00300 e1b0cf02 12-18 14:59:02.860:I/DEBUG(85):code ar (85):80e029e8 e5906008 e0831001 e1510006 8a000006 12-18 14:59:02.860:I/DEBUG(85):80e029f8 e5903000 e1a0100e e0830005 eb000a13 12-bit: 18 14:59:02.860:I/DEBUG(85):80e02a08 e1a00004 e28dd008 e8bd8070 e59f104c 12-18 14:59:02.860:I/DEBUG(85):80e02a18 e59fe04c e1a02005 e79c0001 e08f100e 12-18 14:59:02.860 :I/DEBUG(85):80e02a28 e58d6000 e28000a8 ebfffef8 e3e00000 12-18 14:59:02.860:I/DEBUG(85):stack: 12-18 14:59:02.860:I/DEBUG(85):443ef990 0000018c
    12-18 14:59:02.860:I/DEBUG(85):443ef994 811bd8b0
    12-18 14:59:02.860:I/DEBUG(85):443ef998 000000c6
    12-18 14:59:02.860:I/DEBUG(85):443ef99c 443efb68
    12-18 14:59:02.860:I/DEBUG(85):443ef9a0 4360beb4
    12-18 14:59:02.860: I/DEBUG(85):443ef9a4 4360bea0
    12-18 14:59:02.860:I/DEBUG(85):443ef9a8 428da7b4
    12-18 14:59:02.870:I/DEBUG(85):443ef9ac 81089e25 /系統/ LIB/EGL/libGLESv2_adreno200.so 12-18 14:59:02.870:I/DEBUG(85):443ef9b0 001e8cc8
    12-18 14:59:02.870:I/DEBUG(85):443ef9b4 443efa6c
    12-18 14:59:02.870:I/DEBUG(85):443ef9b8 00000001
    12-18 14:59:02.870:I/DEBUG(85):443ef9bc 00000001
    12-18 14:59:02.870:I/DEBUG(85):443ef9c0 0000018c
    12-18 14:59:02.870:I/DEBUG(85):443ef9c4 afd10f08 /system/lib/libc.so 12- 18 14:59:02.870:I/DEBUG(85):443ef9c8 df002777
    12-18 14:59:02.870:I/DEBUG(85):443ef9cc e3a070ad
    12-18 14:59:02.870:I/DEBUG (85):#00 443ef9d0 00000000
    12-18 14:59:02.870:I/DEBUG(85):443ef9d4 000a3000
    12-18 14:59:02.870:I/DEBUG(85):443ef9d8 0018b834
    12-18 14:59:02.870:I/DEBUG(85):443ef9dc 443efb68
    12-18 14:59:02.870:I/DEBUG(85):443ef9e0 4360beb4
    12-18 14:59:02.870:I/DEBUG(85):443ef9e4 4360bea0
    12-18 14:59:02.870:I/DEBUG(85):443ef9e8 428da7b4
    12-18 14:59:02.870 :I/DEBUG(85):443ef9ec 44aac000
    12-18 14:59:02.870:I/DEBUG(85):00000000 443ef9f0
    12-18 14:59:02.870:I/DEBUG(85):443ef9f4 80e02a08 /system/lib/libgsl.so 12-18 14:59:02.870:I/DEBUG(85):#01 443ef9f8 001e9320
    12-18 14:59:02.870:I/DEBUG(85):443ef9fc 00000001
    12-18 14:59:02.870:I/DEBUG(85):443efa00 001e9320
    12-18 14:59:02。870:I/DEBUG(85):443efa04 00000001
    12-18 14:59:02.870:I/DEBUG(85):443efa08 001e9328
    12-18 14:59:02.870:I/DEBUG(85):443efa0c 81089de3 /system/lib/egl/libGLESv2_adreno200.so

回答

16

調查的另一天以後,我發現了一些我的代碼的問題:

  • 忘了取消綁定使用的緩衝區;這些電話都是用數據填充緩衝區後,並使用它們繪製原始後丟失:

    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mArray); 
    GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndices); 
    // fill or draw 
    // ... 
    // unbind: 
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); 
    GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0); 
    
  • 調用glBindAttribLocation必須出現在正確的時間:編譯着色器之後,但在此之前鏈接程序

    // load and compile shaders ... 
    mProgramId = loadProgram(vertexShaderSource, fragmentShaderSource); 
    
    // Bind the locations 
    GLES20.glBindAttribLocation(mProgramId, Shader.VERTEX_POS, "position"); 
    GLES20.glBindAttribLocation(mProgramId, Shader.NORMAL_POS, "normal"); 
    
    // finally link program 
    GLES20.glLinkProgram(mProgramId); 
    

    GLES20.glBindAttribLocation 
    GLES20.glEnableVertexAttribArray 
    GLES20.glVertexAttribPointer 
    

    呼叫的指標參數的

  • 誤解。規範中更深入的觀察可以幫助我。這似乎總是一個好主意。

這可能是爲別人誰有一些問題VBO安裝和使用有一個簡單,但完整的OpenGL ES 2.0應用爲出發點的幫助,所以我將在這裏發佈的代碼。

我修改這裏找到相應的應用:https://code.google.com/p/gdc2011-android-opengl,去除一切,但VBO相關代碼, 設置一些類encapsule功能,併成功地使一款Android/VBO入門套件。
這個包是一個單獨的文件,包含Activity,一些輔助類,一個基礎着色器和一個攝像機類,最重要的是一個基本的VBO類,它封裝了創建,使用和銷燬頂點緩衝對象的所有功能。
該應用程序的功能:

  • 設置一個OpenGL ES 2.0環境
  • 創建着色器,其能夠使點亮/不點亮的幾何形狀的
  • 創建一個固定照相機
  • 實例化3個基於VBO幾何,其中一個是線框格
  • 呈現彩色幾何

到u只需創建一個新的Android項目,創建一個活動「GLES20VBOTest」並使用以下文件即可。

package com.example.vbo; 

/* 
Note: these not exist or not work before Android 2.3 

GLES20.glVertexAttribPointer 
GLES20.glDrawElements 
*/ 

import java.nio.Buffer; 
import java.nio.ByteBuffer; 
import java.nio.ByteOrder; 
import java.nio.FloatBuffer; 
import java.nio.ShortBuffer; 

import javax.microedition.khronos.egl.EGLConfig; 
import javax.microedition.khronos.opengles.GL10; 

import android.app.Activity; 
import android.opengl.GLES20; 
import android.opengl.GLSurfaceView; 
import android.opengl.Matrix; 
import android.os.Bundle; 
import android.util.Log; 


public class GLES20VBOTest extends Activity { 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     GLSurfaceView view = new GLSurfaceView(this); 
     view.setEGLContextClientVersion(2); 
     view.setRenderer(new GDC11Renderer()); 

     setContentView(view); 
    } 

} 

// Helper class to create some different geometries 
class GeoData { 

    public float[] mVertices; 
    public short[] mIndices; 

    private GeoData() {} 

    static public GeoData halfpipe() { 
     GeoData creator = new GeoData(); 
     creator.mVertices = createVertices1(44); 
     creator.mIndices = createIndices1(44); 
     return creator; 
    } 

    static public GeoData circle() { 
     GeoData creator = new GeoData(); 
     creator.mVertices = createVertices2(32); 
     creator.mIndices = createIndices2(32); 
     return creator; 
    } 

    static public GeoData grid() { 
     GeoData creator = new GeoData(); 
     creator.mVertices = createGridVertices(30,30); 
     creator.mIndices = createGridIndices(30,30); 
     return creator; 
    } 

    static float[] createGridVertices(int m, int n) { 
     float[] vertices = new float[3*(2*m + 2*n + 4)]; 

     float y = 0.1f; 
     float S = 2.8f; 
     for (int i=0; i<=m; i++) { 
      float x = S*(float) (-0.5 + (1.0*i)/m); 
      float z = S*0.5f; 
      vertices[6*i + 0] = x; 
      vertices[6*i + 1] = y; 
      vertices[6*i + 2] = z; 
      vertices[6*i + 3] = x; 
      vertices[6*i + 4] = y; 
      vertices[6*i + 5] = -z; 
     } 

     int start = 3*(2*m + 2); 
     // start = 0; 
     for (int i=0; i<=n; i++) { 
      float z = S*(float) (-0.5 + (1.0*i)/n); 
      float x = S*0.5f; 
      vertices[start + 6*i + 0] = x; 
      vertices[start + 6*i + 1] = y; 
      vertices[start + 6*i + 2] = z; 
      vertices[start + 6*i + 3] = -x; 
      vertices[start + 6*i + 4] = y; 
      vertices[start + 6*i + 5] = z; 
     } 

     float[] M = new float[16]; 
     Matrix.setIdentityM(M, 0); 
     Matrix.rotateM(M, 0, 27, 0.76f, -0.9f, 1.5f); 
     int count = (2*m + 2*n + 4); 
     Log.d("MKZ", "A: " + count); 
     Log.d("MKZ", "B: " + vertices.length/3); 
     for (int i=0; i<count-1; i++) { 
      int offset = 3*i; 
      Log.d("MKZ", "offset: " + offset); 
      Matrix.multiplyMV(vertices, offset, M, 0, vertices, offset); 
     } 

     return vertices; 
    } 

    static short[] createGridIndices(int m, int n) { 
     int N = 2*(m+n+2); 
     short[] indices = new short[N]; 
     for (int i=0; i<N; i++) { 
      indices[i] = (short)i; 
     } 
     return indices; 
    } 

    static float[] createVertices1(int n) { 
     int NUM_COMPONENTS = 6; 
     float S = 0.75f; 
     float X = 1f; 
     float z0 = 1.3f; 
     float z1 = 1.1f; 
     float dx = 2*X/n; 
     float[] vertices = new float[NUM_COMPONENTS*(n+1)*2]; 
     for (int i=0; i<(n+1); i++) { 
      int I0 = 2*NUM_COMPONENTS*i; 
      int I1 = 2*NUM_COMPONENTS*i + NUM_COMPONENTS; 
      float x = -X + dx*i; 
      float y = -(float) Math.sqrt(1.0 - x*x); 
      vertices[I0 + 0] = S*x; 
      vertices[I0 + 1] = S*y; 
      vertices[I0 + 2] = S*z0; 
      vertices[I0 + 3] = x; 
      vertices[I0 + 4] = y; 
      vertices[I0 + 5] = 0; 

      vertices[I1 + 0] = S*x; 
      vertices[I1 + 1] = S*y; 
      vertices[I1 + 2] = S*z1; 
      vertices[I1 + 3] = x; 
      vertices[I1 + 4] = y; 
      vertices[I1 + 5] = 0; 
     } 
     return vertices; 
    } 
    static short[] createIndices1(int n) { 
     short[] indices = new short[(n+1)*2]; 
     for (short i=0; i<(n+1)*2; i++) { 
      indices[i] = i; 
     } 
     return indices; 
    } 

    static float[] createVertices2(int n) { 
     int NUM_COMPONENTS = 6; 
     float[] vertices = new float[NUM_COMPONENTS*(n+2)]; 
     final float S = 0.9f; 
     final float Y = -0.0f; 
     vertices[0] = 0; 
     vertices[1] = Y; 
     vertices[2] = 0; 
     vertices[3] = 0; 
     vertices[4] =-1; 
     vertices[5] = 0; 
     for (int i=0; i<=n; i++) { 
      int I = 6 + 6*i; 
      float a = (float) (0.75*2*Math.PI*i/n); 
      float x = (float) (S*Math.cos(a)); 
      float z = (float) (S*Math.sin(a)); 
      vertices[I+0] = x; 
      vertices[I+1] = Y; 
      vertices[I+2] = z; 
      vertices[I+3] = 0; 
      vertices[I+4] =-1; 
      vertices[I+5] = 0; 
     } 
     return vertices; 
    } 
    static short[] createIndices2(int n) { 
     short[] indices = new short[(n+2)]; 
     for (short i=0; i<(n+2); i++) { 
      indices[i] = i; 
     } 
     return indices; 
    } 
} 

// all GLES20 calls are made here 
class Shader { 
    // THESE ARE ARBITRARY VALUES, the only constraints are 
    // - must be different 
    // - must be less than a maximum value 
    static final int VERTEX_POS = 3; 
    static final int NORMAL_POS = 4; 
    static final int TEX_POS = 5; 
    static final String TAG = "VBOTest"; 

    private int mProgramId; 
    private int mViewProjectionLoc; 
    private int mLightVectorLoc; 
    private int mColorLoc; 
    private int mEnableLightLoc; 


    Shader() { 
     mProgramId = loadProgram(kVertexShader, kFragmentShader); 
     GLES20.glBindAttribLocation(mProgramId, Shader.VERTEX_POS, "position"); 
     GLES20.glBindAttribLocation(mProgramId, Shader.NORMAL_POS, "normal"); 
     GLES20.glLinkProgram(mProgramId); 
     mViewProjectionLoc = 
      GLES20.glGetUniformLocation(mProgramId, "worldViewProjection"); 
     mLightVectorLoc = 
      GLES20.glGetUniformLocation(mProgramId, "lightVector"); 
     mColorLoc = 
      GLES20.glGetUniformLocation(mProgramId, "color"); 
     mEnableLightLoc = 
      GLES20.glGetUniformLocation(mProgramId, "enableLight"); 

     // Other state. 
     GLES20.glClearColor(0.7f, 0.7f, 0.7f, 1.0f); 
     GLES20.glEnable(GLES20.GL_CULL_FACE); 
     GLES20.glEnable(GLES20.GL_DEPTH_TEST); 
    } 

    public void use() { 
     GLES20.glUseProgram(mProgramId); 
    } 
    public void setCamera(float[] viewProjectionMatrix) { 
     GLES20.glUniformMatrix4fv(mViewProjectionLoc, 
       1, 
       false, // transpose isn't supported 
       viewProjectionMatrix, 0); 
    } 
    public void setLight(float[] transformedLightVector) { 
     GLES20.glUniform3fv(mLightVectorLoc, 1, transformedLightVector, 0); 
    } 
    public void setColor(float[] color) { 
     GLES20.glUniform3fv(mColorLoc, 1, color, 0); 
    } 
    public void enableLight(boolean val) { 
     GLES20.glUniform1i(mEnableLightLoc, val ? 1 : 0); 
    } 

    static public void setViewPort(int width, int height) { 
     GLES20.glViewport(0, 0, width, height); 
    } 



    private static String kLogTag = "GDC11"; 

    private static int getShader(String source, int type) { 
     int shader = GLES20.glCreateShader(type); 
     if (shader == 0) return 0; 

     GLES20.glShaderSource(shader, source); 
     GLES20.glCompileShader(shader); 
     int[] compiled = { 0 }; 
     GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0); 
     if (compiled[0] == 0) { 
      Log.e(kLogTag, GLES20.glGetShaderInfoLog(shader)); 
     } 
     return shader; 
    } 

    public static int loadProgram(String vertexShader, 
      String fragmentShader) { 
     int vs = getShader(vertexShader, GLES20.GL_VERTEX_SHADER); 
     int fs = getShader(fragmentShader, GLES20.GL_FRAGMENT_SHADER); 
     if (vs == 0 || fs == 0) return 0; 

     int program = GLES20.glCreateProgram(); 
     GLES20.glAttachShader(program, vs); 
     GLES20.glAttachShader(program, fs); 
     GLES20.glLinkProgram(program); 

     int[] linked = { 0 }; 
     GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linked, 0); 
     if (linked[0] == 0) { 
      Log.e(kLogTag, GLES20.glGetProgramInfoLog(program)); 
      return 0; 
     } 
     return program; 
    } 


    private static final String kVertexShader = 
     "precision mediump float;         \n" + 
     "uniform mat4 worldViewProjection;       \n" + 
     "uniform vec3 lightVector;         \n" + 
     "attribute vec3 position;         \n" + 
     "attribute vec3 normal;          \n" + 
     "varying float light;          \n" + 
     "void main() {            \n" + 
     // |lightVector| is in the model space, so the model 
     // doesn't have to be transformed. 
     " light = max(dot(normal, lightVector), 0.0) + 0.2;  \n" + 
     " gl_Position = worldViewProjection * vec4(position, 1.0); \n" + 
     "}"; 

    private static final String kFragmentShader = 
     "precision mediump float;         \n" + 
     "uniform sampler2D textureSampler;       \n" + 
     "uniform vec3 color;          \n" + 
     "uniform int enableLight;         \n" + 
     "varying float light;          \n" + 
     "void main() {            \n" + 
     " if (1 == enableLight) {         \n" + 
     " gl_FragColor = light * vec4(color,1);     \n" + 
     " } else {             \n" + 
     " gl_FragColor = vec4(color,1);       \n" + 
     " }              \n" + 
     // " gl_FragColor = light * vec4(0.1,0.7,0.0,1);    \n" + 
     "}"; 


    public void clearView() { 
     int clearMask = GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT; 
     GLES20.glClear(clearMask); 
    } 
} 

// view matrices 
class Camera { 
    private float mPhi, mZ = 3.5f; 
    private float[] mProjectionMatrix = new float[16]; 
    private float[] mViewMatrix = new float[16]; 
    private float[] mViewProjectionMatrix = new float[16]; 


    // Updates mViewProjectionMatrix with the current camera position. 
    public void updateMatrices() { 
     Matrix.setIdentityM(mViewMatrix, 0); 
     Matrix.translateM(mViewMatrix, 0, 0, 0, -mZ); 
     Matrix.rotateM(mViewMatrix, 0, mPhi, 0, 1, 0); 
     Matrix.rotateM(mViewMatrix, 0, -90, 1, 0, 0); 
     Matrix.multiplyMM(
       mViewProjectionMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0); 
    } 

    public float[] viewMatrix() { 
     return mViewMatrix; 
    } 

    public void perspective(int width, int height) { 
     float aspect = width/(float)height; 
     perspectiveM(
       mProjectionMatrix, 
       (float)Math.toRadians(45), 
       aspect, 0.1f, 15.f); 
     // aspect, 0.5f, 5.f); 
     updateMatrices(); 
    } 

    // Like gluPerspective(), but writes the output to a Matrix. 
    static private void perspectiveM(
      float[] m, float angle, float aspect, float near, float far) { 
     float f = (float)Math.tan(0.5 * (Math.PI - angle)); 
     float range = near - far; 

     m[0] = f/aspect; 
     m[1] = 0; 
     m[2] = 0; 
     m[3] = 0; 

     m[4] = 0; 
     m[5] = f; 
     m[6] = 0; 
     m[7] = 0; 

     m[8] = 0; 
     m[9] = 0; 
     m[10] = far/range; 
     m[11] = -1; 

     m[12] = 0; 
     m[13] = 0; 
     m[14] = near * far/range; 
     m[15] = 0; 
    } 

    public void use(Shader shader) { 
     shader.setCamera(mViewProjectionMatrix); 
    } 
} 

// The renderer object. 
// Manages the graphic view/content 
class GDC11Renderer implements GLSurfaceView.Renderer { 

    // OpenGL state stuff. 
    private Shader mShader; 
    private Camera mCamera; 

    VBO mVBO1, mVBO2, mVBO3; 

    private float[] mLightVector = { 2/3.f, 1/3.f, 2/3.f }; // Needs to be normalized 
    private float[] mTransformedLightVector = new float[3]; 

    private void updateLightVector() { 

     // Transform the light vector into model space. Since mViewMatrix 
     // is orthogonal, the reverse transform can be done by multiplying 
     // with the transpose. 

     float[] viewMatrix = mCamera.viewMatrix(); 

     mTransformedLightVector[0] = 
      viewMatrix[0] * mLightVector[0] + 
      viewMatrix[1] * mLightVector[1] + 
      viewMatrix[2] * mLightVector[2]; 
     mTransformedLightVector[1] = 
      viewMatrix[4] * mLightVector[0] + 
      viewMatrix[5] * mLightVector[1] + 
      viewMatrix[6] * mLightVector[2]; 
     mTransformedLightVector[2] = 
      viewMatrix[8] * mLightVector[0] + 
      viewMatrix[9] * mLightVector[1] + 
      viewMatrix[10] * mLightVector[2];    
    } 

    // This is called continuously to render. 
    @Override 
    public void onDrawFrame(GL10 unused) { 

     mShader.use(); 
     mShader.clearView(); 
     mCamera.use(mShader); 
     mShader.setLight(mTransformedLightVector); 

     // VBO 
     mShader.enableLight(true); 

     mShader.setColor(red); 
     mVBO1.draw(); 

     mShader.setColor(gold); 
     mVBO2.draw(); 

     mShader.enableLight(false); 
     mShader.setColor(brown); 
     mVBO3.draw(); 

    } 
    static float[] green = {0.2f,1,0.2f}; 
    static float[] brown = {0.7f,0.4f,0.2f}; 
    static float[] red = {0.9f,0,0}; 
    static float[] gold = {0.9f,0.8f,0.1f}; 
    static float[] black = {0,0,0}; 


    @Override 
    public void onSurfaceCreated(GL10 unused, EGLConfig config) { 
     // CREATE GEOMETRY 
     // NEVER load stuff on the render thread in real life! 
     // You'd call fc.map() and b.load() on a loader thread, and 
     // only then upload that to GL once it's done. 

     mShader = new Shader(); 
     mCamera = new Camera(); 

     GeoData data = GeoData.halfpipe(); 
     mVBO1 = new VBO(data.mVertices, data.mIndices, GLES20.GL_TRIANGLE_STRIP, true, false, -1); 

     data = GeoData.circle(); 
     mVBO2 = new VBO(data.mVertices, data.mIndices, GLES20.GL_TRIANGLE_FAN, true, false, -1); 

     data = GeoData.grid(); 
     mVBO3 = new VBO(data.mVertices, data.mIndices, GLES20.GL_LINES, false, false, -1); 
    } 

    // This is called when the surface changes, e.g. after screen rotation. 
    @Override 
    public void onSurfaceChanged(GL10 unused, int width, int height) { 
     mCamera.perspective(width, height); 

     updateLightVector(); 

     // Necessary if the manifest contains |android:configChanges="orientation"|. 
     Shader.setViewPort(width, height); 
    } 
} 


class VBO { 
    int mNumIndices; 

    int mIndexBufferId; 
    int mVertexBufferId; 
    boolean mUseNormals; 
    boolean mUseTexCoords; 

    int mType; 
    int mNumComponents; 
    int mStride; 

    VBO(float[] vertices,    // array of vertex data 
      short[] indices,   // indices 
      int type,     // GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, 
      // GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, and GL_TRIANGLES 
      boolean vertexNormals,  // normals used ? 
      boolean vertexTexCoords, // texCoords used ? 
      int stride) {    // struct size in bytes; if stride <= 0 -> stride will be calculated 


     mType = type; 
     mUseNormals = vertexNormals; 
     mUseTexCoords = vertexTexCoords; 

     mNumComponents = 3; 
     if (mUseNormals) { 
      mNumComponents += 3; 
     } 
     if (mUseTexCoords) { 
      mNumComponents += 2; 
     } 

     if (stride <= 0) { 
      mStride = 4 * mNumComponents; 
     } else { 
      mStride = stride; 
     } 

     int[] buffers = {0,0}; 
     GLES20.glGenBuffers(2, buffers, 0); 

     mVertexBufferId = buffers[0]; 
     mIndexBufferId = buffers[1]; 

     createVertexBuffer(GLES20.GL_ARRAY_BUFFER, vertices, mVertexBufferId); 
     createIndexBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, indices, mIndexBufferId); 
     mNumIndices = indices.length; 
    } 

    void deleteBuffers() { 
     int[] buffers = {mVertexBufferId, mIndexBufferId}; 
     GLES20.glDeleteBuffers(2, buffers, 0); 
     mVertexBufferId = 0; 
     mIndexBufferId = 0; 
    } 

    void draw() { 
     if (0 == mVertexBufferId) { 
      return; 
     } 
     GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBufferId); 

     GLES20.glEnableVertexAttribArray(Shader.VERTEX_POS); 
     if (mUseNormals) { 
      GLES20.glEnableVertexAttribArray(Shader.NORMAL_POS); 
     } 
     if (mUseTexCoords) { 
      GLES20.glEnableVertexAttribArray(Shader.TEX_POS); 
     } 

     int offset = 0; 

     GLES20.glVertexAttribPointer(
       Shader.VERTEX_POS,  // generic id 
       3,      // vertex has 3 components 
       GLES20.GL_FLOAT,  // data type 
       false,     // no normalizing 
       mStride,    // stride: sizeof(float) * number of components 
       offset);    // offset 0; vertex starts at zero 
     offset += 4 * 3; 

     if (mUseNormals) { 

      GLES20.glVertexAttribPointer(
        Shader.NORMAL_POS, 
        3, 
        GLES20.GL_FLOAT, 
        false, 
        mStride, 
        offset); 
      offset += 4 * 3; 
     } 

     if (mUseTexCoords) { 

      GLES20.glVertexAttribPointer(
        Shader.TEX_POS, 
        2,      // texCoord has 2 components 
        GLES20.GL_FLOAT, 
        false, 
        mStride, 
        offset); 
      offset += 4 * 3; 
     } 

     GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndexBufferId); 
     GLES20.glDrawElements(mType, mNumIndices, GLES20.GL_UNSIGNED_SHORT, 0); 

     GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); 
     GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0); 

     GLES20.glDisableVertexAttribArray(Shader.VERTEX_POS); 
     GLES20.glDisableVertexAttribArray(Shader.NORMAL_POS); 
     GLES20.glDisableVertexAttribArray(Shader.TEX_POS); 
    } 
    static void createVertexBuffer(int target, float[] vertices, int bufferId) { 
     int size = vertices.length * 4; 
     FloatBuffer fb = ByteBuffer.allocateDirect(4*vertices.length).order(ByteOrder.nativeOrder()).asFloatBuffer(); 
     fb.put(vertices); 
     fb.position(0); 

     createBuffer(target, fb, size, bufferId); 
    } 
    static void createIndexBuffer(int target, short[] indices, int bufferId) { 
     int size = indices.length * 2; 
     ShortBuffer sb = ByteBuffer.allocateDirect(size).order(ByteOrder.nativeOrder()).asShortBuffer(); 
     sb.put(indices); 
     sb.position(0); 

     createBuffer(target, sb, size, bufferId); 
    } 
    static void createBuffer(int target, Buffer buf, int size, int bufferId) { 
     GLES20.glBindBuffer(target, bufferId); 
     GLES20.glBufferData(target, size, buf, GLES20.GL_STATIC_DRAW); 
     GLES20.glBindBuffer(target, 0); 
    } 
} 
+0

感謝您發佈此!即時通訊也有問題與VBOs.defenitly這將幫助我 – 2012-05-07 08:14:33

相關問題