Hot questions for Using Lightweight Java Game Library in vao

Question:

I have a problem validating my shader program in LWJGL/OpenGL 3. I read the documentation, but I can't seem to find a reason why a VAO is needed when calling glValidateProgram.

int program = glCreateProgram();
int vertexShader = glCreateShader(...);
int fragmentShader = glCreateShader(...);
// ... vertex and fragment shader loading, compiling, errorchecking ...
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glBindAttribLocation(program, 0, "position");
glBindAttribLocation(program, 1, "color");
glLinkProgram(program);
glDetachShader(program, shader);
glDetachShader(program, shader);
glValidateProgram(program);
if (glGetProgrami(program, GL_VALIDATE_STATUS) != GL_TRUE)
    System.exit(-1);

This exits the program without any error message.GL_LINK_STATUS is OK and GL.getErrors() also has nothing to report. But when creating a VAO around glValidateProgram it works just fine. I can also just ignore the fact that glGetProgrami returns GL_FALSE and just run the shader program.

What i mean with creating a VAO around glValidateProgram():

int vao = glGenVertexArrays();
glBindVertexArray(vao);
glValidateProgram(program);
if (glGetProgrami(program, GL_VALIDATE_STATUS) != GL_TRUE)
    System.exit(-1);
glDeleteVertexArrays(vao);

When I do this, GL_VALIDATE_STATUS is true and I can draw my stuff.

The used shaders are simple passthrough shaders.The vertex shader returns the position and the fragment shader returns the color.

So, why do I have to bind an VAO even though I can immediately delete it after the validation?


Answer:

This behavior matches the OpenGL spec. I'm using the OpenGL 3.3 spec as reference.

In appendix E.2.2 "Removed Features" on page 344, it says:

The default vertex array object (the name zero) is also deprecated. Calling VertexAttribPointer when no buffer object or no vertex array object is bound will generate an INVALID_OPERATION error, as will calling any array drawing command when no vertex array object is bound.

The spec for glValidateProgram() on page 82 says:

ValidateProgram will check for all the conditions that could lead to an INVALID_OPERATION error when rendering commands are issued, and may check for other conditions as well.

So because issuing a draw command without a VAO bound will given a GL_INVALID_OPERATION error, and glValidateProgram() checks if a draw command would give a GL_INVALID_OPERATION error, what you're seeing is exactly as expected.

Question:

I am currently trying to draw shapes from a 3d engine that is already made for me that will output me a shape with vertices and triangles. the vertices are listed once only and triangles are built counterclockwise. I am having an Issue with the drawing part because at a certain point OpenGL starts using indices that I do not specify.

The code for setting up the shape into buffers and VBO is here:

