From 35f218e294dfad3c4b4dbd7fde4a89100e4d2708 Mon Sep 17 00:00:00 2001 From: Einar Forselv Date: Sat, 23 Nov 2024 21:26:27 +0100 Subject: [PATCH] Upgrade remaining examples to use glm --- examples/advanced/animated_sprites.py | 42 ++++--- examples/advanced/boids.py | 90 --------------- examples/advanced/boids2.py | 69 ----------- examples/advanced/navier_stokes.py | 134 +++++++++++++--------- examples/advanced/pygame2.py | 29 +++-- examples/advanced/shadow_mapping.py | 63 +++++----- examples/advanced/shadow_mapping_56.py | 63 +++++----- examples/advanced/voxel_cubes.py | 39 ++++--- examples/ssao.py | 88 +++++++++----- examples/uniform_block.py | 31 ++--- examples/video.py | 34 ++++-- moderngl_window/text/bitmapped/text_2d.py | 19 ++- 12 files changed, 328 insertions(+), 373 deletions(-) delete mode 100644 examples/advanced/boids.py delete mode 100644 examples/advanced/boids2.py diff --git a/examples/advanced/animated_sprites.py b/examples/advanced/animated_sprites.py index fa93dd32..040d3eec 100644 --- a/examples/advanced/animated_sprites.py +++ b/examples/advanced/animated_sprites.py @@ -11,7 +11,7 @@ class Test(mglw.WindowConfig): title = "Animated Sprite" - resource_dir = (Path(__file__) / '../../resources').resolve() + resource_dir = (Path(__file__) / "../../resources").resolve() aspect_ratio = 320 / 256 window_size = 320 * 3, 256 * 3 @@ -19,10 +19,14 @@ def __init__(self, **kwargs): super().__init__(**kwargs) self.buffer_size = 320, 256 # Textures - self.background_texture = self.load_texture_array('textures/animated_sprites/giphy.gif') + self.background_texture = self.load_texture_array( + "textures/animated_sprites/giphy.gif" + ) self.background_texture.repeat_x = False self.background_texture.repeat_y = False - self.caveman_texture = self.load_texture_array('textures/animated_sprites/player_2.gif', layers=35) + self.caveman_texture = self.load_texture_array( + "textures/animated_sprites/player_2.gif", layers=35 + ) self.caveman_texture.repeat_x = False self.caveman_texture.repeat_y = False self.caveman_texture.filter = moderngl.NEAREST, moderngl.NEAREST @@ -33,24 +37,36 @@ def __init__(self, **kwargs): self.quad_fs = geometry.quad_fs() # Programs - self.sprite_program = self.load_program('programs/animated_sprites/sprite_array.glsl') - self.texture_program = self.load_program('programs/texture.glsl') + self.sprite_program = self.load_program( + "programs/animated_sprites/sprite_array.glsl" + ) + self.texture_program = self.load_program("programs/texture.glsl") # Offscreen buffer self.offscreen_texture = self.ctx.texture(self.buffer_size, 4) self.offscreen_texture.filter = moderngl.NEAREST, moderngl.NEAREST - self.offscreen = self.ctx.framebuffer(color_attachments=[self.offscreen_texture]) + self.offscreen = self.ctx.framebuffer( + color_attachments=[self.offscreen_texture] + ) - self.projection = glm.orthographic(0, 320, 0, 256, -1.0, 1.0) - self.sprite_program['projection'].write(self.projection) + self.projection = glm.ortho(0, 320, 0, 256, -1.0, 1.0) + self.sprite_program["projection"].write(self.projection) def render(self, time, frame_time): # Render sprite of offscreen self.offscreen.use() self.ctx.clear(0.5, 0.5, 0.5, 0.0) - self.render_sprite(self.background_texture, frame=int(time * 15) % self.background_texture.layers) - self.render_sprite(self.caveman_texture, frame=int(time * 15) % self.caveman_texture.layers, blend=True, position=(260, 20)) + self.render_sprite( + self.background_texture, + frame=int(time * 15) % self.background_texture.layers, + ) + self.render_sprite( + self.caveman_texture, + frame=int(time * 15) % self.caveman_texture.layers, + blend=True, + position=(260, 20), + ) # Display offscreen self.ctx.screen.use() @@ -65,14 +81,14 @@ def render_sprite(self, texture, blend=False, frame=0, position=(0, 0)): self.ctx.enable(moderngl.BLEND) texture.use(location=0) - self.sprite_program['layer_id'] = frame - self.sprite_program['position'] = position + self.sprite_program["layer_id"] = frame + self.sprite_program["position"] = position self.sprite_geometry.render(self.sprite_program) if blend: self.ctx.disable(moderngl.BLEND) -if __name__ == '__main__': +if __name__ == "__main__": mglw.run_window_config(Test) # Test.run() diff --git a/examples/advanced/boids.py b/examples/advanced/boids.py deleted file mode 100644 index 81ce77e9..00000000 --- a/examples/advanced/boids.py +++ /dev/null @@ -1,90 +0,0 @@ -from pathlib import Path -import random -import numpy -import glm - -import moderngl -import moderngl_window -from moderngl_window.opengl.vao import VAO - - -class Boids(moderngl_window.WindowConfig): - """ - An attempt to make something boid-list with GL3.3. - Not currently working as intended, but still creates - and interesting result. - - For this to properly work we need to split the calculations - into several passes. - - We are doing this the O(n^2) way with the gpu using transform feedback. - To make the data avaialble to the vertex shader (looping through it) - we copy the vertex buffer every frame to a texture. - - A better way in the future is to use compute shader. - """ - title = "Boids" - resource_dir = (Path(__file__) / '../../resources').absolute() - aspect_ratio = 3440 / 1440 - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - MAX_TEX_WIDTH = 8192 - N = MAX_TEX_WIDTH * 1 - - def gen_initial_data(n, x_area=2.0, y_area=2.0): - for n in range(n): - # position - yield (random.random() - 0.5) * x_area - yield (random.random() - 0.5) * y_area - # Velocity - yield (random.random() - 0.5) - yield (random.random() - 0.5) - - # Create geometry data - gen = gen_initial_data(N, x_area=self.aspect_ratio * 2 * 0.9, y_area=2.0 * 0.95) - data = numpy.fromiter(gen, count=N * 4, dtype='f4') - self.boids_buffer_1 = self.ctx.buffer(data.tobytes()) - self.boids_buffer_2 = self.ctx.buffer(data=self.boids_buffer_1.read()) - - self.boids_vao_1 = VAO(name='boids_1', mode=moderngl.POINTS) - self.boids_vao_1.buffer(self.boids_buffer_1, '2f 2f', ['in_position', 'in_velocity']) - - self.boids_vao_2 = VAO(name='boids_2', mode=moderngl.POINTS) - self.boids_vao_2.buffer(self.boids_buffer_2, '2f 2f', ['in_position', 'in_velocity']) - - self.boids_texture = self.ctx.texture((MAX_TEX_WIDTH, N * 2 // MAX_TEX_WIDTH), components=2, dtype='f4') - - # Programs - self.boids_render_program = self.load_program('programs/boids/boids_render.glsl') - self.boids_transform_program = self.load_program('programs/boids/boids_transform.glsl') - - # Prepare for rendering - self.m_proj = glm.orthographic( - -self.aspect_ratio, self.aspect_ratio, - -1.0, 1.0, - -1.0, 1.0, - ) - self.boids_render_program['m_proj'].write(self.m_proj.tobytes()) - self.boids_transform_program['data'].value = 0 - self.boids_transform_program['num_boids'].value = N - self.boids_transform_program['tex_width'].value = MAX_TEX_WIDTH - - def render(self, time, frame_time): - - self.boids_texture.use(location=0) - self.boids_transform_program['timedelta'].value = frame_time # max(frame_time, 1.0 / 60.0) - self.boids_vao_1.transform(self.boids_transform_program, self.boids_buffer_2) - self.boids_vao_2.render(self.boids_render_program) - - # Swap around .. - self.boids_vao_1, self.boids_vao_2 = self.boids_vao_2, self.boids_vao_1 - self.boids_buffer_1, self.boids_buffer_2 = self.boids_buffer_2, self.boids_buffer_1 - - # Write vertex data into texture so we can interate it in shader - self.boids_texture.write(self.boids_buffer_1.read()) - - -if __name__ == '__main__': - moderngl_window.run_window_config(Boids) diff --git a/examples/advanced/boids2.py b/examples/advanced/boids2.py deleted file mode 100644 index 35940a1a..00000000 --- a/examples/advanced/boids2.py +++ /dev/null @@ -1,69 +0,0 @@ -from pathlib import Path -import numpy as np -import random - -import moderngl -import moderngl_window -from moderngl_window.opengl.vao import VAO -from moderngl_window import geometry - - -class Boids2(moderngl_window.WindowConfig): - """Minimal WindowConfig example""" - gl_version = (3, 3) - window_size = 256, 256 - aspect_ratio = 1.0 - title = "Basic Window Config" - resource_dir = (Path(__file__) / '../../resources').absolute() - - def __init__(self, **kwargs): - super().__init__(**kwargs) - # Offscreen buffers - self.texture_1 = self.ctx.texture(self.wnd.buffer_size, 4, dtype='f4') - self.texture_2 = self.ctx.texture(self.wnd.buffer_size, 4, dtype='f4') - self.fbo_1 = self.ctx.framebuffer(color_attachments=[self.texture_1]) - self.fbo_2 = self.ctx.framebuffer(color_attachments=[self.texture_1]) - - # VAOs - self.quad_fs = geometry.quad_fs() - - N = 1000 - def gen_boids(n): - for i in range(n): - yield random.uniform(-1, 1) - yield random.uniform(-1, 1) - yield random.uniform(-1, 1) - yield random.uniform(-1, 1) - - data = np.fromiter(gen_boids(N), dtype='f4', count=N * 4) - self.boids_buffer_1 = self.ctx.buffer(data=data) - self.boids_buffer_2 = self.ctx.buffer(reserve=data.nbytes) - - self.boids_vao_1 = VAO(name='boids_1') - self.boids_vao_1.buffer(self.boids_buffer_1, '2f 2f', ['in_position', 'in_velocity']) - - self.boids_vao_2 = VAO(name='boids_2') - self.boids_vao_2.buffer(self.boids_buffer_2, '2f 2f', ['in_position', 'in_velocity']) - - # Programs - self.tex_prog = self.load_program('programs/texture.glsl') - self.tex_prog['texture0'].value = 0 - self.boid_points = self.load_program('programs/boids2/boid_points.glsl') - # self.boid_locality = self.load_program('programs/boids2/boids_locality_info.glsl') - - def render(self, time, frametime): - self.fbo_1.use() - # Render initial data to framebuffer - self.boids_vao_1.render(self.boid_points, mode=moderngl.POINTS) - - # debug render fbo - self.wnd.fbo.use() - self.texture_1.use(location=0) - self.quad_fs.render(self.tex_prog) - - # Gather locality info - # .. - - -if __name__ == '__main__': - moderngl_window.run_window_config(Boids2) diff --git a/examples/advanced/navier_stokes.py b/examples/advanced/navier_stokes.py index 31c30211..5a5aad96 100644 --- a/examples/advanced/navier_stokes.py +++ b/examples/advanced/navier_stokes.py @@ -5,6 +5,7 @@ * Left mouse button (including drag) pokes the surface * Right mouse button places walls """ + import random from pathlib import Path import numpy as np @@ -13,15 +14,15 @@ import moderngl_window from moderngl_window import geometry -external_flow = .35 -viscosity = .018 # Is it odd that negative viscosity still works? +external_flow = 0.35 +viscosity = 0.018 # Is it odd that negative viscosity still works? rho = 1.06 # Density damping = 0.999 class NavierStokes2D(moderngl_window.WindowConfig): title = "Navier Stokes 2D" - resource_dir = (Path(__file__) / '../../resources').absolute() + resource_dir = (Path(__file__) / "../../resources").absolute() # window_size = 3440, 1440 # window_size = 512, 512 aspect_ratio = None # Aspect ratio should change with window size @@ -31,10 +32,13 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # various vars - self.m_proj = glm.orthographic( - 0, self.wnd.buffer_width, - 0, self.wnd.buffer_height, - -1, 1, + self.m_proj = glm.ortho( + 0, + self.wnd.buffer_width, + 0, + self.wnd.buffer_height, + -1, + 1, ) size = self.wnd.buffer_size @@ -45,47 +49,57 @@ def __init__(self, *args, **kwargs): self.wall_geometry = geometry.quad_2d(size=(sprite_size, sprite_size)) # Framebuffers - self.momentum_texture_1 = self.ctx.texture(size, 1, dtype='f4') + self.momentum_texture_1 = self.ctx.texture(size, 1, dtype="f4") self.momentum_texture_1.repeat_x = True self.momentum_texture_1.repeat_y = True - self.momentum_texture_2 = self.ctx.texture(size, 1, dtype='f4') + self.momentum_texture_2 = self.ctx.texture(size, 1, dtype="f4") self.momentum_texture_2.repeat_x = True self.momentum_texture_2.repeat_y = True - self.pressure_texture_1 = self.ctx.texture(size, 1, dtype='f4') - self.pressure_texture_2 = self.ctx.texture(size, 1, dtype='f4') - self.walls_texture = self.ctx.texture(size, 1, dtype='f4') - self.difference_texture = self.ctx.texture(size, 1, dtype='f4') - - self.momentum_fbo_1 = self.ctx.framebuffer(color_attachments=[self.momentum_texture_1]) - self.momentum_fbo_2 = self.ctx.framebuffer(color_attachments=[self.momentum_texture_2]) - self.pressure_fbo_1 = self.ctx.framebuffer(color_attachments=[self.pressure_texture_1]) - self.pressure_fbo_2 = self.ctx.framebuffer(color_attachments=[self.pressure_texture_2]) + self.pressure_texture_1 = self.ctx.texture(size, 1, dtype="f4") + self.pressure_texture_2 = self.ctx.texture(size, 1, dtype="f4") + self.walls_texture = self.ctx.texture(size, 1, dtype="f4") + self.difference_texture = self.ctx.texture(size, 1, dtype="f4") + + self.momentum_fbo_1 = self.ctx.framebuffer( + color_attachments=[self.momentum_texture_1] + ) + self.momentum_fbo_2 = self.ctx.framebuffer( + color_attachments=[self.momentum_texture_2] + ) + self.pressure_fbo_1 = self.ctx.framebuffer( + color_attachments=[self.pressure_texture_1] + ) + self.pressure_fbo_2 = self.ctx.framebuffer( + color_attachments=[self.pressure_texture_2] + ) self.walls_fbo = self.ctx.framebuffer(color_attachments=[self.walls_texture]) - self.difference_fbo = self.ctx.framebuffer(color_attachments=[self.difference_texture]) + self.difference_fbo = self.ctx.framebuffer( + color_attachments=[self.difference_texture] + ) # programs - self.texture_prog = self.load_program('programs/navier-stokes/texture.glsl') - self.drop_prog = self.load_program('programs/navier-stokes/drop.glsl') - self.drop_prog['m_proj'].write(self.m_proj.tobytes()) - self.combine_prog = self.load_program('programs/navier-stokes/combine.glsl') - self.combine_prog['pressure_texture'].value = 0 - self.combine_prog['wall_texture'].value = 1 - self.momentum_prog = self.load_program('programs/navier-stokes/momentum.glsl') - self.momentum_prog['rho'].value = rho - self.momentum_prog['damping'].value = damping - self.momentum_prog['external_flow'].value = external_flow - self.momentum_prog['momentum_texture'].value = 0 - self.momentum_prog['pressure_texture'].value = 1 - self.momentum_prog['walls_texture'].value = 3 - self.flow_prog = self.load_program('programs/navier-stokes/flow.glsl') - self.flow_prog['external_flow'].value = external_flow - self.poisson_prog = self.load_program('programs/navier-stokes/poisson.glsl') - self.pressure_prog = self.load_program('programs/navier-stokes/pressure.glsl') - self.pressure_prog['rho'].value = rho - self.pressure_prog['damping'].value = damping - self.pressure_prog['pressure_texture'].value = 0 - self.pressure_prog['difference_texture'].value = 1 - self.pressure_prog['walls_texture'].value = 3 + self.texture_prog = self.load_program("programs/navier-stokes/texture.glsl") + self.drop_prog = self.load_program("programs/navier-stokes/drop.glsl") + self.drop_prog["m_proj"].write(self.m_proj) + self.combine_prog = self.load_program("programs/navier-stokes/combine.glsl") + self.combine_prog["pressure_texture"].value = 0 + self.combine_prog["wall_texture"].value = 1 + self.momentum_prog = self.load_program("programs/navier-stokes/momentum.glsl") + self.momentum_prog["rho"].value = rho + self.momentum_prog["damping"].value = damping + self.momentum_prog["external_flow"].value = external_flow + self.momentum_prog["momentum_texture"].value = 0 + self.momentum_prog["pressure_texture"].value = 1 + self.momentum_prog["walls_texture"].value = 3 + self.flow_prog = self.load_program("programs/navier-stokes/flow.glsl") + self.flow_prog["external_flow"].value = external_flow + self.poisson_prog = self.load_program("programs/navier-stokes/poisson.glsl") + self.pressure_prog = self.load_program("programs/navier-stokes/pressure.glsl") + self.pressure_prog["rho"].value = rho + self.pressure_prog["damping"].value = damping + self.pressure_prog["pressure_texture"].value = 0 + self.pressure_prog["difference_texture"].value = 1 + self.pressure_prog["walls_texture"].value = 3 self.reset() @@ -99,25 +113,25 @@ def drop(self, x, y): for i in range(10): pos = ( x + int((random.random() - 0.5) * rng), - self.wnd.buffer_size[1] - y + int((random.random() - 0.5) * rng) + self.wnd.buffer_size[1] - y + int((random.random() - 0.5) * rng), ) # Render drop into pressure texture self.pressure_fbo_2.use() - self.drop_prog['pos'].value = pos - self.drop_prog['force'].value = random.random() * 2.0 - self.drop_prog['write_value'].value = 1.0 + self.drop_prog["pos"].value = pos + self.drop_prog["force"].value = random.random() * 2.0 + self.drop_prog["write_value"].value = 1.0 # self.drop.use() self.drop_geometry.render(self.drop_prog) self.momentum_fbo_2.use() - self.drop_prog['write_value'].value = 0.0 + self.drop_prog["write_value"].value = 0.0 self.drop_geometry.render(self.drop_prog) def wall(self, x, y): pos = x, self.wnd.buffer_height - y self.walls_fbo.use() - self.drop_prog['pos'].value = pos - self.drop_prog['force'].value = 1.0 - self.drop_prog['write_value'].value = 1.0 + self.drop_prog["pos"].value = pos + self.drop_prog["force"].value = 1.0 + self.drop_prog["write_value"].value = 1.0 self.drop_geometry.render(self.drop_prog) def render(self, time, frame_time): @@ -156,12 +170,24 @@ def render(self, time, frame_time): self.pressure_swap() def momentum_swap(self): - self.momentum_texture_1, self.momentum_texture_2 = self.momentum_texture_2, self.momentum_texture_1 - self.momentum_fbo_1, self.momentum_fbo_2 = self.momentum_fbo_2, self.momentum_fbo_1 + self.momentum_texture_1, self.momentum_texture_2 = ( + self.momentum_texture_2, + self.momentum_texture_1, + ) + self.momentum_fbo_1, self.momentum_fbo_2 = ( + self.momentum_fbo_2, + self.momentum_fbo_1, + ) def pressure_swap(self): - self.pressure_texture_1, self.pressure_texture_2 = self.pressure_texture_2, self.pressure_texture_1 - self.pressure_fbo_1, self.pressure_fbo_2 = self.pressure_fbo_2, self.pressure_fbo_1 + self.pressure_texture_1, self.pressure_texture_2 = ( + self.pressure_texture_2, + self.pressure_texture_1, + ) + self.pressure_fbo_1, self.pressure_fbo_2 = ( + self.pressure_fbo_2, + self.pressure_fbo_1, + ) def mouse_press_event(self, x, y, button): if button == self.wnd.mouse.left: @@ -183,5 +209,5 @@ def key_event(self, key, action, modifiers): self.reset() -if __name__ == '__main__': +if __name__ == "__main__": moderngl_window.run_window_config(NavierStokes2D) diff --git a/examples/advanced/pygame2.py b/examples/advanced/pygame2.py index 3ae7b016..d1092742 100644 --- a/examples/advanced/pygame2.py +++ b/examples/advanced/pygame2.py @@ -2,6 +2,7 @@ Based on BlubberQuark's blog: https://blubberquark.tumblr.com/post/185013752945/using-moderngl-for-post-processing-shaders-with """ + import math from pathlib import Path import pygame @@ -20,15 +21,16 @@ class Pygame(moderngl_window.WindowConfig): Example using pygame with moderngl. Needs to run with ``--window pygame2`` option. """ + title = "Pygame" window_size = 1280, 720 - resource_dir = (Path(__file__) / '../../resources').absolute() + resource_dir = (Path(__file__) / "../../resources").absolute() def __init__(self, **kwargs): super().__init__(**kwargs) - if self.wnd.name != 'pygame2': - raise RuntimeError('This example only works with --window pygame2 option') + if self.wnd.name != "pygame2": + raise RuntimeError("This example only works with --window pygame2 option") self.pg_res = (160, 160) # Create a 24bit (rgba) offscreen surface pygame can render to @@ -40,9 +42,11 @@ def __init__(self, **kwargs): # Simple geometry and shader to render self.cube = geometry.cube(size=(2.0, 2.0, 2.0)) - self.texture_prog = self.load_program('programs/cube_simple_texture.glsl') - self.texture_prog['m_proj'].write(glm.perspective(glm.radians(60), self.wnd.aspect_ratio, 1, 100)) - self.texture_prog['m_model'].write(glm.mat4()) + self.texture_prog = self.load_program("programs/cube_simple_texture.glsl") + self.texture_prog["m_proj"].write( + glm.perspective(glm.radians(60), self.wnd.aspect_ratio, 1, 100) + ) + self.texture_prog["m_model"].write(glm.mat4()) def render(self, time, frametime): # time = self.wnd.frames / 30 @@ -52,9 +56,9 @@ def render(self, time, frametime): rotate = glm.mat4(glm.quat(glm.vec3(time, time * 1.2, time * 1.3))) translate = glm.translate(glm.vec3(0, 0, -3.5)) - camera = rotate * translate + camera = translate * rotate - self.texture_prog['m_camera'].write(camera) + self.texture_prog["m_camera"].write(camera) self.pg_texture.use() self.cube.render(self.texture_prog) @@ -71,15 +75,16 @@ def render_pygame(self, time): ((i * 50) % 255, (i * 100) % 255, (i * 20) % 255), ( math.sin(time + time_offset) * 55 + self.pg_res[0] // 2, - math.cos(time + time_offset) * 55 + self.pg_res[1] // 2), + math.cos(time + time_offset) * 55 + self.pg_res[1] // 2, + ), math.sin(time) * 4 + 15, ) # Get the buffer view of the Surface's pixels # and write this data into the texture - texture_data = self.pg_screen.get_view('1') + texture_data = self.pg_screen.get_view("1") self.pg_texture.write(texture_data) -if __name__ == '__main__': - moderngl_window.run_window_config(Pygame, args=('--window', 'pygame2')) +if __name__ == "__main__": + moderngl_window.run_window_config(Pygame, args=("--window", "pygame2")) diff --git a/examples/advanced/shadow_mapping.py b/examples/advanced/shadow_mapping.py index 3bebd401..b062d50d 100644 --- a/examples/advanced/shadow_mapping.py +++ b/examples/advanced/shadow_mapping.py @@ -2,6 +2,7 @@ Shadow mapping example from: https://www.opengl-tutorial.org/intermediate-tutorials/tutorial-16-shadow-mapping/ """ + import math from pathlib import Path import glm @@ -15,7 +16,7 @@ class ShadowMapping(CameraWindow): title = "Shadow Mapping" - resource_dir = (Path(__file__) / '../../resources').resolve() + resource_dir = (Path(__file__) / "../../resources").resolve() def __init__(self, **kwargs): super().__init__(**kwargs) @@ -25,7 +26,7 @@ def __init__(self, **kwargs): # Offscreen buffer offscreen_size = 1024, 1024 self.offscreen_depth = self.ctx.depth_texture(offscreen_size) - self.offscreen_depth.compare_func = '' + self.offscreen_depth.compare_func = "" self.offscreen_depth.repeat_x = False self.offscreen_depth.repeat_y = False self.offscreen_color = self.ctx.texture(offscreen_size, 4) @@ -46,15 +47,21 @@ def __init__(self, **kwargs): self.offscreen_quad2 = geometry.quad_2d(size=(0.5, 0.5), pos=(0.25, 0.75)) # Programs - self.raw_depth_prog = self.load_program('programs/shadow_mapping/raw_depth.glsl') - self.basic_light = self.load_program('programs/shadow_mapping/directional_light.glsl') - self.basic_light['shadowMap'].value = 0 - self.basic_light['color'].value = 1.0, 1.0, 1.0, 1.0 - self.shadowmap_program = self.load_program('programs/shadow_mapping/shadowmap.glsl') - self.texture_prog = self.load_program('programs/texture.glsl') - self.texture_prog['texture0'].value = 0 - self.sun_prog = self.load_program('programs/cube_simple.glsl') - self.sun_prog['color'].value = 1, 1, 0, 1 + self.raw_depth_prog = self.load_program( + "programs/shadow_mapping/raw_depth.glsl" + ) + self.basic_light = self.load_program( + "programs/shadow_mapping/directional_light.glsl" + ) + self.basic_light["shadowMap"].value = 0 + self.basic_light["color"].value = 1.0, 1.0, 1.0, 1.0 + self.shadowmap_program = self.load_program( + "programs/shadow_mapping/shadowmap.glsl" + ) + self.texture_prog = self.load_program("programs/texture.glsl") + self.texture_prog["texture0"].value = 0 + self.sun_prog = self.load_program("programs/cube_simple.glsl") + self.sun_prog["color"].value = 1, 1, 0, 1 self.lightpos = 0, 0, 0 def render(self, time, frametime): @@ -66,10 +73,10 @@ def render(self, time, frametime): self.offscreen.clear() self.offscreen.use() - depth_projection = glm.orthographic(-20, 20, -20, 20, -20, 40) + depth_projection = glm.ortho(-20, 20, -20, 20, -20, 40) depth_view = glm.lookAt(self.lightpos, (0, 0, 0), (0, 1, 0)) depth_mvp = depth_projection * depth_view - self.shadowmap_program['mvp'].write(depth_mvp) + self.shadowmap_program["mvp"].write(depth_mvp) self.floor.render(self.shadowmap_program) self.wall.render(self.shadowmap_program) @@ -77,26 +84,30 @@ def render(self, time, frametime): # --- PASS 2: Render scene to screen self.wnd.use() - self.basic_light['m_proj'].write(self.camera.projection.matrix) - self.basic_light['m_camera'].write(self.camera.matrix) - self.basic_light['m_model'].write(glm.translate(glm.vec3(scene_pos))) + self.basic_light["m_proj"].write(self.camera.projection.matrix) + self.basic_light["m_camera"].write(self.camera.matrix) + self.basic_light["m_model"].write(glm.translate(glm.vec3(scene_pos))) bias_matrix = glm.mat4( - [[0.5, 0.0, 0.0, 0.0], - [0.0, 0.5, 0.0, 0.0], - [0.0, 0.0, 0.5, 0.0], - [0.5, 0.5, 0.5, 1.0]], + [ + [0.5, 0.0, 0.0, 0.0], + [0.0, 0.5, 0.0, 0.0], + [0.0, 0.0, 0.5, 0.0], + [0.5, 0.5, 0.5, 1.0], + ], ) - self.basic_light['m_shadow_bias'].write(depth_mvp * bias_matrix) - self.basic_light['lightDir'].write(self.lightpos) + self.basic_light["m_shadow_bias"].write(bias_matrix * depth_mvp) + self.basic_light["lightDir"].write(self.lightpos) self.offscreen_depth.use(location=0) self.floor.render(self.basic_light) self.wall.render(self.basic_light) self.sphere.render(self.basic_light) # Render the sun position - self.sun_prog['m_proj'].write(self.camera.projection.matrix) - self.sun_prog['m_camera'].write(self.camera.matrix) - self.sun_prog['m_model'].write(glm.translate(glm.vec3(self.lightpos + scene_pos))) + self.sun_prog["m_proj"].write(self.camera.projection.matrix) + self.sun_prog["m_camera"].write(self.camera.matrix) + self.sun_prog["m_model"].write( + glm.translate(glm.vec3(self.lightpos + scene_pos)) + ) self.sun.render(self.sun_prog) # --- PASS 3: Debug --- @@ -107,5 +118,5 @@ def render(self, time, frametime): # self.offscreen_quad2.render(self.texture_prog) -if __name__ == '__main__': +if __name__ == "__main__": moderngl_window.run_window_config(ShadowMapping) diff --git a/examples/advanced/shadow_mapping_56.py b/examples/advanced/shadow_mapping_56.py index ee294d71..5979bde2 100644 --- a/examples/advanced/shadow_mapping_56.py +++ b/examples/advanced/shadow_mapping_56.py @@ -2,6 +2,7 @@ Shadow mapping example from: https://www.opengl-tutorial.org/intermediate-tutorials/tutorial-16-shadow-mapping/ """ + import math from pathlib import Path import glm @@ -15,7 +16,7 @@ class ShadowMapping(CameraWindow): title = "Shadow Mapping" - resource_dir = (Path(__file__) / '../../resources').resolve() + resource_dir = (Path(__file__) / "../../resources").resolve() def __init__(self, **kwargs): super().__init__(**kwargs) @@ -25,7 +26,7 @@ def __init__(self, **kwargs): # Offscreen buffer offscreen_size = 1024, 1024 self.offscreen_depth = self.ctx.depth_texture(offscreen_size) - self.offscreen_depth.compare_func = '' + self.offscreen_depth.compare_func = "" self.offscreen_depth.repeat_x = False self.offscreen_depth.repeat_y = False # Less ugly by default with linear. May need to be NEAREST for some techniques @@ -46,15 +47,21 @@ def __init__(self, **kwargs): self.offscreen_quad2 = geometry.quad_2d(size=(0.5, 0.5), pos=(0.25, 0.75)) # Programs - self.raw_depth_prog = self.load_program('programs/shadow_mapping/raw_depth.glsl') - self.basic_light = self.load_program('programs/shadow_mapping/directional_light.glsl') - self.basic_light['shadowMap'].value = 0 - self.basic_light['color'].value = 1.0, 1.0, 1.0, 1.0 - self.shadowmap_program = self.load_program('programs/shadow_mapping/shadowmap.glsl') - self.texture_prog = self.load_program('programs/texture.glsl') - self.texture_prog['texture0'].value = 0 - self.sun_prog = self.load_program('programs/cube_simple.glsl') - self.sun_prog['color'].value = 1, 1, 0, 1 + self.raw_depth_prog = self.load_program( + "programs/shadow_mapping/raw_depth.glsl" + ) + self.basic_light = self.load_program( + "programs/shadow_mapping/directional_light.glsl" + ) + self.basic_light["shadowMap"].value = 0 + self.basic_light["color"].value = 1.0, 1.0, 1.0, 1.0 + self.shadowmap_program = self.load_program( + "programs/shadow_mapping/shadowmap.glsl" + ) + self.texture_prog = self.load_program("programs/texture.glsl") + self.texture_prog["texture0"].value = 0 + self.sun_prog = self.load_program("programs/cube_simple.glsl") + self.sun_prog["color"].value = 1, 1, 0, 1 self.lightpos = 0, 0, 0 def render(self, time, frametime): @@ -66,10 +73,10 @@ def render(self, time, frametime): self.offscreen.clear() self.offscreen.use() - depth_projection = glm.orthographic(-20, 20, -20, 20, -20, 40) + depth_projection = glm.ortho(-20, 20, -20, 20, -20, 40) depth_view = glm.lookAt(self.lightpos, (0, 0, 0), (0, 1, 0)) depth_mvp = depth_projection * depth_view - self.shadowmap_program['mvp'].write(depth_mvp) + self.shadowmap_program["mvp"].write(depth_mvp) self.floor.render(self.shadowmap_program) self.wall.render(self.shadowmap_program) @@ -77,26 +84,30 @@ def render(self, time, frametime): # --- PASS 2: Render scene to screen self.wnd.use() - self.basic_light['m_proj'].write(self.camera.projection.matrix) - self.basic_light['m_camera'].write(self.camera.matrix) - self.basic_light['m_model'].write(glm.translate(glm.vec3(scene_pos))) + self.basic_light["m_proj"].write(self.camera.projection.matrix) + self.basic_light["m_camera"].write(self.camera.matrix) + self.basic_light["m_model"].write(glm.translate(glm.vec3(scene_pos))) bias_matrix = glm.mat4( - [[0.5, 0.0, 0.0, 0.0], - [0.0, 0.5, 0.0, 0.0], - [0.0, 0.0, 0.5, 0.0], - [0.5, 0.5, 0.5, 1.0]], + [ + [0.5, 0.0, 0.0, 0.0], + [0.0, 0.5, 0.0, 0.0], + [0.0, 0.0, 0.5, 0.0], + [0.5, 0.5, 0.5, 1.0], + ], ) - self.basic_light['m_shadow_bias'].write(depth_mvp * bias_matrix) - self.basic_light['lightDir'].write(self.lightpos) + self.basic_light["m_shadow_bias"].write(bias_matrix * depth_mvp) + self.basic_light["lightDir"].write(self.lightpos) self.offscreen_depth.use(location=0) self.floor.render(self.basic_light) self.wall.render(self.basic_light) self.sphere.render(self.basic_light) # Render the sun position - self.sun_prog['m_proj'].write(self.camera.projection.matrix) - self.sun_prog['m_camera'].write(self.camera.matrix) - self.sun_prog['m_model'].write(glm.translate(glm.vec3(self.lightpos + scene_pos))) + self.sun_prog["m_proj"].write(self.camera.projection.matrix) + self.sun_prog["m_camera"].write(self.camera.matrix) + self.sun_prog["m_model"].write( + glm.translate(glm.vec3(self.lightpos + scene_pos)) + ) self.sun.render(self.sun_prog) # --- PASS 3: Debug --- @@ -107,5 +118,5 @@ def render(self, time, frametime): # self.offscreen_quad2.render(self.texture_prog) -if __name__ == '__main__': +if __name__ == "__main__": moderngl_window.run_window_config(ShadowMapping) diff --git a/examples/advanced/voxel_cubes.py b/examples/advanced/voxel_cubes.py index e12a2526..a61576dc 100644 --- a/examples/advanced/voxel_cubes.py +++ b/examples/advanced/voxel_cubes.py @@ -14,12 +14,12 @@ * Partial texture updates from client * We can reduce a voxel volume dramatically by just inspecting neighbors """ + from pathlib import Path from typing import Tuple from array import array import moderngl -from moderngl.program_members import varying from moderngl_window import geometry from base import CameraWindow import glm @@ -28,7 +28,7 @@ class CubeVoxel(CameraWindow): name = "Cube Voxel" window_size = 1920, 1080 - resource_dir = (Path(__file__) / '../../resources').resolve() + resource_dir = (Path(__file__) / "../../resources").resolve() def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -40,9 +40,15 @@ def __init__(self, *args, **kwargs): self.voxel = Voxel(ctx=self.ctx, size=(s, s, s)) # Load resources for the voxel instance self.voxel.texture_prog = self.load_program("programs/texture.glsl") - self.voxel.gen_instance_prog = self.load_program("programs/voxel_cubes/gen_voxel_instance_data.glsl") - self.voxel.voxel_light_prog = self.load_program("programs/voxel_cubes/voxel_light.glsl") - self.voxel.voxel_wireframe_prog = self.load_program("programs/voxel_cubes/voxel_wireframe.glsl") + self.voxel.gen_instance_prog = self.load_program( + "programs/voxel_cubes/gen_voxel_instance_data.glsl" + ) + self.voxel.voxel_light_prog = self.load_program( + "programs/voxel_cubes/voxel_light.glsl" + ) + self.voxel.voxel_wireframe_prog = self.load_program( + "programs/voxel_cubes/voxel_wireframe.glsl" + ) self.wireframe = True self.voxel.rebuild() @@ -82,6 +88,7 @@ def render(self, time, frame_time): self.fill = not self.fill self.current_layer = 0 + class Voxel: """ Simple cube voxel implementation using OpenGL 3.3 core. @@ -97,7 +104,7 @@ def __init__(self, *, ctx: moderngl.Context, size: Tuple[int, int, int]): # 100 x 100 x 100 = 1_000_000 fragments # 1000 x 1000 = 1_000_000 fragments # We store several 100 x 100 layers respersting one slice in voxel - self.voxel_lookup = self.ctx.texture((1000, 1000), 1, dtype='f1') + self.voxel_lookup = self.ctx.texture((1000, 1000), 1, dtype="f1") self.voxel_lookup.filter = moderngl.NEAREST, moderngl.NEAREST self.voxel_lookup.repeat_x = False self.voxel_lookup.repeat_y = False @@ -128,10 +135,8 @@ def max_cubes(self) -> int: def render_wireframe(self, *, projection_matrix, camera_matrix, model_matrix=None): self.ctx.wireframe = True - translate = glm.translate(glm.vec3( - -self._size[0] / 2, - -self._size[0] / 2, - -self._size[0] * 2), + translate = glm.translate( + glm.vec3(-self._size[0] / 2, -self._size[0] / 2, -self._size[0] * 2), ) mat = camera_matrix * translate self.voxel_wireframe_prog["m_proj"].write(projection_matrix) @@ -142,10 +147,8 @@ def render_wireframe(self, *, projection_matrix, camera_matrix, model_matrix=Non def render(self, *, projection_matrix, camera_matrix, model_matrix=None): """Render out the voxel to the screen""" - translate = glm.translate(glm.vec3( - -self._size[0] / 2, - -self._size[0] / 2, - -self._size[0] * 2), + translate = glm.translate( + glm.vec3(-self._size[0] / 2, -self._size[0] / 2, -self._size[0] * 2), ) mat = camera_matrix * translate normal = glm.transpose(glm.inverse(glm.mat3(mat))).to_bytes() @@ -167,13 +170,17 @@ def rebuild(self): self.gen_instance_prog["voxel_size"] = self._size self.voxel_lookup.use(location=0) with self._query: - self.gen_instance_vao.transform(self.instance_data, mode=moderngl.POINTS, vertices=self.max_cubes) + self.gen_instance_vao.transform( + self.instance_data, mode=moderngl.POINTS, vertices=self.max_cubes + ) self._num_instances = self._query.primitives def fill_layer(self, layer: int, value: int): x = (layer % 10) * self._size[0] y = (layer // 10) * self._size[1] - self.voxel_lookup.write(array('B', [value] * 100 * 100), viewport=(x, y, 100, 100)) + self.voxel_lookup.write( + array("B", [value] * 100 * 100), viewport=(x, y, 100, 100) + ) # NOTE: These functions can make adding and removing cubes extremely fast def add_cubes(self, positions): diff --git a/examples/ssao.py b/examples/ssao.py index 48a6df05..61881a64 100644 --- a/examples/ssao.py +++ b/examples/ssao.py @@ -1,5 +1,5 @@ - import imgui +import glm import numpy as np from pathlib import Path @@ -17,11 +17,11 @@ class SSAODemo(OrbitDragCameraWindow): """ title = "SSAO" - resource_dir = (Path(__file__) / '../resources').resolve() + resource_dir = (Path(__file__) / "../resources").resolve() def __init__(self, **kwargs): super().__init__(**kwargs) - #self.wnd.mouse_exclusivity = True + # self.wnd.mouse_exclusivity = True self.camera.projection.update(near=0.1, far=50.0) self.camera.radius = 2.0 @@ -48,7 +48,7 @@ def __init__(self, **kwargs): self.g_depth = self.ctx.depth_texture(self.wnd.buffer_size) self.g_buffer = self.ctx.framebuffer( color_attachments=[self.g_view_z, self.g_normal], - depth_attachment=self.g_depth + depth_attachment=self.g_depth, ) # Generate the SSAO framebuffer. @@ -56,7 +56,9 @@ def __init__(self, **kwargs): self.ssao_buffer = self.ctx.framebuffer(color_attachments=[self.ssao_occlusion]) # Generate the blurred SSAO framebuffer. - self.ssao_blurred_occlusion = self.ctx.texture(self.wnd.buffer_size, 1, dtype="f1") + self.ssao_blurred_occlusion = self.ctx.texture( + self.wnd.buffer_size, 1, dtype="f1" + ) self.ssao_blurred_buffer = self.ctx.framebuffer( color_attachments=[self.ssao_blurred_occlusion] ) @@ -81,27 +83,29 @@ def __init__(self, **kwargs): self.shading_program["ssao_occlusion"].value = 2 # Load the scene. - self.scene = self.load_scene('scenes/stanford_dragon.obj', cache=True) + self.scene = self.load_scene("scenes/stanford_dragon.obj", cache=True) self.vao = self.scene.root_nodes[0].mesh.vao.instance(self.geometry_program) # Generate a fullscreen quad. self.quad_fs = moderngl_window.geometry.quad_fs() # Generate SSAO samples (in tangent space coordinates, with z along the normal). - self.n_ssao_samples = 64 # If you change this number, also change ssao.glsl. + self.n_ssao_samples = 64 # If you change this number, also change ssao.glsl. self.ssao_std_dev = 0.1 - self.ssao_samples = np.random.normal(0.0, self.ssao_std_dev, (self.n_ssao_samples, 3)) + self.ssao_samples = np.random.normal( + 0.0, self.ssao_std_dev, (self.n_ssao_samples, 3) + ) self.ssao_samples[:, 2] = np.abs(self.ssao_samples[:, 2]) - self.ssao_program["samples"].write(self.ssao_samples.ravel().astype('f4')) + self.ssao_program["samples"].write(self.ssao_samples.ravel().astype("f4")) # Create random vectors used to decorrelate SSAO samples. - rand_texture_size = 32 # If you change this number, also change ssao.glgl. + rand_texture_size = 32 # If you change this number, also change ssao.glgl. rand_texture_data = np.random.bytes(3 * rand_texture_size * rand_texture_size) self.random_texture = self.ctx.texture( (rand_texture_size, rand_texture_size), 3, dtype="f1", - data=rand_texture_data + data=rand_texture_data, ) self.random_texture.filter == (moderngl.NEAREST, moderngl.NEAREST) self.random_texture.repeat_x = True @@ -110,35 +114,41 @@ def __init__(self, **kwargs): # Set up imgui. imgui.create_context() if self.wnd.ctx.error != "GL_NO_ERROR": - print(self.wnd.ctx.error) + print(self.wnd.ctx.error) self.imgui = ModernglWindowRenderer(self.wnd) def render(self, time: float, frametime: float): - self.average_frame_time = (self.frame_time_decay_factor * self.average_frame_time + - (1.0 - self.frame_time_decay_factor) * frametime) + self.average_frame_time = ( + self.frame_time_decay_factor * self.average_frame_time + + (1.0 - self.frame_time_decay_factor) * frametime + ) projection_matrix = self.camera.projection.matrix camera_matrix = self.camera.matrix mvp = projection_matrix * camera_matrix - camera_pos = (self.camera.position.x, self.camera.position.y, self.camera.position.z) + camera_pos = ( + self.camera.position.x, + self.camera.position.y, + self.camera.position.z, + ) # Run the geometry pass. self.ctx.enable_only(moderngl.DEPTH_TEST | moderngl.CULL_FACE) self.g_buffer.clear(0.0, 0.0, 0.0) self.g_buffer.use() - self.geometry_program["mvp"].write(mvp.astype('f4')) - self.geometry_program["m_camera"].write(camera_matrix.astype('f4')) + self.geometry_program["mvp"].write(mvp) + self.geometry_program["m_camera"].write(camera_matrix) self.vao.render() # Calculate occlusion. self.ctx.disable(moderngl.DEPTH_TEST) self.ssao_buffer.clear(0.0) self.ssao_buffer.use() - self.ssao_program["m_camera_inverse"].write(camera_matrix.inverse.astype('f4')) - self.ssao_program["m_projection_inverse"].write(projection_matrix.inverse.astype('f4')) + self.ssao_program["m_camera_inverse"].write(glm.inverse(camera_matrix)) + self.ssao_program["m_projection_inverse"].write(glm.inverse(projection_matrix)) self.ssao_program["v_camera_pos"].value = camera_pos self.ssao_program["f_camera_pos"].value = camera_pos - self.ssao_program["mvp"].write(mvp.astype('f4')) + self.ssao_program["mvp"].write(mvp) self.ssao_program["z_offset"].value = self.ssao_z_offset self.g_view_z.use(location=0) self.g_normal.use(location=1) @@ -153,15 +163,19 @@ def render(self, time: float, frametime: float): self.quad_fs.render(self.blur_program) # Run the shading pass. - self.ctx.screen.clear(1.0, 1.0, 1.0); + self.ctx.screen.clear(1.0, 1.0, 1.0) self.ctx.screen.use() - self.shading_program["m_camera_inverse"].write(camera_matrix.inverse.astype('f4')) - self.shading_program["m_projection_inverse"].write(projection_matrix.inverse.astype('f4')) + self.shading_program["m_camera_inverse"].write(glm.inverse(camera_matrix)) + self.shading_program["m_projection_inverse"].write( + glm.inverse(projection_matrix) + ) self.shading_program["v_camera_pos"].value = camera_pos self.shading_program["camera_pos"].value = camera_pos self.shading_program["light_pos"].value = camera_pos self.shading_program["base_color"].value = tuple(self.base_color) - self.shading_program["material_properties"].value = tuple(self.material_properties) + self.shading_program["material_properties"].value = tuple( + self.material_properties + ) self.shading_program["render_mode"].value = self.render_mode self.g_view_z.use(location=0) self.g_normal.use(location=1) @@ -179,8 +193,12 @@ def render_ui(self): imgui.begin("Debug Panel", False) imgui.text(f"Frame time: {1000.0 * self.average_frame_time:.1f} ms") imgui.text(f"FPS: {1.0 / self.average_frame_time:.1f}") - _, self.render_mode = imgui.combo("render mode", self.render_mode, self.render_modes) - _, self.ssao_z_offset = imgui.slider_float("SSAO z-offset", self.ssao_z_offset, -0.3, 0.3) + _, self.render_mode = imgui.combo( + "render mode", self.render_mode, self.render_modes + ) + _, self.ssao_z_offset = imgui.slider_float( + "SSAO z-offset", self.ssao_z_offset, -0.3, 0.3 + ) _, self.ssao_blur = imgui.checkbox("blur occlusion texture", self.ssao_blur) _, self.base_color = imgui.color_edit3( @@ -189,10 +207,18 @@ def render_ui(self): self.base_color[1], self.base_color[2], ) - _, self.material_properties[0] = imgui.slider_float("ambient", self.material_properties[0], 0.0, 1.0) - _, self.material_properties[1] = imgui.slider_float("diffuse", self.material_properties[1], 0.0, 1.0) - _, self.material_properties[2] = imgui.slider_float("specular", self.material_properties[2], 0.0, 1.0) - _, self.material_properties[3] = imgui.slider_float("specular exponent", self.material_properties[3], 1.0, 50.0) + _, self.material_properties[0] = imgui.slider_float( + "ambient", self.material_properties[0], 0.0, 1.0 + ) + _, self.material_properties[1] = imgui.slider_float( + "diffuse", self.material_properties[1], 0.0, 1.0 + ) + _, self.material_properties[2] = imgui.slider_float( + "specular", self.material_properties[2], 0.0, 1.0 + ) + _, self.material_properties[3] = imgui.slider_float( + "specular exponent", self.material_properties[3], 1.0, 50.0 + ) imgui.end() imgui.render() @@ -223,5 +249,5 @@ def key_event(self, key, action, modifiers): super().key_event(key, action, modifiers) -if __name__ == '__main__': +if __name__ == "__main__": moderngl_window.run_window_config(SSAODemo) diff --git a/examples/uniform_block.py b/examples/uniform_block.py index 96cccbc8..31b9d5df 100644 --- a/examples/uniform_block.py +++ b/examples/uniform_block.py @@ -7,13 +7,14 @@ class CubeSimple(moderngl_window.WindowConfig): """Simply shows two cubes rendered with the same uniform block data""" + title = "Uniform Blocks" def __init__(self, **kwargs): super().__init__(**kwargs) self.cube = geometry.cube(size=(2, 2, 2)) shader_source = { - 'vertex_shader': ''' + "vertex_shader": """ #version 330 in vec3 in_position; @@ -39,8 +40,8 @@ def __init__(self, **kwargs): normal = m_normal * in_normal; pos = p.xyz; } - ''', - 'fragment_shader': ''' + """, + "fragment_shader": """ #version 330 out vec4 color; @@ -52,25 +53,27 @@ def __init__(self, **kwargs): float l = dot(normalize(-pos), normalize(normal)); color = vec4(1.0) * (0.25 + abs(l) * 0.75); } - ''', + """, } self.prog1 = self.ctx.program(**shader_source) - self.prog1['pos_offset'].value = (1.1, 0, 0) + self.prog1["pos_offset"].value = (1.1, 0, 0) self.prog2 = self.ctx.program(**shader_source) - self.prog2['pos_offset'].value = (-1.1, 0, 0) + self.prog2["pos_offset"].value = (-1.1, 0, 0) self.vao1 = self.cube.instance(self.prog1) self.vao2 = self.cube.instance(self.prog2) self.m_proj = glm.perspective( - glm.radians(75), self.wnd.aspect_ratio, # fov, aspect - 0.1, 100.0, # near, far + glm.radians(75), + self.wnd.aspect_ratio, # fov, aspect + 0.1, + 100.0, # near, far ) - proj_uniform1 = self.prog1['Projection'] - view_uniform1 = self.prog1['View'] - proj_uniform2 = self.prog2['Projection'] - view_uniform2 = self.prog2['View'] + proj_uniform1 = self.prog1["Projection"] + view_uniform1 = self.prog1["View"] + proj_uniform2 = self.prog2["Projection"] + view_uniform2 = self.prog2["View"] self.proj_buffer = self.ctx.buffer(reserve=proj_uniform1.size) self.view_buffer = self.ctx.buffer(reserve=view_uniform1.size) @@ -80,7 +83,7 @@ def __init__(self, **kwargs): proj_uniform2.binding = 1 view_uniform2.binding = 2 - self.proj_buffer.write(self.m_proj.tobytes()) + self.proj_buffer.write(self.m_proj) self.scope1 = self.ctx.scope( self.ctx.fbo, @@ -116,5 +119,5 @@ def render(self, time=0.0, frametime=0.0, target: moderngl.Framebuffer = None): self.vao2.render(mode=moderngl.TRIANGLES) -if __name__ == '__main__': +if __name__ == "__main__": moderngl_window.run_window_config(CubeSimple) diff --git a/examples/video.py b/examples/video.py index 25f151c0..f71c0b60 100644 --- a/examples/video.py +++ b/examples/video.py @@ -1,3 +1,9 @@ +""" +Relies on the PyAV library to decode video frames and display them using a texture. + + pip install av +""" + import math from typing import Tuple, Union from pathlib import Path @@ -13,7 +19,7 @@ class Decoder: def __init__(self, path: Union[str, Path]): self.container = av.open(str(path)) self.video = self.container.streams[0] - self.video.thread_type = 'AUTO' + self.video.thread_type = "AUTO" self._last_packet = None self._frame_step = float(self.video.time_base) @@ -112,13 +118,15 @@ def update(self, time: float): next_pos = self._decoder.time_to_pos(time) delta = next_pos - self._decoder.current_pos - print(( - f"frame_step={self._decoder.frame_step}, " - f"delta={delta}, " - f"next_pos={next_pos}, " - f"current_pos={self._decoder.current_pos}, " - f"time={time}" - )) + print( + ( + f"frame_step={self._decoder.frame_step}, " + f"delta={delta}, " + f"next_pos={next_pos}, " + f"current_pos={self._decoder.current_pos}, " + f"time={time}" + ) + ) # Seek we are more than 3 frames off if abs(delta) > self._decoder.frame_step * 3: @@ -147,12 +155,14 @@ def next_frame(self) -> av.plane.Plane: class VideoTest(moderngl_window.WindowConfig): gl_version = (3, 3) title = "Video Player" - resource_dir = Path(__file__).parent.resolve() / 'resources' + resource_dir = Path(__file__).parent.resolve() / "resources" def __init__(self, **kwargs): super().__init__(**kwargs) - self.player = Player(self.ctx, self.resource_dir / 'videos/Lightning - 33049.mp4') + self.player = Player( + self.ctx, self.resource_dir / "videos/Lightning - 33049.mp4" + ) print("duration :", self.player.duration) print("fps :", self.player.fps) print("video_size :", self.player.video_size) @@ -160,7 +170,7 @@ def __init__(self, **kwargs): print("step :", self.player._decoder.frame_step) self.quad = geometry.quad_fs() - self.program = self.load_program('programs/texture_flipped.glsl') + self.program = self.load_program("programs/texture_flipped.glsl") def render(self, time, frametime): self.player.update(math.fmod(time, 5)) @@ -182,5 +192,5 @@ def key_event(self, key, action, modifiers): self.timer.toggle_pause() -if __name__ == '__main__': +if __name__ == "__main__": VideoTest.run() diff --git a/moderngl_window/text/bitmapped/text_2d.py b/moderngl_window/text/bitmapped/text_2d.py index a5d77800..41b69c5f 100644 --- a/moderngl_window/text/bitmapped/text_2d.py +++ b/moderngl_window/text/bitmapped/text_2d.py @@ -23,9 +23,9 @@ class TextWriter2D(BaseText): def __init__(self): super().__init__() - meta = FontMeta(resources.data.load( - DataDescription(path="bitmapped/text/meta.json") - )) + meta = FontMeta( + resources.data.load(DataDescription(path="bitmapped/text/meta.json")) + ) self._texture = resources.textures.load( TextureDescription( path="bitmapped/textures/VeraMono.png", @@ -41,12 +41,12 @@ def __init__(self): self._init(meta) self._string_buffer = self.ctx.buffer(reserve=1024 * 4) - self._string_buffer.clear(chunk=b'\32') + self._string_buffer.clear(chunk=b"\32") pos = self.ctx.buffer(data=bytes([0] * 4 * 3)) self._vao = VAO("textwriter", mode=moderngl.POINTS) - self._vao.buffer(pos, '3f', 'in_position') - self._vao.buffer(self._string_buffer, '1u/i', 'in_char_id') + self._vao.buffer(pos, "3f", "in_position") + self._vao.buffer(self._string_buffer, "1u/i", "in_char_id") self._text: str = None @@ -58,11 +58,11 @@ def text(self) -> str: def text(self, value: str): self._text = value self._string_buffer.orphan(size=len(value) * 4) - self._string_buffer.clear(chunk=b'\32') + self._string_buffer.clear(chunk=b"\32") self._write(value) def _write(self, text: str): - self._string_buffer.clear(chunk=b'\32') + self._string_buffer.clear(chunk=b"\32") self._string_buffer.write( numpy.fromiter( @@ -75,14 +75,13 @@ def draw(self, pos, length=-1, size=24.0): # Calculate ortho projection based on viewport vp = self.ctx.fbo.viewport w, h = vp[2], vp[3] - projection = glm.orthographic( + projection = glm.ortho( 0, # left w, # right 0, # bottom h, # top 1.0, # near -1.0, # far - dtype=numpy.float32, ) self._texture.use(location=0)