28 votes

Android OpenGL ES 2, Dessin de carrés

EDIT : Problème résolu ! J'ai parcouru les tutoriels officiels d'OpenGL ES 2 pour Android, et je suis arrivé à la partie qui concerne le dessin de formes, mais je n'arrive pas à faire fonctionner un carré. Il dessine un triangle droit à la place.

J'ai inclus le code que j'utilise pour définir et dessiner la forme, qui est copié presque exactement du tutoriel. La classe Renderer crée simplement une instance de cette forme et appelle la méthode draw.

Pour une raison quelconque, le tutoriel ne donne pas les valeurs/déclarations pour vertexStride et vertexCount, donc celles que j'ai là sont des suppositions éclairées. J'ai essayé plusieurs valeurs pour vertexCount (1 à 12), mais aucune ne fonctionne.

Merci d'avance.

            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);
                }
            }

27voto

Nate Points 1888
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

Faites-moi savoir si ça a marché pour vous, bonne chance.

Je pense que vous oubliez aussi le ModelViewProjection Matrice utilisée pour convertir l'espace 3D en espace d'écran 2D. mvpMatrix doit être transmise par la fonction draw. draw(float[] mvpMatrix) J'ai oublié de mentionner que vous devez également utiliser DrawElements(...) (utilisé dans l'exemple) si vous le faites, il n'y a pas besoin de count ou stride, juste de la longueur d'un tableau d'idicies et d'un tampon de dessin.

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

23voto

mrfelis Points 606

Le tutoriel manque certaines étapes : le code final pour le carré est ici .

L'exemple était destiné à utiliser glDrawElements au lieu de glDrawArrays ce qui est indiqué par la présence de la ligne : private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices .

Ce tableau spécifie les sommets souhaités de 2 triangles. 0, 1 et 2 pour le premier. Puis 0, 2 et 3 pour le second. GL_TRANGLE_FAN fonctionne parce qu'elle dessine le triangle suivant en utilisant le premier sommet du tampon, le dernier sommet utilisé dans le triangle précédent et le sommet suivant. Pour le deuxième triangle, c'est 0, 2 et 3. Puis 0, 3 et 4, etc. Si le sommet 2 avait été 5, 5 et le sommet 3 -5, 5, l'éventail résultant n'aurait pas été un carré.

Remplacez ces lignes :

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

Avec ça :

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

-1voto

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X