2012-08-04 8 views
18

MODIFICA: Problema risolto! Quindi ho passato le esercitazioni ufficiali di OpenGL ES 2 per Android e sono giunto alla parte che riguarda il disegno delle forme, ma non riesco a far funzionare una squadra. Disegna invece un triangolo rettangolo.Android OpenGL ES 2, Quadrati di disegno

Ho incluso il codice che sto usando per definire e disegnare la forma, che viene copiata quasi esattamente dal tutorial. La classe Renderer crea semplicemente un'istanza di questa forma e chiama il metodo draw.

Per qualche motivo, il tutorial non fornisce i valori/dichiarazione per vertexStride e vertexCount, quindi quelli che ho in là sono ipotesi plausibili. Ho provato diversi valori per vertexCount (1 a 12) e nessuno funziona.

Grazie in anticipo.

  public class Square { 

       private FloatBuffer vertexBuffer; 
       private ShortBuffer drawListBuffer; 

       // number of coordinates per vertex in this array 
       static final int COORDS_PER_VERTEX = 3; 
       static float squareCoords[] = { -0.5f, 0.5f, 0.0f, // top left 
               -0.5f, -0.5f, 0.0f, // bottom left 
               0.5f, -0.5f, 0.0f, // bottom right 
               0.5f, 0.5f, 0.0f }; // top right 

       private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices 
       float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f }; 


       private final String vertexShaderCode = 
         "attribute vec4 vPosition;" + 
         "void main() {" + 
         " gl_Position = vPosition;" + 
         "}"; 

       private final String fragmentShaderCode = 
        "precision mediump float;" + 
        "uniform vec4 vColor;" + 
        "void main() {" + 
        " gl_FragColor = vColor;" + 
        "}"; 

       int mProgram; 

       static final int vertexStride = COORDS_PER_VERTEX * 4; 
       static final int vertexCount = 4; 

       public Square() { 
        // initialize vertex byte buffer for shape coordinates 
        ByteBuffer bb = ByteBuffer.allocateDirect(squareCoords.length * 4); // (# of coordinate values * 4 bytes per float) 
        bb.order(ByteOrder.nativeOrder()); 
        vertexBuffer = bb.asFloatBuffer(); 
        vertexBuffer.put(squareCoords); 
        vertexBuffer.position(0); 

        // initialize byte buffer for the draw list 
        ByteBuffer dlb = ByteBuffer.allocateDirect(drawOrder.length * 2); // (# of coordinate values * 2 bytes per short) 
        dlb.order(ByteOrder.nativeOrder()); 
        drawListBuffer = dlb.asShortBuffer(); 
        drawListBuffer.put(drawOrder); 
        drawListBuffer.position(0); 


        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode); 
        int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode); 

        mProgram = GLES20.glCreateProgram();    // create empty OpenGL ES Program 
        GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program 
        GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program 
        GLES20.glLinkProgram(mProgram);     // creates OpenGL ES program executables 
       } 

       public static 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); 

        // add the source code to the shader and compile it 
        GLES20.glShaderSource(shader, shaderCode); 
        GLES20.glCompileShader(shader); 

        return shader; 
       } 

       public void draw() { 
        // Add program to OpenGL ES environment 
        GLES20.glUseProgram(mProgram); 

        // get handle to vertex shader's vPosition member 
        int mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition"); 

        // Enable a handle to the triangle vertices 
        GLES20.glEnableVertexAttribArray(mPositionHandle); 

        // Prepare the triangle coordinate data 
        GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, 
               GLES20.GL_FLOAT, false, 
               vertexStride, vertexBuffer); 

        // get handle to fragment shader's vColor member 
        int mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor"); 

        // Set color for drawing the triangle 
        GLES20.glUniform4fv(mColorHandle, 1, color, 0); 

        // Draw the triangle 
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount); 

        // Disable vertex array 
        GLES20.glDisableVertexAttribArray(mPositionHandle); 
       } 
      } 
+2

In realtà, ho scoperto che usando solo GL_TRANGLE_FAN al posto di GL_TRIANGLES come argomento per glDrawArrays() risolve il problema. Problema risolto! Anche se qualcuno potrebbe indicarmi un'API che in realtà spiega tutti i metodi e i valori invece di elencarli come fa Android, sarebbe fantastico. –

+0

Dai un'occhiata a questo: http://stackoverflow.com/questions/6124636/gldrawarrays-vs-gldrawelements –

risposta

23
vertexCount = squareCoords.length/COORDS_PER_VERTEX; //Vertex count is the array divided by the size of the vertex ex. (x,y) or (x,y,z) 
vertexStride = COORDS_PER_VERTEX * 4;    //4 are how many bytes in a float 

fatemi sapere se che ha funzionato per voi, buona fortuna.

Penso che manchi anche la matrice ModelViewProjection utilizzata per convertire lo spazio 3D in uno spazio dello schermo 2D. mvpMatrix dovrebbe essere passato dalla funzione draw draw(float[] mvpMatrix) Hai dimenticato di menzionare che dovresti usare anche DrawElements(...) (usato nell'esempio) se fai non c'è bisogno del conteggio o del passo, solo la lunghezza di un array idicies e un buffer di disegno.

// Get handle to shape's transformation matrix 
    mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); 

    // Apply the projection and view transformation 
    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0); 

    // Draw the square 
    GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length, 
          GLES20.GL_UNSIGNED_SHORT, drawListBuffer); 
+1

Penso che questa risposta merita un segno di spunta verde.In parte perché spiega chiaramente le domande 'vertexCount' e' vertexStride' ma anche perché punta alla funzione 'GLES20.glDrawElements (...)' (che in questo caso dovrebbe sostituire 'GLES20.glDrawArray (...)' funzione). Il 'ModelViewProjection' non è richiesto, come dalla mia esperienza, a meno che non si trasformino le coordinate del mondo prima di disegnare il quadrato (che non sembra essere il caso qui). – dbm

+0

@dbm Grazie! Ho cercato di mantenerlo breve e semplice, così potrei aver perso qualcosa di altre critiche? Ho usato ModelViewProjection principalmente perché questo è quello che uso, ma anche perché ho cambiato il mio modo di trasformare le coordinate del mondo prima del disegno. –

-1
+3

Sarebbe fantastico se tu spiegassi come questo risponde alla domanda –

6

Il tutorial manca alcuni passaggi: the final code for the square is here.

L'esempio era destinato a utilizzare glDrawElements anziché glDrawArrays che è indicato dalla presenza della riga: private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices.

Questo array specifica i vertici desiderati di 2 triangoli. 0, 1 e 2 per il primo. Quindi 0, 2 e 3 per il secondo. GL_TRANGLE_FAN funziona solo perché disegnerà il prossimo triangolo usando il primo vertice nel buffer, l'ultimo vertice usato nel triangolo precedente e il vertice successivo. Per il secondo triangolo questo è 0, 2 e 3. Quindi 0, 3 e 4, ecc. Se il vertice 2 fosse 5, 5 e il vertice 3 fosse -5, 5, la ventola risultante non sarebbe stata un quadrato.

Sostituire queste righe:

// Draw the triangle 
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount); 

Con questi:

// Draw the square 
GLES20.glDrawElements(
    GLES20.GL_TRIANGLES, drawOrder.length, 
    GLES20.GL_UNSIGNED_SHORT, drawListBuffer);