Skip to content

Instantly share code, notes, and snippets.

@binarycrusader
Last active December 29, 2023 22:19
Show Gist options
  • Save binarycrusader/1fdc686fb00d6c818caf to your computer and use it in GitHub Desktop.
Save binarycrusader/1fdc686fb00d6c818caf to your computer and use it in GitHub Desktop.
pysdl2 pyopengl "modern" opengl example
#!/usr/bin/python2.7
"""Quick hack of 'modern' OpenGL example using pysdl2 and pyopengl
Based on
pysdl2 OpenGL example
http://www.arcsynthesis.org/gltut/Basics/Tut02%20Vertex%20Attributes.html
http://schi.iteye.com/blog/1969710
"""
import sys
import ctypes
import numpy
from OpenGL import GL, GLU
from OpenGL.GL import shaders
from OpenGL.arrays import vbo
import sdl2
from sdl2 import video
from numpy import array
shaderProgram = None
VAO = None
VBO = None
def initialize():
global shaderProgram
global VAO
global VBO
vertexShader = shaders.compileShader("""
#version 330
layout (location=0) in vec4 position;
layout (location=1) in vec4 colour;
smooth out vec4 theColour;
void main()
{
gl_Position = position;
theColour = colour;
}
""", GL.GL_VERTEX_SHADER)
fragmentShader = shaders.compileShader("""
#version 330
smooth in vec4 theColour;
out vec4 outputColour;
void main()
{
outputColour = theColour;
}
""", GL.GL_FRAGMENT_SHADER)
shaderProgram = shaders.compileProgram(vertexShader, fragmentShader)
vertexData = numpy.array([
# Vertex Positions
0.0, 0.5, 0.0, 1.0,
0.5, -0.366, 0.0, 1.0,
-0.5, -0.366, 0.0, 1.0,
# Vertex Colours
1.0, 0.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0,
], dtype=numpy.float32)
# Core OpenGL requires that at least one OpenGL vertex array be bound
VAO = GL.glGenVertexArrays(1)
GL.glBindVertexArray(VAO)
# Need VBO for triangle vertices and colours
VBO = GL.glGenBuffers(1)
GL.glBindBuffer(GL.GL_ARRAY_BUFFER, VBO)
GL.glBufferData(GL.GL_ARRAY_BUFFER, vertexData.nbytes, vertexData,
GL.GL_STATIC_DRAW)
# enable array and set up data
GL.glEnableVertexAttribArray(0)
GL.glEnableVertexAttribArray(1)
GL.glVertexAttribPointer(0, 4, GL.GL_FLOAT, GL.GL_FALSE, 0,
None)
# the last parameter is a pointer
GL.glVertexAttribPointer(1, 4, GL.GL_FLOAT, GL.GL_FALSE, 0,
ctypes.c_void_p(48))
GL.glBindBuffer(GL.GL_ARRAY_BUFFER, 0)
GL.glBindVertexArray(0)
def render():
global shaderProgram
global VAO
GL.glClearColor(0, 0, 0, 1)
GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)
# active shader program
GL.glUseProgram(shaderProgram)
try:
GL.glBindVertexArray(VAO)
# draw triangle
GL.glDrawArrays(GL.GL_TRIANGLES, 0, 3)
finally:
GL.glBindVertexArray(0)
GL.glUseProgram(0)
def run():
if sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO) != 0:
print(sdl2.SDL_GetError())
return -1
window = sdl2.SDL_CreateWindow(b"OpenGL demo",
sdl2.SDL_WINDOWPOS_UNDEFINED,
sdl2.SDL_WINDOWPOS_UNDEFINED, 800, 600,
sdl2.SDL_WINDOW_OPENGL)
if not window:
print(sdl2.SDL_GetError())
return -1
# Force OpenGL 3.3 'core' context.
# Must set *before* creating GL context!
video.SDL_GL_SetAttribute(video.SDL_GL_CONTEXT_MAJOR_VERSION, 3)
video.SDL_GL_SetAttribute(video.SDL_GL_CONTEXT_MINOR_VERSION, 3)
video.SDL_GL_SetAttribute(video.SDL_GL_CONTEXT_PROFILE_MASK,
video.SDL_GL_CONTEXT_PROFILE_CORE)
context = sdl2.SDL_GL_CreateContext(window)
# Setup GL shaders, data, etc.
initialize()
event = sdl2.SDL_Event()
running = True
while running:
while sdl2.SDL_PollEvent(ctypes.byref(event)) != 0:
if event.type == sdl2.SDL_QUIT:
running = False
render()
sdl2.SDL_GL_SwapWindow(window)
sdl2.SDL_Delay(10)
sdl2.SDL_GL_DeleteContext(context)
sdl2.SDL_DestroyWindow(window)
sdl2.SDL_Quit()
return 0
if __name__ == "__main__":
sys.exit(run())
@CheyneWilson
Copy link

I tried running this on python3.4 / macosx and got the following error: b'Validation Failed: No vertex array object bound.\n'. I moved the compileProgram after the VAO binding and it worked fine.

# Core OpenGL requires that at least one OpenGL vertex array be bound
VAO = GL.glGenVertexArrays(1)
GL.glBindVertexArray(VAO)

shaderProgram = shaders.compileProgram(vertexShader, fragmentShader)

@FloydATC
Copy link

FloydATC commented Jun 3, 2019

Trying to get into python/opengl and using this code as a starting point. Unfortunately, I'm unable to make any progress at all because glLoadIdentity(), glMatrixMode() and all other attempts at matrix manipulation anywhere in the render() function fails with "invalid operation". Can you point me in the right direction please?

@buzmeg
Copy link

buzmeg commented Jun 29, 2019

Thanks for this. I've been killing myself trying to get a modern OpenGL system to work on any of the Python libraries.

@chenz
Copy link

chenz commented Mar 15, 2022

Unfortunately, I'm unable to make any progress at all because glLoadIdentity(), glMatrixMode() and all other attempts at matrix manipulation anywhere in the render() function fails with "invalid operation".

There are no more built-in matrices in "modern" OpenGL. You have to do the math yourself. That is what the shaders are for. E.g. you would compute your matrices on the CPU and then pass them to the vertex shader, which can apply them to the vertices.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment