Brief Introduction to OpenGL in Python with PyOpenGL

Introduction

In this tutorial, we're going to learn how to use PyOpenGL library in Python. OpenGL is a graphics library which is supported by multiple platforms including Windows, Linux, and MacOS, and is available for use in multiple other languages as well; however, the scope of this post will be limited to its usage in the Python programming language.

OpenGL, as compared to other similar graphics libraries, is fairly simple. We'll start with setting it up on our system, followed by writing a simple example demonstrating the usage of the library.

Installation

The easiest way to install OpenGL using Python is through the pip package manager. If you have pip installed in your system, run the following command to download and install OpenGL:

$ pip install PyOpenGL PyOpenGL_accelerate

I'd recommend copying the above command to help avoid typos.

Once this command finishes execution, if the installation is successful, you should get the following output at the end:

Successfully installed PyOpenGL-3.1.0 PyOpenGL-accelerate-3.1.0  

If this doesn't work, you can also download it manually. For that, this link, scroll down to the 'downloading and installation' heading, and download all the files over there. After that, navigate to the folder where you downloaded those files, and run the following command in the terminal or command prompt:

$ python setup.py

It is pertinent to mention that you require Visual C++ 14.0 build tools installed on your system in order to work with OpenGL libraries in Python.

Now that we have successfully installed OpenGL on our system, let's get our hands dirty with it.

Coding Exercise

The first thing we need to do to use OpenGL in our code is to import it. To do that, run the following command:

import OpenGL  

Before we proceed, there are a few other libraries that you need to import whenever you intend to use this library in your program. Below is the code for those imports:

import OpenGL.GL  
import OpenGL.GLUT  
import OpenGL.GLU  
print("Imports successful!") # If you see this printed to the console then installation was successful  

Now that we are done with the necessary imports, let's first create a window in which our graphics will be shown. The code for that is given below, along with its explanation in the comments:

def showScreen():  
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # Remove everything from screen (i.e. displays all white)

glutInit() # Initialize a glut instance which will allow us to customize our window  
glutInitDisplayMode(GLUT_RGBA) # Set the display mode to be colored  
glutInitWindowSize(500, 500)   # Set the width and height of your window  
glutInitWindowPosition(0, 0)   # Set the position at which this windows should appear  
wind = glutCreateWindow("OpenGL Coding Practice") # Give your window a title  
glutDisplayFunc(showScreen)  # Tell OpenGL to call the showScreen method continuously  
glutIdleFunc(showScreen)     # Draw any graphics or shapes in the showScreen function at all times  
glutMainLoop()  # Keeps the window created above displaying/running in a loop  

Copy the imports above, as well as this code in a single python (.py) file, and execute it. You should see a white square dimension screen pop up. Now, if we wish to draw any shapes or make any other kind of graphics, we need to do that in our "showScreen" function.

Let's now try to make a square using OpenGL, but before we do we need to understand the coordinate system that OpenGL follows.

The (0,0) point is the bottom left of your window, if you go up from there, you're moving along the y-axis, and if you go right from there, you're moving along the x-axis. So, the top left point of your window would be (0, 500), top right would be (500, 500), bottom right would be (500, 0).

Note: We're talking about the window we created above, which had a dimension of 500 x 500 in our example, and not your computer's full screen.

Now that we've got that out of the way, lets code a square. The explanation to the code can be found in the comments.

from OpenGL.GL import *  
from OpenGL.GLUT import *  
from OpenGL.GLU import *

w, h = 500,500

# ---Section 1---
def square():  
    # We have to declare the points in this sequence: bottom left, bottom right, top right, top left
    glBegin(GL_QUADS) # Begin the sketch
    glVertex2f(100, 100) # Coordinates for the bottom left point
    glVertex2f(200, 100) # Coordinates for the bottom right point
    glVertex2f(200, 200) # Coordinates for the top right point
    glVertex2f(100, 200) # Coordinates for the top left point
    glEnd() # Mark the end of drawing

# This alone isn't enough to draw our square

# ---Section 2---

def showScreen():  
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # Remove everything from screen (i.e. displays all white)
    glLoadIdentity() # Reset all graphic/shape's position
    square() # Draw a square using our function
    glutSwapBuffers()

#---Section 3---

glutInit()  
glutInitDisplayMode(GLUT_RGBA) # Set the display mode to be colored  
glutInitWindowSize(500, 500)   # Set the w and h of your window  
glutInitWindowPosition(0, 0)   # Set the position at which this windows should appear  
wind = glutCreateWindow("OpenGL Coding Practice") # Set a window title  
glutDisplayFunc(showScreen)  
glutIdleFunc(showScreen) # Keeps the window open  
glutMainLoop()  # Keeps the above created window displaying/running in a loop  

Running the code above would draw a square, but that square would not be visible since it's color would be the same as the color of our window, so we need to assign it a different color as well, for that we will make some changes in "Section 2" of the code above i.e. the showScreen function. Add the following line below the glLoadIdentity statement and above the square() statement:

glColor3f(1.0, 0.0, 3.0) # Set the color to pink  

However, our code is still not complete. What it currently does is draw the square once, and then clear the screen again. We don't want that. Actually, we won't even be able to spot the moment when it actually draws the square because it would appear and disappear in a split second. Lets write another function to avoid this.

# Add this function before Section 2 of the code above i.e. the showScreen function
def iterate():  
    glViewport(0, 0, 500,500)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    glOrtho(0.0, 500, 0.0, 500, 0.0, 1.0)
    glMatrixMode (GL_MODELVIEW)
    glLoadIdentity()

Call this iterate function in "Section 2" of the code above. Add it below glLoadIdentity and above the glColor3d statement in the showScreen function.

Let's now compile all this into a single code file so that there are no ambiguities:

from OpenGL.GL import *  
from OpenGL.GLUT import *  
from OpenGL.GLU import *

w,h= 500,500  
def square():  
    glBegin(GL_QUADS)
    glVertex2f(100, 100)
    glVertex2f(200, 100)
    glVertex2f(200, 200)
    glVertex2f(100, 200)
    glEnd()

def iterate():  
    glViewport(0, 0, 500, 500)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    glOrtho(0.0, 500, 0.0, 500, 0.0, 1.0)
    glMatrixMode (GL_MODELVIEW)
    glLoadIdentity()

def showScreen():  
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glLoadIdentity()
    iterate()
    glColor3f(1.0, 0.0, 3.0)
    square()
    glutSwapBuffers()

glutInit()  
glutInitDisplayMode(GLUT_RGBA)  
glutInitWindowSize(500, 500)  
glutInitWindowPosition(0, 0)  
wind = glutCreateWindow("OpenGL Coding Practice")  
glutDisplayFunc(showScreen)  
glutIdleFunc(showScreen)  
glutMainLoop()  

When you run this, a window should appear with a pink colored square box in it.

Output:

Conclusion

In this tutorial, we learned about OpenGL, how to download and install it, followed by using it an a short example program. In this example we also practiced making a basic shape using OpenGL, which gave us an insight into some complex function calls that need to be made whenever we need to draw something using this library. To conclude, OpenGL is very resourceful and gets more and more complex as we dive deeper into it.