Saturday, December 8, 2012

Vertex Array Objects in PyOpenGL

It has come to my attention that there aren't any good examples available of how to use vertex array objects in PyOpenGL. 

Vertex Array Objects (VAOs) allow all the attributes and buffers needed to draw an object to be stored during initialization and called back whenever the object needs to be drawn. This can speed up the rendering process and result in cleaner code.

To read more about VAOs see Learning Modern 3D Graphics Programming - Chapter 5

Here's an example of using VAOs in PyOpenGL.
import OpenGL.GL as GL
import OpenGL.GL.shaders
import ctypes
import pygame
import numpy
vertex_shader = """
#version 330
in vec4 position;
void main()
{
gl_Position = position;
}
"""
fragment_shader = """
#version 330
void main()
{
gl_FragColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);
}
"""
vertices = [ 0.6, 0.6, 0.0, 1.0,
-0.6, 0.6, 0.0, 1.0,
0.0, -0.6, 0.0, 1.0]
vertices = numpy.array(vertices, dtype=numpy.float32)
def create_object(shader):
# Create a new VAO (Vertex Array Object) and bind it
vertex_array_object = GL.glGenVertexArrays(1)
GL.glBindVertexArray( vertex_array_object )
# Generate buffers to hold our vertices
vertex_buffer = GL.glGenBuffers(1)
GL.glBindBuffer(GL.GL_ARRAY_BUFFER, vertex_buffer)
# Get the position of the 'position' in parameter of our shader and bind it.
position = GL.glGetAttribLocation(shader, 'position')
GL.glEnableVertexAttribArray(position)
# Describe the position data layout in the buffer
GL.glVertexAttribPointer(position, 4, GL.GL_FLOAT, False, 0, ctypes.c_void_p(0))
# Send the data over to the buffer
GL.glBufferData(GL.GL_ARRAY_BUFFER, 48, vertices, GL.GL_STATIC_DRAW)
# Unbind the VAO first (Important)
GL.glBindVertexArray( 0 )
# Unbind other stuff
GL.glDisableVertexAttribArray(position)
GL.glBindBuffer(GL.GL_ARRAY_BUFFER, 0)
return vertex_array_object
def display(shader, vertex_array_object):
GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)
GL.glUseProgram(shader)
GL.glBindVertexArray( vertex_array_object )
GL.glDrawArrays(GL.GL_TRIANGLES, 0, 3)
GL.glBindVertexArray( 0 )
GL.glUseProgram(0)
def main():
pygame.init()
screen = pygame.display.set_mode((512, 512), pygame.OPENGL|pygame.DOUBLEBUF)
GL.glClearColor(0.5, 0.5, 0.5, 1.0)
GL.glEnable(GL.GL_DEPTH_TEST)
shader = OpenGL.GL.shaders.compileProgram(
OpenGL.GL.shaders.compileShader(vertex_shader, GL.GL_VERTEX_SHADER),
OpenGL.GL.shaders.compileShader(fragment_shader, GL.GL_FRAGMENT_SHADER)
)
vertex_array_object = create_object(shader)
clock = pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
if event.type == pygame.KEYUP and event.key == pygame.K_ESCAPE:
return
display(shader, vertex_array_object)
pygame.display.flip()
if __name__ == '__main__':
try:
main()
finally:
pygame.quit()
view raw main.py hosted with ❤ by GitHub
https://gist.github.com/4243336