How to Install PyOpenGL on Windows 10

By | September 15, 2023

PyOpenGL is an python module that implements OpenGL functions in python allowing you to write OpenGL applications using Python.

With OpenGL you are able to write applications that use "GPU acceleration". So if you have an Nvidia RTX 3060 gpu on your system, the opengl functions will use it to render the 3D graphics on screen.

So technically you can write a game based on OpenGL, though Python is not a very ideal language for writing games. For game development you should use C++ instead. Moreover using OpenGL based API directly is also not recommended, since you would have to do a lot of rudimentary drawing tasks yourself.

Instead you are better off using a game development library like SDL or a full-fledged framework like Unreal or Unity. Python even has a wrapper module for SDL called PyGame.

It must be kept in mind that OpenGL is just a set of specifications, and various vendors provide implementation of this specifications in the form of an API that can be used in other programming languages like C++.

In this simple and quick tutorial we shall take a look at the required steps to install PyOpenGL on Windows 10 and test it.

Step 1: Install Python

First off, you need to have Python on your system. You can simply download it from:

https://www.python.org/downloads/

Run the installer and it will install the python interpreter on Windows.

Step 2: Install PyOpenGL modules

The next task is to install PyOpenGL package which brings in OpenGL functions in python. However there is a twist. The original method was to install it from the pip packages using the following command:

pip install PyOpenGL PyOpenGL_accelerate

However the above will not working. It will install PyOpenGL packages, but when you try to import the packages, it will fail.

The alternative working method is to download un-official packages from a 3rd party site.

https://www.lfd.uci.edu/~gohlke/pythonlibs/#pyopengl

Be careful to download the .whl package file that matches the Python interpreter version on your system. For example I downloaded:

PyOpenGL-3.1.6-cp310-cp310-win_amd64.whl
PyOpenGL_accelerate-3.1.6-cp310-cp310-win_amd64.whl

as I have Python 3.10 install on my system. the "cp-310" part indicates which version of python interpreter is the package compiled for.
If you download a package for a different Python version, it will fail to install.

Source:
https://stackoverflow.com/questions/65699670/pyopengl-opengl-error-nullfunctionerror-attempt-to-call-an-undefined-functio

Code

The following is a simple python program, that will import the OpenGL modules and print out some basic information about the driver being used.

# PyOpenGL Setup
# Ref: https://stackabuse.com/brief-introduction-to-opengl-in-python-with-pyopengl/

import sys
print('Python version: ' + sys.version + '\n')

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

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

def showScreen():
    return

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

# print OpenGL Driver Information
try:
    # this method can be called only after glutCreateWindow has been called.
    # it works only after a opengl context has been created
    # OpenGL Context: https://www.khronos.org/opengl/wiki/OpenGL_Context

    print("OpenGL Vendor: " + GL.glGetString(GL.GL_VENDOR).decode())
    print("OpenGL Renderer: " + GL.glGetString(GL.GL_RENDERER).decode())
    gl_version_str = GL.glGetString(GL.GL_VERSION)
    gl_version = float(gl_version_str[:3])
    print("OpenGL Renderer Version: " + str(gl_version) + " ( " + gl_version_str.decode() + " )")
    print("OpenGL Shading Language Version: " + GL.glGetString(GL.GL_SHADING_LANGUAGE_VERSION).decode())
    print("OpenGL Total Extensions: " + str(GL.glGetIntegerv(GL.GL_NUM_EXTENSIONS)))
    
    gl_extensions_str = GL.glGetString(GL.GL_EXTENSIONS).decode()

    #print("OpenGL Extensions: " + gl_extensions_str)
    #print("OpenGL ATTRIBUTES:\n",", ".join(d for d in dir(GL) if d.startswith("GL_")))

    vram_total = vram_used = vram_available = 'Unknown'
    
    # https://gamedev.stackexchange.com/questions/3346/how-can-i-tell-how-much-video-card-memory-im-using
    # Only for Nvidia GPUs
    # https://stackoverflow.com/questions/43267640/how-i-can-get-my-total-gpu-memory-using-qts-native-opengl
    if('GL_NVX_gpu_memory_info' in gl_extensions_str):
        
        # Ref: https://github.com/collincebecky/QT-OPENCV-GSTREAMER-CUDA/blob/master/glUtility.h
        # https://registry.khronos.org/OpenGL/extensions/NVX/NVX_gpu_memory_info.txt
        GL_GPU_MEM_INFO_TOTAL_AVAILABLE_MEM_NVX = 0x9048
        GL_GPU_MEM_INFO_CURRENT_AVAILABLE_MEM_NVX = 0x9049
        
        vram_total = GL.glGetIntegerv(GL_GPU_MEM_INFO_TOTAL_AVAILABLE_MEM_NVX)
        vram_available = GL.glGetIntegerv(GL_GPU_MEM_INFO_CURRENT_AVAILABLE_MEM_NVX)
        vram_used = vram_total - vram_available
    
    # For AMD gpus (Integrated GPUs)
    # https://registry.khronos.org/OpenGL/extensions/ATI/ATI_meminfo.txt
    elif ('GL_ATI_meminfo' in gl_extensions_str):
        TEXTURE_FREE_MEMORY_ATI = 0x87FC
        vram_total = GL.glGetIntegerv(TEXTURE_FREE_MEMORY_ATI)
    
    else:
        print('Memory information not available')
    
    print("Total VRAM: " + str( vram_total ) + " KB")
    print("VRAM Used: " + str( vram_used ) + " KB")
    print("Total Available VRAM: " + str( vram_available ) + " KB")

except Exception as e:
    print('GL.glGetString failed:' + str(e))

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

Output

I used the free Visual Studio Code IDE to run the above program. It should output details about the OpenGL driver that is being used for OpenGL rendering.
On my Asus TUF gaming laptop I have both RTX 3060 dGPU and Radeon Vega 8 iGPU.

When Nvidia is configured as the default GPU, the output looks something like this:

OpenGL Imports successful!
OpenGL Vendor: NVIDIA Corporation
OpenGL Renderer: NVIDIA GeForce RTX 3060 Laptop GPU/PCIe/SSE2
OpenGL Renderer Version: 4.6 ( 4.6.0 NVIDIA 512.78 )
OpenGL Shading Language Version: 4.60 NVIDIA
OpenGL Total Extensions: 402
Total VRAM: 6291456 KB
VRAM Used: 292168 KB
Total Available VRAM: 5999288 KB

Note that 4.6 is the version of the OpenGL standard that has been implemented by this driver.
So you can write programs that use OpenGL 4.6 features. With the GL_NVX_gpu_memory_info extension it also reports information about VRAM on the GPU. The above NVidia RTX 3060 has 6GB vram for instance.

However reporting the vram might not be possible for all kinds of gpus like the AMD igpu.

When AMD Radeon is set as the default GPU, the output looks like this:

OpenGL Imports successful!
OpenGL Vendor: ATI Technologies Inc.
OpenGL Renderer: AMD Radeon(TM) Graphics
OpenGL Renderer Version: 4.6 ( 4.6.14756 Compatibility Profile Context 20.40.44.02 27.20.14044.2001 )
OpenGL Shading Language Version: 4.60
OpenGL Total Extensions: 305

There is a difference in the number of extensions supported by the OpenGL drivers from Nvidia vs. AMD.
Nvidia being a more powerful dedicated gpu supports more extensions, whereas the integrated gpu from amd is less powerful with comparatively fewer features.

On systems that do not have any kind of gpu (either dedicated or integrated), the system provides a software based implementation of OpenGL. Software based OpenGL renderer is far slower compared to hardware based ones simply because the software libraries use the CPU which cannot handle rendering as fast as GPUs.

References:

https://www.programcreek.com/python/example/95621/OpenGL.GL.glGetString - The glGetString samples have been taken from this page.
https://stackoverflow.com/questions/10037251/how-to-determine-the-opengl-version-under-windows
https://stackoverflow.com/questions/12184506/why-does-glgetstringgl-version-return-null-zero-instead-of-the-opengl-versio

How OpenGL connects to the GPU

Some of you might be wondering, how exactly does OpenGL talk to the GPU to perform the rendering. This topic has been discussed on Stackoverflow over here and here.

Any OpenGL application initially loads the "opengl32.dll" file which is present on all versions of Windows. This particular library acts as a buffer and it in turn loads an actual ICD (Installable Client Driver) which provides the OpenGL implementation for to the specific GPU like Nvidia RTX 3060.

If you are using an Nvidia RTX 3060 GPU then it will load - nvoglv64.dll
With AMD iGPU the OpenGL driver file is - atig6pxx.dll

The respective driver files talk to the gpu hardware and provide "hardware acceleration" or hardware based execution.

PyOpenGL application -> FreeGLUT dll -> opengl32.dll -> nvoglv64.dll -> the Nvidia GPU (graphics card)

The official wiki also explains this
https://www.khronos.org/opengl/wiki/FAQ#How_Does_It_Work_On_Windows.3F

Other Libraries - GLU and GLUT

OpenGL does not have a standalone SDK or API per se that can be used directly, but there are actually other libraries that wrap around OpenGL functions from "drivers" to provide access to the OpenGL functions that can be used to write applications.

These are called Extension Loading Libraries or OpenGL Loading Library. These libraries basically load "pointers" to OpenGL functions at runtime which the application can call directly.

Extension Loading Library (FreeGLUT) -> Actual OpenGL Driver (nvoglv64.dll)

These individual Loading Libraries provide their own SDK (header and lib files in C++) for developing applications.

PyOpenGL is a wrapper around 2 libraries which are OpenGL Utility Toolkit and OpenGL Utility Library.

To be more specific PyOpenGL is a wrapper around the implementation of GLUT called FreeGLUT.

GLUT provides functionality like drawing windows, registering callbacks for keyboard, mouse etc. Specifications are available here.

The GLU library specifications are available here.

They are listed on the official site: https://www.opengl.org/resources/librarIES

In PyOpenGL function names start with "glut", "glu" and "gl" which indicates which library they come from. Function from GLUT are prefixed with "glut", whereas "glu" indicates GLU. Function names starting with just "gl" indicate the core OpenGL functions

Besides GLUT and GLU there are many other alternative 3rd party wrappers available for OpenGL. Some common ones include:

GLEW - http://glew.sourceforge.net/
GLFW - https://www.glfw.org/

Both the above libraries have Python bindings.

Links and Resources

https://stackabuse.com/brief-introduction-to-opengl-in-python-with-pyopengl/ - A brief introduction to PyOpenGL
https://www.khronos.org/opengl/wiki/
https://open.gl/ - Learn the latest OpenGL version
https://docs.gl/
https://www.opengl.org/Documentation/Documentation.html
https://www.opengl.org/sdk/libs/

About Silver Moon

A Tech Enthusiast, Blogger, Linux Fan and a Software Developer. Writes about Computer hardware, Linux and Open Source software and coding in Python, Php and Javascript. He can be reached at [email protected].

Leave a Reply

Your email address will not be published. Required fields are marked *