Last active
January 11, 2026 16:42
-
-
Save nitori/df2913ffc24e05b65b9004d441912085 to your computer and use it in GitHub Desktop.
simple pygame + moderngl example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import pygame | |
| import moderngl | |
| from pyglm import glm | |
| import numpy as np | |
| VERTEX_SHADER = """ | |
| #version 330 | |
| uniform mat4 mvp; | |
| in vec3 in_pos; | |
| out vec3 pos; | |
| void main() { | |
| gl_Position = mvp * vec4(in_pos, 1.0); | |
| pos = in_pos; | |
| } | |
| """ | |
| FRAGMENT_SHADER = """ | |
| #version 330 | |
| out vec4 fragColor; | |
| in vec3 pos; | |
| void main() { | |
| // make color position dependent | |
| vec3 col = (pos + 1.0) / 2.0; | |
| fragColor = vec4(col, 1.0); | |
| } | |
| """ | |
| # fmt: off | |
| CUBE_VERTICES = np.array([ | |
| [1, 1, -1], | |
| [1, -1, -1], | |
| [1, 1, 1], | |
| [1, -1, 1], | |
| [-1, 1, -1], | |
| [-1, -1, -1], | |
| [-1, 1, 1], | |
| [-1, -1, 1], | |
| ], dtype=np.float32) | |
| CUBE_FACE_INDICES = np.array([ | |
| [4, 2, 0], | |
| [2, 7, 3], | |
| [6, 5, 7], | |
| [1, 7, 5], | |
| [0, 3, 1], | |
| [4, 1, 5], | |
| [4, 6, 2], | |
| [2, 6, 7], | |
| [6, 4, 5], | |
| [1, 3, 7], | |
| [0, 2, 3], | |
| [4, 0, 1], | |
| ], dtype=np.uint8) | |
| # fmt: on | |
| def main(): | |
| screen = pygame.display.set_mode( | |
| (800, 600), pygame.OPENGL | pygame.DOUBLEBUF | pygame.RESIZABLE | |
| ) | |
| clock = pygame.Clock() | |
| # no argument: discovers the context created by pygame. | |
| ctx = moderngl.create_context() | |
| ctx.enable(moderngl.CULL_FACE) | |
| ctx.enable(moderngl.DEPTH_TEST) | |
| prog = ctx.program( | |
| vertex_shader=VERTEX_SHADER, | |
| fragment_shader=FRAGMENT_SHADER, | |
| ) | |
| vertex_buffer = ctx.buffer(CUBE_VERTICES.tobytes()) | |
| index_buffer = ctx.buffer(CUBE_FACE_INDICES.tobytes()) | |
| vao = ctx.vertex_array( | |
| prog, | |
| [(vertex_buffer, "3f", "in_pos")], | |
| index_buffer=index_buffer, | |
| index_element_size=1, | |
| ) | |
| camera_pos = glm.vec3(0, 0, 5) | |
| camera_target = glm.vec3(0, 0, 0) | |
| camera_up = glm.vec3(0, 1, 0) | |
| angle = 0.0 | |
| width, height = screen.size | |
| while True: | |
| for event in pygame.event.get(): | |
| if event.type == pygame.QUIT: | |
| return | |
| if event.type == pygame.WINDOWRESIZED: | |
| width, height = event.x, event.y | |
| delta = clock.tick(60) / 1000 | |
| angle += 50 * delta | |
| ctx.clear(0, 0, 0) | |
| proj = glm.perspective(glm.radians(60), width / height, 0.1, 1000.0) | |
| view = glm.lookAt(camera_pos, camera_target, camera_up) | |
| model = glm.rotate(glm.radians(angle), glm.vec3(1.5, 1, 0.5)) | |
| mvp = proj * view * model | |
| prog["mvp"].write(mvp.to_bytes()) | |
| vao.render(mode=moderngl.TRIANGLES) | |
| pygame.display.flip() | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment