2012-08-04 11 views
18

EDITAR: ¡Problema resuelto! He estado revisando los tutoriales oficiales de OpenGL ES 2 para Android, y he llegado a la parte que implica dibujar formas, pero parece que no puedo hacer que funcione un cuadrado. Dibuja un triángulo rectángulo en su lugar.Android OpenGL ES 2, cuadros de dibujo

He incluido el código que estoy usando para definir y dibujar la forma, que se copia casi exactamente del tutorial. La clase Renderer simplemente crea una instancia de esta forma y llama al método draw.

Por alguna razón, el tutorial no da los valores/declaración para vertexStride y vertexCount, por lo que los que tengo allí son conjeturas. He intentado varios valores para vertexCount (1 a 12) y ninguno funciona.

Gracias de antemano.

  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

En realidad, he encontrado que simplemente usando GL_TRANGLE_FAN en lugar de GL_TRIANGLES como un argumento para glDrawArrays() resuelve el problema. ¡Problema resuelto! Aunque si alguien pudiera indicarme una API que realmente explique todos los métodos y valores en lugar de solo enumerarlos como lo hace Android, sería genial. –

+0

Eche un vistazo a esto: http://stackoverflow.com/questions/6124636/gldrawarrays-vs-gldrawelements –

Respuesta

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 

Avísame si eso funcionó para usted, buena suerte.

Creo que también le falta la ModelViewProjection matriz utilizada para convertir espacio en 3D a espacio de pantalla en 2D. mvpMatrix debe pasarse por la función draw draw(float[] mvpMatrix) Olvidó mencionar que también debe usar DrawElements(...) (utilizado en el ejemplo) si lo hace no es necesario el conteo o stride, solo la longitud de un conjunto de idicies y un buffer de dibujo.

// 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

Creo que esta respuesta merece una marca de verificación verde.En parte porque explica claramente las preguntas 'vertexCount' y' vertexStride' pero también porque apunta a la función 'GLES20.glDrawElements (...)' (que en este caso debería reemplazar 'GLES20.glDrawArray (...)' función). El 'ModelViewProjection' no es necesario, según mi experiencia, a menos que no transformes las coordenadas de tu mundo antes de dibujar tu cuadrado (que no parece ser el caso aquí). – dbm

+0

@dbm ¡Gracias! Traté de mantenerlo corto y simple así que podría haberme perdido algo de otras críticas. Usé ModelViewProjection principalmente porque eso es lo que uso, pero también porque he cambiado mi forma de transformar las coordenadas del mundo antes de dibujar. –

-1
+3

Sería genial si explicaras cómo responde esto a la pregunta –

6

El tutorial le faltan algunos pasos: the final code for the square is here.

El ejemplo fue diseñado para usar glDrawElements en lugar de glDrawArrays que se indica con la presencia de la línea: private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices.

Esta matriz especifica los vértices deseados de 2 triángulos. 0, 1 y 2 para el primero. Luego 0, 2 y 3 para el segundo. GL_TRANGLE_FAN simplemente funciona porque dibujará el siguiente triángulo usando el primer vértice en el buffer, el último vértice usado en el triángulo anterior y el siguiente vértice. Para el segundo triángulo esto es 0, 2 y 3. Luego 0, 3 y 4, etc. Si el vértice 2 hubiera sido 5, 5 y el vértice 3 hubiera sido -5, 5, el ventilador resultante no habría sido un cuadrado.

reemplazar estas líneas:

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

Con éstos:

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