1

what works:

shader

#version 330 core

attribute vec3 pos;
attribute vec2 uv;

    out vec3 color;

    uniform mat4 view;
    uniform mat4 projection;

    void main() {
      gl_Position = projection * view * vec4(pos.xy, sin(10.0*(pos.x + pos.y))/8.0 + 1.0, 1.0);
      color = vec3(pos.xy, sin(10.0*(pos.x + pos.y))/8.0);
    }

python

vao = glGenVertexArrays(1)
glBindVertexArray(vao)
#                            [x, y, z]
vertices = vbo.VBO(np.array([[...],[...],...], dtype=np.float32))

def draw():
    glUseProgram(program)

    glUniformMatrix4fv(projectionLoc, 1, False, perspectiveMatrix)
    glUniformMatrix4fv(viewLoc, 1, False, viewMatrix)
    vertices.bind()
    glEnableClientState(GL_VERTEX_ARRAY)
    glVertexPointer(3, GL_FLOAT, 12, vertices)
    glDrawArrays(GL_TRIANGLES, 0, lenVerticesArray)
    vertices.unbind()

I would like to either, have a separate array of uv values [x, y] to pass through to the uv attribute, or to append them to the current vertices as [x, y, z, ux, uy] and have those be the uv attribute.

I tried doing the following with the combined [x, y, z, ux, uy]:

glEnableVertexAttribArray(posLoc)
glVertexAttribPointer(posLoc, 3, GL_FLOAT, False, 12, vertices)
glEnableVertexAttribArray(uvLoc)
glVertexAttribPointer(uvLoc, 2, GL_FLOAT, False, 12, vertices+12)

However, this does not work. Everything else I have tried is some variation of this, all of which fails. I cannot seem to understand what to properly do to send the data.

1 Answer 1

1

The 5th parameter of glVertexAttribPointer is the byte offset between consecutive generic vertex attributes.

In your case an attribute tuple consist of 5 floats [x, y, z, ux, uy]. So the offset has to be 5*4 = 20.

If a named buffer object is bound, then the 6th parameter of glVertexAttribPointer is treated as a byte offset into the buffer object's data store. But anyway the type of the parameter is a pointer (c_void_p).

So if the offset is 0, then the 5th parameter can either be None or c_void_p(0) else the offset has to be caste to c_void_p:

glBindVertexArray(vao)

glEnableVertexAttribArray(posLoc)
glEnableVertexAttribArray(uvLoc)

vertices.bind()
glVertexAttribPointer(posLoc, 3, GL_FLOAT, False, 20, None)
glVertexAttribPointer(uvLoc, 2, GL_FLOAT, False, 20, c_void_p(12))

vertices.bind() is assumed to bind the vertex array object (glBindBuffer(GL_ARRAY_BUFFER, vbo)).
When glVertexAttribPointer is called then the specification of the array of generic vertex attributes is stored in the state vector of the current Vertex Array Object. So the VAO has to be bound before (glBindVertexArray(vao)).
Further a name reference to the currently bound vertex buffer object is stored in the VAO. Each vertex attribute has its own VBO reference. They can all be the same or they can be different for all or some attributes. So the Vertex Buffer Object has to be bound before, too.

Sign up to request clarification or add additional context in comments.

3 Comments

This works, I can now append the UV data to the vertex, I believe my problem was the offset and strides, I did do the c_void_p before, but it was probably the sizes that were wrong, I was using np.finfo(np.float32).nexp to get the float size (8), np.finfo(GL_FLOAT).nexp gave the same size. However, (not sure if it is my version of OpenGL) there is no glEnablePointer, its glEnableVertexAttribArray IDE returned that as the option when searching for "glEnable".
@Drew I'm very sorry, my oversight. I just copy/past that part of the code form your question and didn't further think about it.
Not an issue, that's a typo on my part, odd I copied it over wrong.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.