def main(argv=None): ''' main ''' parser = argparse.ArgumentParser(prog='ModernGL') parser.add_argument('-v', '--version', action='version', version='ModernGL %s' % ModernGL.__version__) parser.add_argument('-i', '--info', action='store_true', default=False) args = parser.parse_args(argv) ctx = ModernGL.create_standalone_context() if args.info: print(json.dumps(ctx.info, sort_keys=True, indent=4)) else: repo = os.path.isfile( os.path.join(os.path.dirname(__file__), 'README.md')) install = '(git repository)' if repo else '(installed)' print('ModernGL:', ModernGL.__version__, install) print('Vendor:', ctx.vendor) print('Renderer:', ctx.renderer) print('Version:', ctx.version) print('Python:', sys.version) print('Platform:', sys.platform)
def setUpClass(cls): cls.ctx = ModernGL.create_standalone_context() cls.vert = cls.ctx.vertex_shader(''' #version 330 in vec2 in_v; out vec2 out_v; uniform Block1 { float x; }; uniform Block2 { float y; }; uniform Block3 { float z; }; void main() { out_v = in_v * z + vec2(x, y); } ''') cls.prog = cls.ctx.program(cls.vert, ['out_v'])
def main(): ''' main ''' parser = argparse.ArgumentParser(prog='ModernGL') parser.add_argument('-v', '--version', action='version', version='ModernGL %s' % ModernGL.__version__) parser.add_argument('-i', '--info', action='store_true', default=False) args = parser.parse_args() ctx = ModernGL.create_standalone_context() if args.info: print(json.dumps(ctx.info, sort_keys=True, indent=4)) else: print('ModernGL:', ModernGL.__version__) print('Vendor:', ctx.vendor) print('Renderer:', ctx.renderer) print('Version:', ctx.version) print('Python:', sys.version) print('Platform:', sys.platform)
def setUpClass(cls): cls.ctx = ModernGL.create_standalone_context() cls.vbo = cls.ctx.buffer(reserve=1024) cls.res = cls.ctx.buffer(reserve=1024) cls.vbo.clear() cls.shader = '''
def test_basic_material(): # create context ctx = ModernGL.create_standalone_context() # create renderer renderer = ModernGLRenderer(ctx) # create scene scene = radiant.Scene() cube_geom = radiant.PlaneGeometry() red = radiant.MeshBasicMaterial(color=(1.0, 0.0, 0.0, 0.0)) cube = radiant.Mesh(cube_geom, red) scene.append_child(cube) # create camera camera = radiant.PerspectiveCamera(position=[10, 10, 10], target=[0, 0, 0], up=[0, 1, 0]) scene.append_child(camera) # create framebuffer and render into it fbo = ctx.framebuffer(ctx.renderbuffer((512, 512))) fbo.use() renderer.render(scene, camera) # read from the framebuffer and write to an image file data = fbo.read(components=3, alignment=1) img = Image.frombytes('RGB', fbo.size, data).transpose(Image.FLIP_TOP_BOTTOM) filename = "test_basic.png" with open(filename, mode="wb") as fh: img.save(fh) # complete the test assert os.path.exists(filename)
def setUpClass(cls): cls.ctx = ModernGL.create_standalone_context() cls.vert = cls.ctx.vertex_shader(''' #version 330 in int a_in; in int b_in; in int c_in; in int d_in; out int a_out; out int b_out; out int c_out; out int d_out; void main() { a_out = a_in * 2; b_out = b_in * 2; c_out = c_in * 2; d_out = d_in * 2; } ''') cls.prog = cls.ctx.program(cls.vert, ['a_out', 'b_out', 'c_out', 'd_out'])
def create(cls, width, height): ctx = ModernGL.create_standalone_context() color_rbo = ctx.renderbuffer((width, height), samples=ctx.max_samples) fbo = ctx.framebuffer([color_rbo]) fbo.use() prog = ctx.program([ ctx.vertex_shader(''' #version 330 in vec3 in_vert; in vec4 in_color; out vec4 v_color; uniform mat4 mvp; void main() { gl_Position = mvp * vec4(in_vert, 1.0); v_color = in_color; } '''), ctx.fragment_shader(''' #version 330 in vec4 v_color; out vec4 f_color; void main() { f_color = v_color; } '''), ]) ctx.enable(ModernGL.BLEND) return cls(width, height, ctx, prog, fbo)
def setUpClass(cls): cls.ctx = ModernGL.create_standalone_context() prog = cls.ctx.program([ cls.ctx.vertex_shader(''' #version 330 in vec2 vert; out vec2 text; void main() { gl_Position = vec4(vert * 2.0 - 1.0, 0.0, 1.0); text = vert; } '''), cls.ctx.fragment_shader(''' #version 330 uniform sampler2D Texture; in vec2 text; out vec4 color; void main() { color = texture(Texture, text); } '''), ]) vbo = cls.ctx.buffer(struct.pack('8f', 0, 0, 0, 1, 1, 0, 1, 1)) cls.vao = cls.ctx.simple_vertex_array(prog, vbo, ['vert'])
def get_context() -> ModernGL.Context: ctx = _static.get('context') if ctx is None: ctx = ModernGL.create_standalone_context() _static['context'] = ctx return ctx
def __init__(self, compute_shader, **named_args): self.ctx = ModernGL.create_standalone_context() #self.prog = self.ctx.program([self.ctx.compute_shader(compute_shader)]) self.cpu = self.ctx.compute_shader(compute_shader) #self.cpu.uniform_blocks['Output']. for name, value in named_args.items(): self.cpu.uniforms[name].value = value
def __init__(self, viewport=(299, 299)): """ Construct a Renderer object viewport: width and height of windows """ super(Renderer, self).__init__() self.width, self.height = viewport # require OpenGL 330 core profile self.ctx = ModernGL.create_standalone_context(viewport, require=330) self.ctx.enable(ModernGL.DEPTH_TEST) self.ctx.enable(ModernGL.CULL_FACE) # frame buffer object self.fbo = self.ctx.framebuffer( self.ctx.texture(viewport, components=2, floats=True), self.ctx.depth_renderbuffer(viewport) ) # shader program self.prog = self.ctx.program([ self.ctx.vertex_shader(''' #version 330 core // model view projection matrix uniform mat4 mvp; in vec3 in_vert; in vec2 in_text; out vec2 v_text; void main() { gl_Position = mvp * vec4(in_vert, 1.0f); // UV coordinate starts from bottom left corner // image coordinate starts from top left corner // therefore we need to flip the V-axis v_text = vec2(in_text.x, 1.0f - in_text.y); } '''), self.ctx.fragment_shader(''' #version 330 core in vec2 v_text; out vec2 f_color; void main() { f_color = v_text; } ''') ]) self.mvp = self.prog.uniforms['mvp']
def main(): ''' main ''' parser = argparse.ArgumentParser(prog='ModernGL') parser.add_argument('-v', '--version', action='version', version='ModernGL %s' % ModernGL.__version__) parser.parse_args() ctx = ModernGL.create_standalone_context() print('ModernGL:', ModernGL.__version__) print('Vendor:', ctx.vendor) print('Renderer:', ctx.renderer) print('Version:', ctx.version)
def setUpClass(cls): cls.ctx = ModernGL.create_standalone_context() cls.vert = cls.ctx.vertex_shader(''' #version 330 in vec2 in_v1; in vec2 in_v2; out vec2 out_v; void main() { out_v = in_v1 + in_v2; } ''') cls.prog = cls.ctx.program(cls.vert, ['out_v'])
def __init__(self, size, vertex, fragment): self.size = size self.context = ModernGL.create_standalone_context(self.size) renderbuffer = self.context.renderbuffer(self.size, 3) self.framebuffer = self.context.framebuffer(renderbuffer) self.framebuffer.use() program = self.context.program([self.context.vertex_shader(vertex), self.context.fragment_shader(fragment)]) self.fraction = program.uniforms['fraction'] vbo = self.context.buffer(struct.pack('8f', -1, -1, 1, -1, -1, 1, 1, 1)) self.vao = self.context.simple_vertex_array(program, vbo, ['vertex']) self.texture = self.context.texture(self.size, 3) self.texture.use() self.context.enable(ModernGL.BLEND)
def setUpClass(self): self.ctx = ModernGL.create_standalone_context() self.vert = self.ctx.vertex_shader(''' #version 330 in vec2 in_v1; in vec2 in_v2; out vec2 out_v; void main() { out_v = in_v1 + in_v2; } ''') self.prog = self.ctx.program(self.vert, ['out_v'])
def setUpClass(self): self.ctx = ModernGL.create_standalone_context() self.vert = self.ctx.vertex_shader(''' #version 330 in mat2 in_m; in vec2 in_v; out vec2 out_v; uniform float mult; void main() { out_v = in_m * in_v * mult; } ''') self.prog = self.ctx.program(self.vert, ['out_v'])
def setUpClass(cls): cls.ctx = ModernGL.create_standalone_context() cls.vertex_shader = cls.ctx.vertex_shader(''' #version 330 uniform mat4 Mvp; in vec4 vertex; uniform Block { mat4 Transform; }; void main() { gl_Position = Mvp * Transform * vertex; } ''') cls.geometry_shader = cls.ctx.geometry_shader(''' #version 330 layout(points) in; uniform vec4 Position; layout(line_strip, max_vertices = 2) out; out vec4 color; void main() { gl_Position = gl_in[0].gl_Position + Position; EmitVertex(); gl_Position = gl_in[0].gl_Position - Position; EmitVertex(); EndPrimitive(); } ''') cls.fragment_shader = cls.ctx.fragment_shader(''' #version 330 uniform vec4 Color; uniform Lights { uniform vec4 Light[1]; }; out vec4 color; void main() { color = Color * Light[0]; } ''')
def test_phong(): # create context ctx = ModernGL.create_standalone_context() # create renderer renderer = ModernGLRenderer(ctx) # create scene scene = radiant.Scene() plane_geom = radiant.PlaneGeometry(width=2, height=2) red = radiant.MeshPhongMaterial(color=(0.1, 0.5, 0.3, 1.0), shininess=16.0) plane = radiant.Mesh(plane_geom, red) scene.append_child(plane) # create a light light = radiant.PointLight(position=[-0.5, -0.5, 4]) plane.append_child(light) # follow the plane # create camera camera = radiant.PerspectiveCamera(position=[0.5, 0.5, 2], target=[0, 0, 0], up=[0, 1, 0]) scene.append_child(camera) # create framebuffer and render into it fbo = ctx.framebuffer(ctx.renderbuffer((512, 512))) fbo.use() renderer.render(scene, camera, light=light) # read from the framebuffer and write to an image file data = fbo.read(components=3, alignment=1) img = Image.frombytes('RGB', fbo.size, data).transpose(Image.FLIP_TOP_BOTTOM) filename = "test_phong.png" with open(filename, mode="wb") as fh: img.save(fh) # complete the test assert os.path.exists(filename)
def setUpClass(cls): cls.ctx = ModernGL.create_standalone_context() prog = cls.ctx.program([ cls.ctx.vertex_shader(''' #version 330 in float v_in_1; in float v_in_2; in float v_in_3; out float v_out; void main() { v_out = v_in_1 + v_in_2 + v_in_3; } '''), ], varyings=['v_out']) vbo1 = cls.ctx.buffer(struct.pack('4f', 1.0, 2.0, 3.0, 4.0)) vbo2 = cls.ctx.buffer(struct.pack('4f', 10.0, 20.0, 30.0, 40.0)) vbo3 = cls.ctx.buffer(struct.pack('4f', 100.0, 200.0, 300.0, 400.0)) vao1_content = [ (vbo1, 'f', ['v_in_1']), (vbo2, 'f/i', ['v_in_2']), ] cls.vao1 = cls.ctx.vertex_array(prog, vao1_content) vao2_content = [ (vbo1, 'f', ['v_in_1']), (vbo2, 'f/i', ['v_in_2']), (vbo3, 'f/r', ['v_in_3']), ] cls.vao2 = cls.ctx.vertex_array(prog, vao2_content) cls.res = cls.ctx.buffer(reserve=1024)
import struct import ModernGL from PIL import Image size = 512, 512 ctx = ModernGL.create_standalone_context() color_rbo = ctx.renderbuffer(size, samples=ctx.max_samples) depth_rbo = ctx.depth_renderbuffer(size, samples=ctx.max_samples) fbo = ctx.framebuffer(color_rbo, depth_rbo) fbo.use() prog = ctx.program([ ctx.vertex_shader(''' #version 330 in vec2 vert; out vec2 tex; void main() { gl_Position = vec4(vert, 0.0, 1.0); tex = vert / 2.0; } '''), ctx.fragment_shader(''' #version 330 in vec2 tex; out vec4 color;
import struct import tkinter import ModernGL import ModernGL.tk ctx = ModernGL.create_standalone_context() prog = ctx.program( ctx.vertex_shader(''' #version 330 in vec2 vert; in vec3 vert_color; out vec3 frag_color; uniform vec2 scale; uniform float rotation; void main() { frag_color = vert_color; mat2 rot = mat2( cos(rotation), sin(rotation), -sin(rotation), cos(rotation) ); gl_Position = vec4((rot * vert) * scale, 0.0, 1.0); } '''), ctx.fragment_shader(''' #version 330
def setUpClass(cls): cls.ctx = ModernGL.create_standalone_context()
def setUpClass(self): self.ctx = ModernGL.create_standalone_context()
def get_piece_heatmaps(frame_size, voxel_resolution, projection): rotation, jacobian = cv2.Rodrigues( projection.pose.rvec.astype(numpy.float32)) inv_rotation = rotation.transpose() inv_tvec = numpy.dot(inv_rotation, -projection.pose.tvec.astype(numpy.float32)) inv_pose = numpy.vstack( [numpy.hstack([inv_rotation, inv_tvec]), numpy.float32([0, 0, 0, 1])]) inv_camera_matrix = numpy.linalg.inv( projection.cameraIntrinsics.cameraMatrix.astype(numpy.float32)) # Change the frame coordinates from (0, 0) - frame_size to (-1, -1) - (1, 1) gl_scale = numpy.float32([ [frame_size[0] / 2, 0, 0], [0, frame_size[1] / 2, 0], [0, 0, 1], ]) gl_shift = numpy.float32([ [1, 0, 1], [0, 1, 1], [0, 0, 1], ]) gl_inv_camera_matrix = numpy.dot(inv_camera_matrix, numpy.dot(gl_scale, gl_shift)) ext_inv_camera_matrix = numpy.vstack( [gl_inv_camera_matrix, numpy.float32([0, 0, 1])]) piece_voxels = voxels.get_piece_voxels(*voxel_resolution) # This helper performs volume ray casting ctx = ModernGL.create_standalone_context() voxels_size = tuple(reversed(piece_voxels.shape)) texture = ctx.texture3d(voxels_size, 1, piece_voxels, floats=True) texture.repeat_x = False texture.repeat_y = False texture.repeat_z = False texture.use() prog = ctx.program([ ctx.vertex_shader(''' #version 330 in vec2 canvas_coord; out vec2 tex_coord; void main() { gl_Position = vec4(canvas_coord, 0, 1); tex_coord = canvas_coord; } '''), ctx.fragment_shader(''' #version 330 struct OptionalFloat { bool isPresent; float value; }; uniform mat3 inv_projection; uniform vec3 camera_position; uniform vec3 piece_dimensions; uniform sampler3D voxels; in vec2 tex_coord; out float color; void reverse_project(vec2 image_coord, mat3 rotation, vec3 camera_position, out vec3 camera_ray) { vec3 hom_image_coord = vec3(image_coord, 1); vec3 world_coord = rotation * hom_image_coord; camera_ray = world_coord - camera_position; } void interceptBoundingBoxFace(float intercept, float tail, float dir, vec2 other_tail, vec2 other_dir, out OptionalFloat dist ) { if (dir == 0) { dist.isPresent = false; } else { dist.value = (intercept - tail) / dir; vec2 other_intercept = other_tail + other_dir * dist.value; dist.isPresent = all(greaterThanEqual(other_intercept, vec2(0))) && all(lessThanEqual(other_intercept, vec2(1))); } } void intersectBoundingBox(vec3 tail, vec3 dir, out float min_z, out float max_z) { OptionalFloat face_dist[6]; interceptBoundingBoxFace(0, tail.x, dir.x, tail.yz, dir.yz, face_dist[0]); interceptBoundingBoxFace(1, tail.x, dir.x, tail.yz, dir.yz, face_dist[1]); interceptBoundingBoxFace(0, tail.y, dir.y, tail.xz, dir.xz, face_dist[2]); interceptBoundingBoxFace(1, tail.y, dir.y, tail.xz, dir.xz, face_dist[3]); interceptBoundingBoxFace(0, tail.z, dir.z, tail.xy, dir.xy, face_dist[4]); interceptBoundingBoxFace(1, tail.z, dir.z, tail.xy, dir.xy, face_dist[5]); bool none_intercepted = true; for (int i = 0; i < face_dist.length(); ++i) { if (face_dist[i].isPresent) { if (none_intercepted || face_dist[i].value < min_z) { min_z = face_dist[i].value; } if (none_intercepted || face_dist[i].value > max_z) { max_z = face_dist[i].value; } none_intercepted = false; } } if (none_intercepted || max_z < 0) { discard; } min_z = max(min_z, 0); } void getBoundingBoxTraversal(vec3 tail, vec3 dir, float min_z, float max_z, out vec3 boundingBoxTraversal) { vec3 min_intercept = tail + dir * min_z; vec3 max_intercept = tail + dir * max_z; boundingBoxTraversal = max_intercept - min_intercept; } void getResolution(vec3 boundingBoxTraversal, vec3 textureSize, out int resolution) { vec3 textureTraversal = textureSize * boundingBoxTraversal; float voxelsTraversed = length(textureTraversal); resolution = int(ceil(voxelsTraversed)); } void main() { vec3 camera_ray; reverse_project(tex_coord, inv_projection, camera_position, camera_ray); float min_z, max_z; intersectBoundingBox(camera_position, camera_ray, min_z, max_z); vec3 boundingBoxTraversal; getBoundingBoxTraversal(camera_position, camera_ray, min_z, max_z, boundingBoxTraversal); int resolution; getResolution(boundingBoxTraversal, textureSize(voxels, 0), resolution); float depth = length(boundingBoxTraversal * piece_dimensions); float exp = depth / resolution; float step_z = (max_z - min_z) / resolution; float transparency = 1; for (int i = 0; i < resolution; ++i) { float z = min_z + (i + 0.5) * step_z; vec3 world_coord = camera_position + z * camera_ray; float voxel = texture(voxels, world_coord).x; transparency *= pow(1 - voxel, exp); } color = 1 - transparency; } '''), ]) fbo = ctx.framebuffer(ctx.renderbuffer(frame_size, components=1)) fbo.use() triangle_slice_vertices = numpy.float32([(-1, -1), (-1, 1), (1, -1), (1, 1)]) vbo = ctx.buffer(triangle_slice_vertices) vao = ctx.simple_vertex_array(prog, vbo, ['canvas_coord']) projection_shape = tuple(reversed(frame_size)) heatmaps = {} for (square, piece_type) in itertools.product(chess.SQUARES, chess.PIECE_TYPES): i = chess.square_file(square) j = chess.square_rank(square) height = size.HEIGHTS[piece_type] # Transform the piece to a cube at the origin, to simplify the ray caster shift = numpy.float32([ [1, 0, 0, -i], [0, 1, 0, -j], [0, 0, 1, 0], [0, 0, 0, 1], ]) stretch = numpy.float32([ [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1 / height, 0], [0, 0, 0, 1], ]) piece_inv_pose = numpy.dot(numpy.dot(shift, stretch), inv_pose) piece_inv_projection = numpy.dot(piece_inv_pose, ext_inv_camera_matrix) camera_position = numpy.dot(piece_inv_pose, numpy.float32([0, 0, 0, 1]).reshape(4, 1)) prog.uniforms['inv_projection'].write( piece_inv_projection[:3].transpose()) prog.uniforms['camera_position'].write(camera_position[:3]) prog.uniforms['piece_dimensions'].write(numpy.float32([1, 1, height])) ctx.clear() # TODO: It would be possible to speed this up by shrinking the frame # until it barely contains the bounding box vao.render(ModernGL.TRIANGLE_STRIP) data = fbo.read(components=1, floats=True) heatmap = numpy.frombuffer( data, dtype=numpy.float32).reshape(projection_shape) # TODO: Optimize the raycaster so it only creates the relevant part of the heatmap heatmaps[(square, piece_type)] = Heatmap(heatmap).as_sparse() return heatmaps
def get_square_heatmap(frame_size, projection, is_offset): ctx = ModernGL.create_standalone_context() weights = numpy.fromiter( (scipy.stats.norm.cdf( (weight_idx / EDGE_RESOLUTION) * EDGE_GAUSSIAN_SCALE) for weight_idx in range(EDGE_RESOLUTION - 1, -1, -1)), dtype=numpy.float32).reshape((1, EDGE_RESOLUTION)) weights_size = tuple(reversed(weights.shape)) texture = ctx.texture(weights_size, 1, weights, floats=True) texture.repeat_x = False texture.use() prog = ctx.program([ ctx.vertex_shader(''' #version 330 uniform mat4 projection; in vec2 board_coord; out vec2 tex_coord; void main() { vec4 homog_coord = vec4(board_coord, 0, 1); gl_Position = projection * homog_coord; tex_coord = board_coord; } '''), ctx.fragment_shader(''' #version 330 uniform sampler2D weights; in vec2 tex_coord; out float color; void get_axis_weight(float location, sampler2D axis_weights, out float weight) { float square_location = mod(location, 1); float tex_index = abs(0.5 - square_location) * 2; weight = texture(axis_weights, vec2(tex_index, 0)).x; } void main() { float hor_weight, ver_weight; get_axis_weight(tex_coord.x, weights, hor_weight); get_axis_weight(tex_coord.y, weights, ver_weight); color = hor_weight * ver_weight; } '''), ]) fbo = ctx.framebuffer(ctx.renderbuffer(frame_size, components=1)) fbo.use() squares = ((x, y) for y in range(8) for x in range(8) if bool((x + y) % 2) != is_offset) triangles = numpy.float32([[ [ (square[0], square[1]), (square[0], square[1] + 1), (square[0] + 1, square[1] + 1), ], [ (square[0] + 1, square[1] + 1), (square[0] + 1, square[1]), (square[0], square[1]), ], ] for square in squares]) vbo = ctx.buffer(triangles) vao = ctx.simple_vertex_array(prog, vbo, ['board_coord']) (rotation, jacobian) = cv2.Rodrigues(projection.pose.rvec) projection_matrix = numpy.dot( projection.cameraIntrinsics.cameraMatrix, numpy.hstack([rotation, projection.pose.tvec]), ).astype(numpy.float32) # Change the frame coordinates from (0, 0) - frame_size to (-1, -1) - (1, 1) gl_shift = numpy.float32([ [1, 0, -1], [0, 1, -1], [0, 0, 1], ]) gl_scale = numpy.float32([ [2 / frame_size[0], 0, 0], [0, 2 / frame_size[1], 0], [0, 0, 1], ]) scaled_matrix = numpy.dot(numpy.dot(gl_shift, gl_scale), projection_matrix) gl_projection = numpy.vstack([ scaled_matrix[:2], numpy.zeros(4, dtype=numpy.float32), scaled_matrix[2:], ]) prog.uniforms['projection'].write(gl_projection.transpose()) ctx.clear() vao.render() data = fbo.read(components=1, floats=True) projection_shape = tuple(reversed(frame_size)) heatmap = numpy.frombuffer(data, dtype=numpy.float32).reshape(projection_shape) return heatmaps.Heatmap(heatmap).as_sparse()