Last active
November 24, 2021 12:35
-
-
Save aforren1/a590b994e4b2ba7e40c6aa965bd0bbca to your computer and use it in GitHub Desktop.
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 moderngl as mgl | |
| import glfw | |
| import numpy as np | |
| import glm | |
| import mapbox_earcut as earcut | |
| from timeit import default_timer | |
| from xxhash import xxh32 | |
| vao_cache = {} | |
| class Shape: | |
| def __init__(self, ctx, shader, vertices, pos=(0, 0), color=(0,0,0,1), name=None): | |
| self.color = glm.vec4(color) | |
| self.pos = glm.vec2(pos) | |
| self.name = name | |
| idx = earcut.triangulate_float32(vertices, [vertices.shape[0]]) | |
| foo = vertices[idx] | |
| hsh = xxh32(seed=1) | |
| hsh.update(foo.data) | |
| hsh.update(shader.glo.to_bytes(4, 'big')) | |
| digest = hsh.hexdigest() | |
| if digest not in vao_cache: | |
| buf = ctx.buffer(data=foo) | |
| self.vao = vao_cache[digest] = ctx.vertex_array(shader, buf, 'vert') | |
| else: | |
| self.vao = vao_cache[digest] | |
| self.offset_unif = shader['offset'] | |
| self.color_unif = shader['color'] | |
| def draw(self): | |
| self.offset_unif.write(self.pos) | |
| self.color_unif.write(self.color) | |
| self.vao.render(mgl.TRIANGLES) | |
| vert = ''' | |
| #version 450 | |
| layout(location = 0) in vec2 vert; | |
| uniform vec2 offset; | |
| void main() { | |
| gl_Position = vec4(vert + offset, 0.0, 1.0); | |
| } | |
| ''' | |
| frag = ''' | |
| #version 450 | |
| layout(location = 0) uniform vec4 color; | |
| layout(location = 0) out vec4 out_color; | |
| void main() { | |
| out_color = color; | |
| } | |
| ''' | |
| frag2 = ''' | |
| #version 450 | |
| layout(location = 0) uniform vec4 color; | |
| layout(location = 0) out vec4 out_color; | |
| void main() { | |
| out_color = color; | |
| out_color.rgb = out_color.brg; | |
| } | |
| ''' | |
| rect = np.array([[-1, -1], [1, -1], [1, 1], [-1, 1]], dtype='f4') * 0.02 | |
| cross = np.array([[-1, 0.2], [-0.2, 0.2], [-0.2, 1], [0.2, 1], | |
| [0.2, 0.2], [1, 0.2], [1, -0.2], [0.2, -0.2], | |
| [0.2, -1], [-0.2, -1], [-0.2, -0.2], [-1, -0.2]], dtype='f4') * 0.02 | |
| arrow = np.array([[-1, 0.4], [0, 0.4], [0, 0.8], [1, 0], | |
| [0, -0.8], [0, -0.4], [-1, -0.4]], dtype='f4') * 0.02 | |
| def prod(x, y): | |
| return np.dstack(np.meshgrid(x, y)).reshape(-1, 2) | |
| if __name__ == '__main__': | |
| import sys | |
| if not glfw.init(): | |
| raise RuntimeError('GLFW failed.') | |
| glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 4) | |
| glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 5) | |
| glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE) | |
| glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True) | |
| glfw.window_hint(glfw.VISIBLE, True) | |
| if not (win := glfw.create_window(600, 600, 'Test', None, None)): | |
| glfw.terminate() | |
| raise RuntimeError('Window failed.') | |
| glfw.make_context_current(win) | |
| glfw.swap_interval(1) | |
| ctx = mgl.create_context(require=450) | |
| prog = ctx.program(vertex_shader=vert, fragment_shader=frag) | |
| prog2 = ctx.program(vertex_shader=vert, fragment_shader=frag2) | |
| bs = np.linspace(-1, 1, 50) | |
| shps = [] | |
| prods = prod(bs, bs) | |
| tot = prods.shape[0] | |
| bufs = [rect, cross, arrow] | |
| names = [0, 1, 2] | |
| t0 = default_timer() | |
| for i, (x, y) in enumerate(prods): | |
| col = i / tot, x * 0.5 + 0.5, y * 0.5 + 0.5, 1 | |
| p = prog if y > 0 else prog2 | |
| shps.append(Shape(ctx, p, bufs[i % 3], pos=(x, y), color=col, name=names[i % 3])) | |
| print(f'Startup time: {default_timer() - t0}') | |
| if len(sys.argv) > 1 and sys.argv[1] == '-sort': | |
| shps.sort(key=lambda x: x.name, reverse=True) | |
| query = ctx.query(time=True) | |
| N_SAMPLES = 1000 | |
| cpu_times = np.empty(N_SAMPLES) | |
| gpu_times = np.empty(N_SAMPLES) | |
| counter = 0 | |
| while not glfw.window_should_close(win) and counter < N_SAMPLES: | |
| ctx.clear(0.2, 0.1, 0.1) | |
| with query: | |
| t0 = default_timer() | |
| for shp in shps: | |
| shp.draw() | |
| #vao.render() | |
| t1 = default_timer() | |
| cpu_times[counter] = t1 - t0 | |
| gpu_times[counter] = query.elapsed | |
| glfw.swap_buffers(win) | |
| glfw.poll_events() | |
| counter += 1 | |
| glfw.terminate() | |
| print(f'Avg CPU: {np.mean(cpu_times) * 1000} ms') | |
| print(f'Avg GPU: {np.mean(gpu_times) / 1000000} ms') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment