Corentin
Corentin

Reputation: 49

How to render a quad with OpenGL ES using drawElements and an indices array?

I am currently learning android development to programme a tile based game, but I can't get OpenGLES working correctly.

So I am trying to render a quad using an index array, but it's only rendering the first triangle of the quad and the second is missing, so I am assuming OpenGL doesn't get somehow my indices array. Or maybe I don't generate my ibo correctly, I don't know... Here is some of my code where I think the problem could be. If you need more code, just ask:

My class which renders a simple quad graphics.ModelSquare:

package com.gametheque.mobilegameengine.graphics;

import android.opengl.GLES20;
import android.opengl.Matrix;
import com.gametheque.mobilegameengine.util.Color;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

public class ModelSquare extends Model {

    private float vertexArray[] = {
            0.0f,  1.0f, 0.0f,   // top left
            0.0f, 0.0f, 0.0f,   // bottom left
            1.0f, 0.0f, 0.0f,   // bottom right
            1.0f,  0.0f, 0.0f }; // top right
    private short indicesArray[] = { 0, 1, 2, 0, 2, 3 };

    private FloatBuffer vertexBuffer;
    private ShortBuffer indicesBuffer;
    private int indicesID[] = new int[1];
    private int verticesID[] = new int[1];

    float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };

    float[] modelViewMatrix = new float[16];

    public ModelSquare(){
        vertexBuffer = Util.loadFloatBuffer(vertexArray);
        indicesBuffer = Util.loadShortBuffer(indicesArray);
        Util.loadVBO(indicesID, indicesBuffer);
        Util.loadVBO(verticesID, vertexBuffer);
    }

    public void draw(ShaderProgram shader, float[] projectionMatrix, float[] viewMatrix, float[] modelMatrix, int hexcolor) {
        // Add program to OpenGL environment
        GLES20.glUseProgram(shader.getProgramID());

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

        // Prepare the triangle coordinate data
        GLES20.glVertexAttribPointer(
                shader.getAttrib_location_vertices(), COORDS_PER_VERTEX,
                GLES20.GL_FLOAT, false,
                COORDS_PER_VERTEX * 4, vertexBuffer);

        // Set color for drawing the triangle
        color[0] = Color.colorFromHex(hexcolor, 'r')/255;
        color[1] = Color.colorFromHex(hexcolor, 'g')/255;
        color[2] = Color.colorFromHex(hexcolor, 'b')/255;
        GLES20.glUniform4fv(shader.getUniform_location_color(), 1, color, 0);

        // Apply the projection and view transformation
        Matrix.multiplyMM(modelViewMatrix, 0, viewMatrix, 0, modelMatrix, 0);
        GLES20.glUniformMatrix4fv(shader.getUniform_location_projectionMatrix(), 1, false, projectionMatrix, 0);
        GLES20.glUniformMatrix4fv(shader.getUniform_location_ModelViewMatrix(), 1, false, modelViewMatrix, 0);

        // Draw the square
        GLES20.glDrawElements(GLES20.GL_TRIANGLES, indicesArray.length, GLES20.GL_UNSIGNED_SHORT, indicesBuffer);

        // Disable vertex array
        GLES20.glDisableVertexAttribArray(shader.getAttrib_location_vertices());
    }

}

And my class which creates the ibo graphics.Util:

package com.gametheque.mobilegameengine.graphics;

import android.opengl.GLES20;

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

public class Util {

    public static FloatBuffer loadFloatBuffer(float[] array) {
        FloatBuffer floatBuffer;
        // initialize vertex byte buffer for shape coordinates
        ByteBuffer bb = ByteBuffer.allocateDirect(
                // (number of coordinate values * 4 bytes per float)
                array.length * 4);
        // use the device hardware's native byte order
        bb.order(ByteOrder.nativeOrder());

        // create a floating point buffer from the ByteBuffer
        floatBuffer = bb.asFloatBuffer();
        // add the coordinates to the FloatBuffer
        floatBuffer.put(array);
        // set the buffer to read the first coordinate
        floatBuffer.position(0);

        return floatBuffer;
    }

    public static ShortBuffer loadShortBuffer(short[] array) {
        ShortBuffer shortBuffer = ByteBuffer.allocateDirect(array.length * 2).order(ByteOrder.nativeOrder()).asShortBuffer();
        shortBuffer.put(array).position(0);
        return shortBuffer;
    }

    public static void loadVBO(int[] iboID, ShortBuffer buffer){

        int m_tailleBytes = buffer.limit() * 2;

        // Génération de l'ID
        GLES20.glGenBuffers(1, iboID, 0);

        // Verrouillage du VBO
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, iboID[0]);

        // Allocation de la mémoire
        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, m_tailleBytes, buffer, GLES20.GL_STATIC_DRAW);

        // Déverrouillage de l'objet
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
    }

    public static void loadVBO(int[] vboID, FloatBuffer buffer){

        int m_tailleBytes = buffer.limit() * 4;

        // Génération de l'ID
        GLES20.glGenBuffers(1, vboID, 0);

        // Verrouillage du VBO
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboID[0]);

        // Allocation de la mémoire
        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, m_tailleBytes, buffer, GLES20.GL_STATIC_DRAW);

        // Déverrouillage de l'objet
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
    }

}

Here is a screenshot:

screenshot

Upvotes: 2

Views: 1448

Answers (1)

Victor
Victor

Reputation: 471

I noticed wrong coordinates for last vertex

 private float vertexArray[] = {
            0.0f,  1.0f, 0.0f,   // top left
            0.0f, 0.0f, 0.0f,   // bottom left
            1.0f, 0.0f, 0.0f,   // bottom right
            1.0f,  0.0f, 0.0f }; // top right  << Here

Should be

  1.0f,  1.0f, 0.0f }; // top right

So for one you get your second triangle degraded.

Upvotes: 3

Related Questions