//Reset index Count
    indicesCount.add(s.triangles().size() * 3);
    int vertexCount = s.getVertices().size() * 3;

    //Set Hash Map
    s.setHashMap();

    for (int i = 0; i < s.getVertices().size(); i++) {
        System.err.println(s.getVertices().get(i));
    }

    //Initialize the Buffers
    vertBuff = BufferUtils.createFloatBuffer(vertexCount);
    normalBuff = BufferUtils.createFloatBuffer(vertexCount);
    indicesBuff = BufferUtils.createIntBuffer(indicesCount.get(this.objectCount - 1));

    //Place all the indices into the ByteBuffer
    ArrayList<Triangle> tempTriangles = s.triangles();

    for (Triangle t : tempTriangles) {
        for (int i = 0; i < 3; i++) {
            indicesBuff.put((s.getHashMap().get(t.vertex.get(i))));
            System.err.print(s.getHashMap().get(t.vertex.get(i)));
        }
        System.err.print('\n');
    }

    System.out.println("Hashmap: " + s.getHashMap().toString());

    //Place all the vertices in the FloatBuffer
    for (Vector v : s.getVertices()) {
        vertBuff.put((float) v.x);
        vertBuff.put((float) v.y);
        vertBuff.put((float) v.z);
        normalBuff.put((float) v.normalized().x);
        normalBuff.put((float) v.normalized().y);
        normalBuff.put((float) v.normalized().z);
    }

    //Close the Buffer for input
    vertBuff.flip();
    indicesBuff.flip();
    normalBuff.flip();

    generateOneVBO();
    setChanged(true);
}
 private void generateOneVBO() {

    vao_IDs.add(glGenVertexArrays());
    glBindVertexArray(vao_IDs.get(this.objectCount - 1));
    i_IDs.add(glGenBuffers());
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_IDs.get(this.objectCount - 1));
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesBuff, GL_STATIC_DRAW);
    // glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    //Generate Buffers and get IDs
    v_IDs.add(glGenBuffers());
    glBindBuffer(GL_ARRAY_BUFFER, v_IDs.get(this.objectCount - 1));
    glBufferData(GL_ARRAY_BUFFER, vertBuff, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

This is my render function(that loops whenever there is a change)

private synchronized void render(int p_Id) {
    Vector4f selectedColor = new Vector4f(1, 0, 0, 1f);
    Vector4f normalColor = new Vector4f(0.5f, 0.5f, 0.5f, 1f);

    // glMatrixMode(GL_PROJECTION_MATRIX);
    for (int index = 0; index < v_IDs.size(); index++) {

        glBindVertexArray(vao_IDs.get(index));
        glEnableVertexAttribArray(0);
        glEnableVertexAttribArray(1);

        //  glPointSize(3.0f);
        // glEnable(GL_POINT_SMOOTH);
        //Draw triangles
        if (selected.get(index)) {
            shader.setUniform(p_Id, "shapeColor", selectedColor);
        } else {
            shader.setUniform(p_Id, "shapeColor", normalColor);
        }
        //glDrawElements(GL_TRIANGLES, indicesCount.get(index), GL_UNSIGNED_INT, 0);
        //Draw Wireframe
        shader.setUniform(p_Id, "shapeColor", new Vector4f(1, 1, 1, 0.75f));
        //glDrawElements(GL_LINE_STRIP, indicesCount.get(index), GL_UNSIGNED_INT, 0);
        int num = 0;
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

        Vector4f[] arr = {
            new Vector4f(1f, 0, 0, 1),
            new Vector4f(0f, 1, 0, 1),
            new Vector4f(0f, 0, 1, 1)
        };

        for (int i = 0; i < toDraw; i += 3) {
            if (i % 3 == 0) {
                num++;
            }
            shader.setUniform(p_Id, "shapeColor", arr[num % 3]);
              glDrawElements(GL_POLYGON, i + 3, GL_UNSIGNED_INT, i);
        }

        glDisableVertexAttribArray(0);
        glDisableVertexAttribArray(1);
        glBindVertexArray(0);

    }
}

I made the render loop draw my triangle wireframe/triangles step by step by adding a click listener and adding 3 to the toDraw variable, with this i could see the first time it messes up. In addition to the code i printed out both the hashmap that is used to convert from vertex to index, and an output of indices that is printed after each index is added to the buffer.

 Hashmap: {15.0 -15.0 15.0=2, -15.0 -15.0 15.0=3, 15.0 15.0 15.0=0, -15.0 15.0 15.0=1, -15.0 -15.0 -15.0=7, 15.0 -15.0 -15.0=6, -15.0 15.0 -15.0=5, 15.0 15.0 -15.0=4}

Indices:

201
213
315
357
045
051
264
240
675
654
623
637.

each triplet of numbers is a triangle so the first one is a triangle pointing at indices 2->0->1 and so on.

Here is the window after the first triangle

Window after the second click

Window after the third click which is where it first gets messed up

I have been debugging this for a few days now and I do not know what is wrong. I think that it might be the way I draw it(the parameters I give it), but that's just a guess.


Answer:

You are not drawing triangles:

          glDrawElements(GL_POLYGON, i + 3, GL_UNSIGNED_INT, i);

You are drawing Polygons with n vertices. For i=0, you will actually end up with a triangle. For i=3 (and you're increasing i in steps of 3 in the loop`, you end up drawing an hexagon, with using 6 elements of your index buffer, starting from the fourth byte. And so on.

Question:

Is there a way to overwrite or clear an attribute location in OpenGL? For example (I'm using lwjgl) I render something like this:

public void render(int vaoID, int vertexCount, int shaderProgramID){
    GL30.glBindVertexArray(vaoID);

    GL20.glBindAttribLocation(shaderProgramID, 0, "position");
    GL20.glBindAttribLocation(shaderProgramID, 1, "normal");

    GL20.glEnableVertexAttribArray(0);
    GL20.glEnableVertexAttribArray(1);

    GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, vertexCount);

    GL20.glDisableVertexAttribArray(0);
    GL20.glDisableVertexAttribArray(1);

    GL30.glBindVertexArray(0);
}

and after that I want to run the next code with the same shaderProgramID

public void render(int vaoID, int vertexCount, int shaderProgramID){
    GL30.glBindVertexArray(vaoID);

    //this previously was position
    GL20.glBindAttribLocation(shaderProgramID, 0, "normal");
    //and this was the normal
    GL20.glBindAttribLocation(shaderProgramID, 1, "position");

    GL20.glEnableVertexAttribArray(0);
    GL20.glEnableVertexAttribArray(1);

    GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, vertexCount);

    GL20.glDisableVertexAttribArray(0);
    GL20.glDisableVertexAttribArray(1);

    GL30.glBindVertexArray(0);
}

As you can see i changed the following code from this:

GL20.glBindAttribLocation(shaderProgramID, 0, "position");
GL20.glBindAttribLocation(shaderProgramID, 1, "normal");

to this:

GL20.glBindAttribLocation(shaderProgramID, 0, "normal");
GL20.glBindAttribLocation(shaderProgramID, 1, "position");

But when i run both of the code, the

GL20.glGetAttribLocation(programID, "position");

returns 0 instead of 1

Is there a way to clear the previously bound locations so that I can bind new ones?


Answer:

You must re-link your program after binding attribute locations. This is outlined in the documentation for glBindAttribLocation (...) as follows:

Name

glBindAttribLocation — Associates a generic vertex attribute index with a named attribute variable

C Specification

void glBindAttribLocation( GLuint program, GLuint index, const GLchar *name);

Description

[...]

Attribute variable name-to-generic attribute index bindings for a program object can be explicitly assigned at any time by calling glBindAttribLocation. Attribute bindings do not go into effect until glLinkProgram is called. After a program object has been linked successfully, the index values for generic attributes remain fixed (and their values can be queried) until the next link command occurs.

Any attribute binding that occurs after the program object has been linked will not take effect until the next time the program object is linked.