Using OpenGL with Pygame (Advanced)

OpenGL specifies an API for 2D and 3D computer graphics. The API consists of functions and constants. We will be concentrating on the Python implementation called PyOpenGL.

Getting ready

Install PyOpenGL with the following command:

pip install PyOpenGL PyOpenGL_accelerate

You might need to have root access to execute this command. The corresponding easy_install command is as follows:

easy_install PyOpenGL PyOpenGL_accelerate

How to do it...

For the purpose of demonstration we will draw a Sierpinski gasket with OpenGL. This is a fractal pattern in the shape of a triangle created by the mathematician Waclaw Sierpinski. The triangle is obtained via a recursive and in principle infinite procedure.

  1. OpenGL Initialization: First, we will start out by initializing some of the OpenGL-related primitives. This includes setting the display mode and background color. A line-by-line explanation is given at the end of the recipe:
    def display_openGL(w, h):
      pygame.display.set_mode((w,h), pygame.OPENGL|pygame.DOUBLEBUF)
    
      glClearColor(0.0, 0.0, 0.0, 1.0)
      glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
    
    
     
      gluOrtho2D(0, w, 0, h)
    
  2. Displaying points: The algorithm requires us to display points, the more the better. First, we set the drawing color to red. Second, we define the vertices (I call them points myself) of a triangle. Then we define random indices, which are to be used to choose one of the three triangle vertices. We pick a random point somewhere in the middle, it doesn't really matter where. After that we draw points halfway between the previous point and one of the vertices picked at random. Finally, we "flush" the result:
        glColor3f(1.0, 0, 0)
        vertices = numpy.array([[0, 0], [DIM/2, DIM], [DIM, 0]])
        NPOINTS = 9000
        indices = numpy.random.random_integers(0, 2, NPOINTS)
        point = [175.0, 150.0]
    
        for index in indices:
           glBegin(GL_POINTS)
           point = (point + vertices[index])/2.0
           glVertex2fv(point)
           glEnd()
    
        glFlush()

    The Sierpinski triangle looks like this:

    How to do it...

    The full Sierpinski gasket demo code with all the imports is shown as follows:

    import pygame
    from pygame.locals import *
    import numpy
         
    from OpenGL.GL import *
    from OpenGL.GLU import *
    
    def display_openGL(w, h):
      pygame.display.set_mode((w,h), pygame.OPENGL|pygame.DOUBLEBUF)
    
      glClearColor(0.0, 0.0, 0.0, 1.0)
      glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
    
      
      gluOrtho2D(0, w, 0, h)
    
    
    def main():
        pygame.init()
        pygame.display.set_caption('OpenGL Demo')
        DIM = 400
        display_openGL(DIM, DIM)
        glColor3f(1.0, 0, 0)
        vertices = numpy.array([[0, 0], [DIM/2, DIM], [DIM, 0]])
        NPOINTS = 9000
        indices = numpy.random.random_integers(0, 2, NPOINTS)
        point = [175.0, 150.0]
    
        for index in indices:
           glBegin(GL_POINTS)
           point = (point + vertices[index])/2.0
           glVertex2fv(point)
           glEnd()
    
        glFlush()
        pygame.display.flip()
         
        while True:
            for event in pygame.event.get():
                if event.type == QUIT:
                    return
    
        
    if __name__ == '__main__':
      main()

How it works...

As promised here is a line-by-line explanation of the most important parts of the example:

Function

Description

pygame.display.set_mode((w,h), pygame.OPENGL|pygame.DOUBLEBUF)

This sets the display mode to the required width, height, and OpenGL display.

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)

This clears the buffers using a mask. Here we clear the color buffer and depth buffer bits.

gluOrtho2D(0, w, 0, h)

This defines a 2D orthographic projection matrix with the coordinates of the left, right, top, and bottom clipping planes.

glColor3f(1.0, 0, 0)

This defines the current drawing color using three float values for RGB (0-1 instead of 0-255 that is usual for Pygame). In this case we will be painting in red.

glBegin(GL_POINTS)

This delimits the vertices of primitives or a group of primitives. Here the primitives are points.

glVertex2fv(point)

This renders a point given a vertex.

glEnd()

This closes a section of code started with glBegin.

glFlush()

This forces execution of GL commands.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset