I wrote this simple program that displays an image onto a moderngl
context, using pygame
, and my goal is to draw a rectangle on the screen. (This is obviously just a minimal working example, and the real goal is to animate the texture and make more than a rectangle on the screen).
import moderngl
import numpy as np
import pygame
from PIL import Image
class MyPyGame:
def __init__(self):
pygame.init()
self._surface = pygame.display.set_mode((800, 600), pygame.DOUBLEBUF | pygame.OPENGL)
self.context = moderngl.create_context()
image = Image.open("test.jpg").transpose(Image.FLIP_TOP_BOTTOM)
self.texture = self.context.texture(image.size, 3, image.tobytes())
self.texture.use(0)
self.program = self.context.program(
vertex_shader="""
#version 330
in vec2 in_position;
out vec2 uv0;
void main() {
gl_Position = vec4(in_position, 0.0, 1.0);
uv0 = (0.5 * in_position) + vec2(0.5);
}
""",
fragment_shader="""
#version 330
out vec4 fragColor;
uniform sampler2D texture0;
in vec2 uv0;
void main() {
fragColor = texture(texture0, uv0);
}
""")
vertices_quad_2d = np.array([-1.0, 1.0, -1.0, -1.0, 1.0, -1.0,
-1.0, 1.0, 1.0, -1.0, 1.0, 1.0], dtype=np.float32)
vertex_buffer_quad_2d = self.context.buffer(vertices_quad_2d.tobytes())
self.vertex_array = self.context.vertex_array(self.program, [(vertex_buffer_quad_2d, "2f", "in_position")])
def run(self):
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
self.vertex_array.render()
pygame.display.flip()
if __name__ == '__main__':
app = MyPyGame()
app.run()
Some things I tried:
Draw a rectangle as is the "regular" way with
pygame
, that is, add this line in the mainrun
method, either before or after the vertex array rendering (both didn't work):pygame.draw.rect(self._surface, (200, 200, 200), [100, 100, 100, 100])
Instead of flag
pygame.OPENGL
, use flagpygame.OPENGLBLIT
and thenblit
the rectangle (didn't work, more info here)Use the
moderngl
context as a window inside the main display, as suggested here, and thenblit
the rectangle onto the main display. This is not what I am aiming for, I want to able to display texts and shapes onto the context, but still, wanted to at least try this. Didn't work either, the code below (replacing the corresponding code in the__init__
) resulted in an exceptioncannot detect OpenGL context
:pygame.init() self.main_window = pygame.display.set_mode((800, 600)) self.graphics_window = pygame.Surface((700, 600), pygame.DOUBLEBUF | pygame.OPENGL) self.main_window.blit(self.graphics_window, (100, 0)) self.context = moderngl.create_context()
Use "out of the box" window from
moderngl_window
usingpygame
(code here). Again, didn't succeed to draw a rectangle onto the context itself - tried to add the same line from (1) either inside the window code itself, or when I write my own window that inherits from this pygame window.
[Working on: Windows10, python3.6, pygame 1.9.6, moderngl 5.6.1]
How can I create a window that is both displaying graphics and has a layer of costume objects? (text, buttons, etc.)
EDIT: Perhaps a clarification for my motivation is needed: I would like to have one layer of graphics in the background, that in the example above is some manipulation of an input image. Then, in the foreground, I would like to have some costume PyGame objects like geometric shapes, buttons, etc.