1

Edit: I should clarify a bit...

This is how I've planned for things to work:

  1. Each time my application renders (60hz) I want to put all vertices that are to be rendered into a huge buffer. Then, that buffer will be uploaded to the GPU. (glBufferdata).

  2. I will then use glDrawElements to render the whole thing in one call.

This is how I'm trying to implement it:

Setup: 1. create a huge FloatBuffer (java) 2. init my VOB (this is still a bit illusive to me, but I think I've gotten it right.) I'm using a EBO to cut down on vertices.

Render: 1. put tons of vertices in my FloatBuffer 2. upload my floatbuffer to the GPU 3. render it with glDrawElements.

Result: The first quad renders fine. All the rest don't render at all.

Problem Why doesn't all the quads render?

This is how I use the class Renderer2 below:

r = new Renderer(); loop: Renderer.bind(); for many, many objects... Renderer.render(x1, x2, y1, y2, Color top, Color bottom); ... Renderer.flush(); break loop;

public class Renderer2
{
    private util.ShaderProgram shaderProgram;

private int vaoID;
private int vboVertID;
private int eboID;

FloatBuffer vboBuff;

private final int floatsPerQuad = 6;
private int nrOfVert = 0;


public Renderer2(){
    String VERTEX = "#version 330 core" + "\n"
            + "layout(location = 0) in vec2 position;" + "\n"
            + "layout(location = 1) in vec4 color;" + "\n"
            + "out vec4 vColor;" + "\n"
            + "void main(){" + "\n"
            + "vColor = color;" + "\n"
            + "gl_Position = vec4(position, 0.0, 1.0);" + "\n"
            + "}";

    String FRAGMENT = "#version 330 core" + "\n"
            + "in vec4 vColor;" + "\n"
            + "out vec4 fragColor;" + "\n"
            + "void main(){" + "\n"
            + "fragColor = vColor;" + "\n"
            + "}";

    shaderProgram = new ShaderProgram();
    shaderProgram.attachVertexShader(VERTEX);
    shaderProgram.attachFragmentShader(FRAGMENT);
    shaderProgram.link();

    vboBuff = BufferUtils.createFloatBuffer(25000);

    // Generate and bind a Vertex Array
    vaoID = glGenVertexArrays();
    glBindVertexArray(vaoID);

    // The indices that form the rectangle
    short[] indices = new short[]
    {
        0, 1, 2,  // The indices for the left triangle
        1, 2, 3   // The indices for the right triangle
    };

    // Create a Buffer Object and upload the vertices buffer
    vboVertID = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, vboVertID);

    // Point the buffer at location 0, the location we set
    // inside the vertex shader. You can use any location
    // but the locations should match
    glVertexAttribPointer(0, 2, GL_FLOAT, false, 24, 0);
    glVertexAttribPointer(1, 4, GL_FLOAT, false, 24, 8);
    // Create a Buffer Object and upload the colors buffer

    // Create a ShortBuffer of indices
    ShortBuffer indicesBuffer = BufferUtils.createShortBuffer(indices.length);
    indicesBuffer.put(indices).flip();

    // Create the Element Buffer object
    eboID = glGenBuffers();
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eboID);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesBuffer, GL_STATIC_DRAW);

    // Enable the vertex attribute locations
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);

    glBindVertexArray(0);
}

public void bind(){
    vboBuff.clear();
    glBindVertexArray(vaoID);
    shaderProgram.bind();
    nrOfVert = 0;
}

public void render(float x1, float x2, float y1, float y2, Color top, Color bottom){

    vboBuff.put(x1).put(y1);
    vboBuff.put(top.r).put(top.g).put(top.b).put(top.a);
    vboBuff.put(x2).put(y1);
    vboBuff.put(top.r).put(top.g).put(top.b).put(top.a);
    vboBuff.put(x1).put(y2);
    vboBuff.put(bottom.r).put(bottom.g).put(bottom.b).put(bottom.a);
    vboBuff.put(x2).put(y2);
    vboBuff.put(bottom.r).put(bottom.g).put(bottom.b).put(bottom.a);

    nrOfVert += floatsPerQuad;
}

public void flush(){

    vboBuff.flip();

    glBindBuffer(GL_ARRAY_BUFFER, vboVertID);

    glBufferData(GL_ARRAY_BUFFER, vboBuff, GL_DYNAMIC_DRAW);

    glDrawElements(GL_TRIANGLES, nrOfVert, GL_UNSIGNED_SHORT, 0);

    glBindVertexArray(0);
    ShaderProgram.unbind();
}

public void dispose()
{
    // Dispose the program
    shaderProgram.dispose();

    // Dispose the vertex array
    glBindVertexArray(0);
    glDeleteVertexArrays(vaoID);

    // Dispose the buffer object
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glDeleteBuffers(vboVertID);

    // Dispose the element buffer object
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glDeleteBuffers(eboID);
}

}

Jake
  • 843
  • 1
  • 7
  • 18
  • Ok, I think I found the culprit. When defining the indices, I need to define one set for each quad I intend to draw. I though the indices buffer would be reused for each element. – Jake Apr 21 '15 at 12:43
  • SO, I suppose I'll just generate a huge index buffer and keep it static in my initiation phase. Is this efficient? – Jake Apr 21 '15 at 12:47

1 Answers1

0

Since you already found your answer in the comment section and now are asking if making a huge index buffer and keep it static is efficient:

If the data is not gonna be changed, you should declare your array buffer with GL_STATIC_DRAW. GL_DYNAMIC_DRAW implies to the GPU that you are gonna be constantly changing the buffer data and that makes the drivers handle your data differently.

If you are really worried about performance, I suggest you looking at different rendering methods like instancing if the quads that you are rendering are the same or vary only by color or something. Take a look at this OpenGL Best Practices and experiment with some of the methods.

sgtHale
  • 1,507
  • 1
  • 16
  • 28