def _compute_animation(cfg, animate_pre_render=True): cfg.duration = 5 cfg.aspect_ratio = (1, 1) local_size = 2 vertices_data = array.array( "f", [ # fmt: off -0.5, -0.5, 0.0, 0.5, -0.5, 0.0, -0.5, 0.5, 0.0, 0.5, 0.5, 0.0, # fmt: on ], ) nb_vertices = 4 input_vertices = ngl.BufferVec3(data=vertices_data, label="vertices") output_vertices = ngl.BufferVec3(data=vertices_data, label="vertices") input_block = ngl.Block(fields=[input_vertices], layout="std140") output_block = ngl.Block(fields=[output_vertices], layout="std140") rotate_animkf = [ ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration, 360) ] rotate = ngl.Rotate(ngl.Identity(), axis=(0, 0, 1), angle=ngl.AnimatedFloat(rotate_animkf)) transform = ngl.UniformMat4(transform=rotate) program = ngl.ComputeProgram(_ANIMATION_COMPUTE, workgroup_size=(local_size, local_size, 1)) program.update_properties(dst=ngl.ResourceProps(writable=True)) compute = ngl.Compute(workgroup_count=(nb_vertices / (local_size**2), 1, 1), program=program) compute.update_resources(transform=transform, src=input_block, dst=output_block) quad_buffer = ngl.BufferVec3(block=output_block, block_field=0) geometry = ngl.Geometry(quad_buffer, topology="triangle_strip") program = ngl.Program(vertex=cfg.get_vert("color"), fragment=cfg.get_frag("color")) render = ngl.Render(geometry, program) render.update_frag_resources(color=ngl.UniformVec3(value=COLORS.sgreen), opacity=ngl.UniformFloat(1)) children = (compute, render) if animate_pre_render else (render, compute) return ngl.Group(children=children)
def compute_particules(cfg): random.seed(0) cfg.duration = 10 local_size = 4 nb_particules = 128 shader_version = '310 es' if cfg.backend == 'gles' else '430' shader_data = dict( version=shader_version, local_size=local_size, nb_particules=nb_particules, ) compute_shader = _PARTICULES_COMPUTE % shader_data vertex_shader = _PARTICULES_VERT % shader_data fragment_shader = _PARTICULES_FRAG % shader_data positions = array.array('f') velocities = array.array('f') for i in range(nb_particules): positions.extend([ random.uniform(-2.0, 1.0), random.uniform(-1.0, 1.0), 0.0, ]) velocities.extend([ random.uniform(1.0, 2.0), random.uniform(0.5, 1.5), ]) ipositions = ngl.Block( fields=[ ngl.BufferVec3(data=positions), ngl.BufferVec2(data=velocities), ], layout='std430', ) opositions = ngl.Block(fields=[ngl.BufferVec3(count=nb_particules)], layout='std430') animkf = [ ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration, 1.0), ] time = ngl.AnimatedFloat(animkf) duration = ngl.UniformFloat(cfg.duration) group_size = nb_particules / local_size program = ngl.ComputeProgram(compute_shader) compute = ngl.Compute(nb_particules, 1, 1, program) compute.update_uniforms(time=time, duration=duration) compute.update_blocks(ipositions_buffer=ipositions, opositions_buffer=opositions) circle = ngl.Circle(radius=0.05) program = ngl.Program(vertex=vertex_shader, fragment=fragment_shader) render = ngl.Render(circle, program, nb_instances=nb_particules) render.update_uniforms(color=ngl.UniformVec4(value=COLORS['sgreen'])) render.update_blocks(positions_buffer=opositions) group = ngl.Group() group.add_children(compute, render) return group
def compute_particles(cfg): cfg.duration = 10 workgroups = (2, 1, 4) local_size = (4, 4, 1) nb_particles = workgroups[0] * workgroups[1] * workgroups[2] * local_size[ 0] * local_size[1] * local_size[2] positions = array.array("f") velocities = array.array("f") for i in range(nb_particles): positions.extend([ cfg.rng.uniform(-2.0, 1.0), cfg.rng.uniform(-1.0, 1.0), 0.0, ]) velocities.extend([ cfg.rng.uniform(1.0, 2.0), cfg.rng.uniform(0.5, 1.5), ]) ipositions = ngl.Block( fields=[ ngl.BufferVec3(data=positions, label="positions"), ngl.BufferVec2(data=velocities, label="velocities"), ], layout="std430", ) opositions = ngl.Block( fields=[ngl.BufferVec3(count=nb_particles, label="positions")], layout="std140") animkf = [ ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration, 1.0), ] time = ngl.AnimatedFloat(animkf) duration = ngl.UniformFloat(cfg.duration) program = ngl.ComputeProgram(_PARTICULES_COMPUTE, workgroup_size=local_size) program.update_properties(odata=ngl.ResourceProps(writable=True)) compute = ngl.Compute(workgroups, program) compute.update_resources(time=time, duration=duration, idata=ipositions, odata=opositions) circle = ngl.Circle(radius=0.05) program = ngl.Program(vertex=_PARTICULES_VERT, fragment=cfg.get_frag("color")) render = ngl.Render(circle, program, nb_instances=nb_particles) render.update_frag_resources(color=ngl.UniformVec3(value=COLORS.sgreen), opacity=ngl.UniformFloat(1)) render.update_vert_resources(data=opositions) group = ngl.Group() group.add_children(compute, render) return group
def compute_particules(cfg): random.seed(0) cfg.duration = 10 local_size = 4 nb_particules = 128 positions = array.array('f') velocities = array.array('f') for i in range(nb_particules): positions.extend([ random.uniform(-2.0, 1.0), random.uniform(-1.0, 1.0), 0.0, ]) velocities.extend([ random.uniform(1.0, 2.0), random.uniform(0.5, 1.5), ]) ipositions = ngl.Block( fields=[ ngl.BufferVec3(data=positions, label='positions'), ngl.BufferVec2(data=velocities, label='velocities'), ], layout='std430', ) opositions = ngl.Block( fields=[ngl.BufferVec3(count=nb_particules, label='positions')], layout='std430') animkf = [ ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration, 1.0), ] time = ngl.AnimatedFloat(animkf) duration = ngl.UniformFloat(cfg.duration) group_size = nb_particules / local_size program = ngl.ComputeProgram(_PARTICULES_COMPUTE % dict(local_size=local_size)) compute = ngl.Compute(nb_particules, 1, 1, program) compute.update_resources(time=time, duration=duration, idata=ipositions, odata=opositions) circle = ngl.Circle(radius=0.05) program = ngl.Program(vertex=_PARTICULES_VERT, fragment=cfg.get_frag('color')) render = ngl.Render(circle, program, nb_instances=nb_particules) render.update_frag_resources(color=ngl.UniformVec4(value=COLORS['sgreen'])) render.update_vert_resources(data=opositions) group = ngl.Group() group.add_children(compute, render) return group
def stl(cfg, stl=None, scale=0.8): """Load and display a sphere generated with OpenSCAD""" if stl is None: # generated with: echo 'sphere($fn=15);'>sphere.scad; openscad sphere.scad -o sphere.stl stl = op.join(op.dirname(__file__), "data", "sphere.stl") normals_data = array.array("f") vertices_data = array.array("f") solid_label = None normal = None with open(stl) as fp: for line in fp.readlines(): line = line.strip() if line.startswith("solid"): solid_label = line.split(None, 1)[1] elif line.startswith("facet normal"): _, _, normal = line.split(None, 2) normal = [float(f) for f in normal.split()] elif normal and line.startswith("vertex"): _, vertex = line.split(None, 1) vertex = [float(f) for f in vertex.split()] normals_data.extend(normal) vertices_data.extend(vertex) vertices = ngl.BufferVec3(data=vertices_data) normals = ngl.BufferVec3(data=normals_data) g = ngl.Geometry(vertices=vertices, normals=normals) p = ngl.Program(vertex=cfg.get_vert("colored-normals"), fragment=cfg.get_frag("colored-normals")) p.update_vert_out_vars(var_normal=ngl.IOVec3(), var_uvcoord=ngl.IOVec2(), var_tex0_coord=ngl.IOVec2()) solid = ngl.Render(g, p, label=solid_label) solid = ngl.GraphicConfig(solid, depth_test=True) solid = ngl.Scale(solid, [scale] * 3) for i in range(3): rot_animkf = ngl.AnimatedFloat([ ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration, 360 * (i + 1)) ]) axis = [int(i == x) for x in range(3)] solid = ngl.Rotate(solid, axis=axis, angle=rot_animkf) camera = ngl.Camera(solid) camera.set_eye(2.0, 2.0, 2.0) camera.set_center(0.0, 0.0, 0.0) camera.set_up(0.0, 1.0, 0.0) camera.set_perspective(45.0, cfg.aspect_ratio_float) camera.set_clipping(1.0, 10.0) return camera
def compute_animation(cfg): cfg.duration = 5 cfg.aspect_ratio = (1, 1) local_size = 2 vertices_data = array.array('f', [ -0.5, -0.5, 0.0, 0.5, -0.5, 0.0, -0.5, 0.5, 0.0, 0.5, 0.5, 0.0, ]) nb_vertices = 4 input_vertices = ngl.BufferVec3(data=vertices_data, label='vertices') output_vertices = ngl.BufferVec3(data=vertices_data, label='vertices') input_block = ngl.Block(fields=[input_vertices], layout='std140') output_block = ngl.Block(fields=[output_vertices], layout='std140') rotate_animkf = [ ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration, 360) ] rotate = ngl.Rotate(ngl.Identity(), axis=(0, 0, 1), anim=ngl.AnimatedFloat(rotate_animkf)) transform = ngl.UniformMat4(transform=rotate) program = ngl.ComputeProgram(_ANIMATION_COMPUTE, workgroup_size=(local_size, local_size, 1)) program.update_properties(dst=ngl.ResourceProps(writable=True)) compute = ngl.Compute(workgroup_count=(nb_vertices / (local_size**2), 1, 1), program=program) compute.update_resources(transform=transform, src=input_block, dst=output_block) quad_buffer = ngl.BufferVec3(block=output_block, block_field=0) geometry = ngl.Geometry(quad_buffer, topology='triangle_strip') program = ngl.Program(vertex=cfg.get_vert('color'), fragment=cfg.get_frag('color')) render = ngl.Render(geometry, program) render.update_frag_resources(color=ngl.UniformVec4(value=COLORS['sgreen'])) return ngl.Group(children=(compute, render))
def _get_cube(): # front p0 = (-1, -1, 1) p1 = ( 1, -1, 1) p2 = ( 1, 1, 1) p3 = (-1, 1, 1) # back p4 = (-1, -1, -1) p5 = ( 1, -1, -1) p6 = ( 1, 1, -1) p7 = (-1, 1, -1) cube_vertices_data = array.array( 'f', p0 + p1 + p2 + p2 + p3 + p0 + # front p1 + p5 + p6 + p6 + p2 + p1 + # right p7 + p6 + p5 + p5 + p4 + p7 + # back p4 + p0 + p3 + p3 + p7 + p4 + # left p4 + p5 + p1 + p1 + p0 + p4 + # bottom p3 + p2 + p6 + p6 + p7 + p3 # top ) uvs = (0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1) cube_uvs_data = array.array('f', uvs * 6) up = (0, 1, 0) down = (0, -1, 0) front = (0, 0, 1) back = (0, 0, -1) left = (-1, 0, 0) right = (1, 0, 0) cube_normals_data = array.array( 'f', front * 6 + right * 6 + back * 6 + left * 6 + down * 6 + up * 6 ) return ngl.Geometry( vertices=ngl.BufferVec3(data=cube_vertices_data), uvcoords=ngl.BufferVec2(data=cube_uvs_data), normals=ngl.BufferVec3(data=cube_normals_data), )
def catmull(cfg, tension=0.5): cfg.duration = 3 # fmt: off points = ( (-0.62, -0.30, 0.0), (-0.36, 0.40, 0.0), (0.04, -0.27, 0.0), (0.36, 0.28, 0.0), (0.65, -0.04, 0.0), ) controls = ( (-0.84, 0.07, 0.0), (0.84, 0.04, 0.0), ) # fmt: on flat_points = (elt for iterable in points for elt in iterable) points_array = array.array("f", flat_points) path = ngl.SmoothPath( ngl.BufferVec3(data=points_array), control1=controls[0], control2=controls[1], tension=tension, ) return _path_scene(cfg, path, points, controls, easing="exp_in_out")
def triangle(cfg, size=4 / 3): """Rotating triangle with edge coloring specified in a vertex attribute""" cfg.duration = 3.0 cfg.aspect_ratio = (1, 1) colors_data = array.array("f", [0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0]) colors_buffer = ngl.BufferVec3(data=colors_data) p0, p1, p2 = equilateral_triangle_coords(size) triangle = ngl.Triangle(p0, p1, p2) p = ngl.Program(fragment=cfg.get_frag("color"), vertex=cfg.get_vert("triangle")) p.update_vert_out_vars(color=ngl.IOVec3()) node = ngl.Render(triangle, p) node.update_attributes(edge_color=colors_buffer) node.update_frag_resources(opacity=ngl.UniformFloat(1)) animkf = [ ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration / 3.0, -360 / 3.0, "exp_in_out"), ngl.AnimKeyFrameFloat(2 * cfg.duration / 3.0, -2 * 360 / 3.0, "exp_in_out"), ngl.AnimKeyFrameFloat(cfg.duration, -360, "exp_in_out"), ] node = ngl.Rotate(node, angle=ngl.AnimatedFloat(animkf)) return node
def transform_smoothpath(cfg): cfg.aspect_ratio = (1, 1) cfg.duration = 3 shape = _transform_shape(cfg, w=0.3, h=0.3) # fmt: off points = ( (-0.62, -0.30, 0.0), (-0.36, 0.40, 0.0), (0.04, -0.27, 0.0), (0.36, 0.28, 0.0), (0.65, -0.04, 0.0), ) controls = ( (-0.84, 0.07, 0.0), (0.84, 0.04, 0.0), ) # fmt: on flat_points = (elt for point in points for elt in point) points_array = array.array("f", flat_points) path = ngl.SmoothPath( ngl.BufferVec3(data=points_array), control1=controls[0], control2=controls[1], tension=0.4, ) anim_kf = [ ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration, 1, "exp_in_out"), ] return ngl.Translate(shape, vector=ngl.AnimatedPath(anim_kf, path))
def compute_animation(cfg): cfg.duration = 5 cfg.aspect_ratio = (1, 1) local_size = 2 shader_version = '310 es' if cfg.backend == 'gles' else '430' shader_data = dict( version=shader_version, local_size=local_size, ) compute_shader = _ANIMATION_COMPUTE % shader_data vertex_shader = _ANIMATION_VERT % shader_data fragment_shader = _ANIMATION_FRAG % shader_data vertices_data = array.array('f', [ -0.5, -0.5, 0.0, 0.5, -0.5, 0.0, 0.5, 0.5, 0.0, -0.5, 0.5, 0.0, ]) nb_vertices = 4 input_vertices = ngl.BufferVec3(data=vertices_data) output_vertices = ngl.BufferVec3(data=vertices_data) input_block = ngl.Block(fields=[input_vertices], layout='std140') output_block = ngl.Block(fields=[output_vertices], layout='std430') rotate_animkf = [ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration, 360)] rotate = ngl.Rotate(ngl.Identity(), axis=(0, 0, 1), anim=ngl.AnimatedFloat(rotate_animkf)) transform = ngl.UniformMat4(transform=rotate) program = ngl.ComputeProgram(compute_shader) compute = ngl.Compute(nb_vertices / (local_size ** 2), 1, 1, program) compute.update_uniforms(transform=transform) compute.update_blocks(input_block=input_block, output_block=output_block) quad_buffer = ngl.BufferVec3(block=output_block, block_field=0) geometry = ngl.Geometry(quad_buffer, topology='triangle_fan') program = ngl.Program(vertex=vertex_shader, fragment=fragment_shader) render = ngl.Render(geometry, program) render.update_uniforms(color=ngl.UniformVec4(value=COLORS['sgreen'])) return ngl.Group(children=(compute, render))
def obj(cfg, n=0.5, model=None): """Load and display a cube object (generated with Blender)""" if model is None: model = op.join(op.dirname(__file__), "data", "model.obj") with open(model) as fp: vertices_data, uvs_data, normals_data = _load_model(fp) vertices = ngl.BufferVec3(data=vertices_data) texcoords = ngl.BufferVec2(data=uvs_data) normals = ngl.BufferVec3(data=normals_data) q = ngl.Geometry(vertices, texcoords, normals) m = ngl.Media(cfg.medias[0].filename) t = ngl.Texture2D(data_src=m) p = ngl.Program(vertex=cfg.get_vert("tex-tint-normals"), fragment=cfg.get_frag("tex-tint-normals")) p.update_vert_out_vars(var_normal=ngl.IOVec3(), var_uvcoord=ngl.IOVec2(), var_tex0_coord=ngl.IOVec2()) render = ngl.Render(q, p) render.update_frag_resources(tex0=t) render = ngl.GraphicConfig(render, depth_test=True) animkf = [ ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration, 360 * 2) ] rot = ngl.Rotate(render, label="roty", axis=(0, 1, 0), angle=ngl.AnimatedFloat(animkf)) camera = ngl.Camera(rot) camera.set_eye(2.0, 2.0, 2.0) camera.set_center(0.0, 0.0, 0.0) camera.set_up(0.0, 1.0, 0.0) camera.set_perspective(45.0, cfg.aspect_ratio_float) camera.set_clipping(1.0, 10.0) return camera
def _shape_geometry(cfg, set_normals=False, set_indices=False): # Fake cube (3 faces only) obtained from: # echo 'cube();'>x.scad; openscad x.scad -o x.stl vertices = array.array('f', [x - 0.5 for x in [ 1,1,0, 0,1,1, 1,1,1, 0,1,1, 1,1,0, 0,1,0, 0,0,0, 0,1,1, 0,1,0, 0,1,1, 0,0,0, 0,0,1, 0,1,1, 1,0,1, 1,1,1, 1,0,1, 0,1,1, 0,0,1, ]]) normals = array.array('f', [ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, -1,0,0, -1,0,0, -1,0,0, -1,0,0, -1,0,0, -1,0,0, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, ]) vertices_buffer = ngl.BufferVec3(data=vertices) normals_buffer = ngl.BufferVec3(data=normals) cfg.aspect_ratio = (1, 1) geometry = ngl.Geometry(vertices=vertices_buffer) if set_normals: geometry.set_normals(normals_buffer) prog = ngl.Program(vertex=cfg.get_vert('colored-normals'), fragment=cfg.get_frag('colored-normals')) prog.update_vert_out_vars(var_normal=ngl.IOVec3()) render = ngl.Render(geometry, prog) else: render = _render_shape(cfg, geometry, COLORS['magenta']) if set_indices: indices = array.array('H', list(range(3 * 6))) indices_buffer = ngl.BufferUShort(data=indices) geometry.set_indices(indices_buffer) return ngl.Rotate(render, 45, axis=(1, 1, 1))
def ret_func(cfg, nb_points=100, zoom=1, offset_start=0, offset_end=1, draw_in=True, draw_out=True, draw_in_out=True, draw_out_in=True): g = ngl.Group() cfg.aspect_ratio = (1, 1) frag_data = cfg.get_frag('color') program = ngl.Program(fragment=frag_data) for idx, ext in enumerate(versions): interp = name if ext is not None: interp += '_' + ext if not eval('draw_' + ext): continue anim = ngl.AnimatedFloat([ ngl.AnimKeyFrameFloat(-1, -1), ngl.AnimKeyFrameFloat(1, 1, interp, easing_start_offset=offset_start, easing_end_offset=offset_end) ]) vertices_data = array.array('f') for i in range(nb_points + 1): x = (i / float(nb_points) * 2 - 1) y = anim.evaluate(x * 1 / zoom) * zoom vertices_data.extend([x, y, 0]) vertices = ngl.BufferVec3(data=vertices_data) geometry = ngl.Geometry(vertices, topology='line_strip') render = ngl.Render(geometry, program) render.update_uniforms(color=ngl.UniformVec4(_colors[idx])) g.add_children(render) return g
def shape_geometry_with_renderother(cfg): cfg.aspect_ratio = (1, 1) vertices_data = array.array("f") uvcoords_data = array.array("f") boundaries = ( (-1, 0, 0, 1), (0, 1, 0, 1), (-1, 0, -1, 0), (0, 1, -1, 0), ) for xmin, xmax, ymin, ymax in boundaries: x0, y0 = cfg.rng.uniform(xmin, xmax), cfg.rng.uniform(ymin, ymax) x1, y1 = cfg.rng.uniform(xmin, xmax), cfg.rng.uniform(ymin, ymax) vertices_data.extend((0, 0, 0, x0, y0, 0, x1, y1, 0)) uvcoords_data.extend((0, 0, x0, y0, x1, y1)) geometry = ngl.Geometry( vertices=ngl.BufferVec3(data=vertices_data), uvcoords=ngl.BufferVec2(data=uvcoords_data), topology="triangle_list", ) return ngl.RenderColor(geometry=geometry)
def _shape_geometry(cfg, set_normals=False, set_indices=False): # Fake cube (3 faces only) obtained from: # echo 'cube();'>x.scad; openscad x.scad -o x.stl vertices = array.array( "f", [ x - 0.5 for x in [ # fmt: off 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, # fmt: on ] ], ) normals = array.array( "f", [ # fmt: off 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, # fmt: on ], ) vertices_buffer = ngl.BufferVec3(data=vertices) normals_buffer = ngl.BufferVec3(data=normals) cfg.aspect_ratio = (1, 1) geometry = ngl.Geometry(vertices=vertices_buffer) if set_normals: geometry.set_normals(normals_buffer) prog = ngl.Program(vertex=cfg.get_vert("colored-normals"), fragment=cfg.get_frag("colored-normals")) prog.update_vert_out_vars(var_normal=ngl.IOVec3()) render = ngl.Render(geometry, prog) else: prog = ngl.Program(vertex=cfg.get_vert("color"), fragment=cfg.get_frag("color")) render = ngl.Render(geometry, prog) render.update_frag_resources( color=ngl.UniformVec3(value=COLORS.magenta), opacity=ngl.UniformFloat(1)) if set_indices: indices = array.array("H", list(range(3 * 6))) indices_buffer = ngl.BufferUShort(data=indices) geometry.set_indices(indices_buffer) return ngl.Rotate(render, 45, axis=(1, 1, 1))
def cropboard(cfg, dim_clr=3, dim_cut=9): cfg.duration = 5. + 1. random.seed(0) get_rand = lambda: array.array( 'f', [random.random() for i in range(dim_clr**2 * 3)]) nb_kf = 2 buffers = [get_rand() for i in range(nb_kf)] random_animkf = [] time_scale = cfg.duration / float(nb_kf) for i, buf in enumerate(buffers + [buffers[0]]): random_animkf.append(ngl.AnimKeyFrameBuffer(i * time_scale, buf)) random_buffer = ngl.AnimatedBufferVec3(keyframes=random_animkf) random_tex = ngl.Texture2D(data_src=random_buffer, width=dim_clr, height=dim_clr) kw = kh = 1. / dim_cut qw = qh = 2. / dim_cut p = ngl.Program(vertex=cfg.get_vert('cropboard'), fragment=cfg.get_frag('texture')) uv_offset_buffer = array.array('f') translate_a_buffer = array.array('f') translate_b_buffer = array.array('f') if set_indices: indices = array.array('H', [0, 2, 1, 3]) indices_buffer = ngl.BufferUShort(data=indices) vertices = array.array('f', [ 0, 0, 0, qw, qh, 0, qw, 0, 0, 0, qh, 0, ]) uvcoords = array.array('f', [ 0, 1.0, kw, 1.0 - kh, kw, 1.0, 0, 1.0 - kh, ]) vertices_buffer = ngl.BufferVec3(data=vertices) uvcoords_buffer = ngl.BufferVec2(data=uvcoords) q = ngl.Geometry(topology='triangle_fan', vertices=vertices_buffer, uvcoords=uvcoords_buffer, indices=indices_buffer) else: q = ngl.Quad(corner=(0, 0, 0), width=(qw, 0, 0), height=(0, qh, 0), uv_corner=(0, 0), uv_width=(kw, 0), uv_height=(0, kh)) for y in range(dim_cut): for x in range(dim_cut): uv_offset = [x * kw, (y + 1.) * kh - 1.] src = [random.uniform(-2, 2), random.uniform(-2, 2)] dst = [x * qw - 1., 1. - (y + 1.) * qh] uv_offset_buffer.extend(uv_offset) translate_a_buffer.extend(src) translate_b_buffer.extend(dst) utime_animkf = [ ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration - 1., 1) ] utime = ngl.AnimatedFloat(utime_animkf) render = ngl.Render(q, p, nb_instances=dim_cut**2) render.update_textures(tex0=random_tex) render.update_uniforms(time=utime) render.update_instance_attributes( uv_offset=ngl.BufferVec2(data=uv_offset_buffer), translate_a=ngl.BufferVec2(data=translate_a_buffer), translate_b=ngl.BufferVec2(data=translate_b_buffer), ) return render
def particles(cfg, particles=32): """Particules demo using compute shaders and instancing""" compute_shader = cfg.get_comp("particles") vertex_shader = cfg.get_vert("particles") fragment_shader = cfg.get_frag("color") cfg.duration = 6 x = 64 p = x * particles positions = array.array("f") velocities = array.array("f") for i in range(p): positions.extend([ cfg.rng.uniform(-1.0, 1.0), cfg.rng.uniform(0.0, 1.0), 0.0, ]) velocities.extend([ cfg.rng.uniform(-0.01, 0.01), cfg.rng.uniform(-0.05, 0.05), ]) ipositions = ngl.Block( fields=[ngl.BufferVec3(data=positions, label="data")], layout="std430") ivelocities = ngl.Block( fields=[ngl.BufferVec2(data=velocities, label="data")], layout="std430") opositions = ngl.Block(fields=[ngl.BufferVec3(count=p, label="data")], layout="std430") animkf = [ ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration, 1) ] utime = ngl.AnimatedFloat(animkf) uduration = ngl.UniformFloat(cfg.duration) cp = ngl.ComputeProgram(compute_shader, workgroup_size=(1, 1, 1)) cp.update_properties(opositions=ngl.ResourceProps(writable=True)) c = ngl.Compute(workgroup_count=(x, particles, 1), program=cp) c.update_resources( time=utime, duration=uduration, ipositions=ipositions, ivelocities=ivelocities, opositions=opositions, ) quad_width = 0.01 quad = ngl.Quad(corner=(-quad_width / 2, -quad_width / 2, 0), width=(quad_width, 0, 0), height=(0, quad_width, 0)) p = ngl.Program( vertex=vertex_shader, fragment=fragment_shader, ) p.update_vert_out_vars(var_uvcoord=ngl.IOVec2(), var_tex0_coord=ngl.IOVec2()) r = ngl.Render(quad, p, nb_instances=particles, blending="src_over") r.update_frag_resources(color=ngl.UniformVec3(value=(0, 0.6, 0.8)), opacity=ngl.UniformFloat(0.9)) r.update_vert_resources(positions=opositions) g = ngl.Group() g.add_children(c, r) return ngl.Camera(g)
def particles(cfg, particles=32): '''Particules demo using compute shaders and instancing''' random.seed(0) compute_shader = cfg.get_comp('particles') vertex_shader = cfg.get_vert('particles') fragment_shader = cfg.get_frag('color') cfg.duration = 6 x = 64 p = x * particles positions = array.array('f') velocities = array.array('f') for i in range(p): positions.extend([ random.uniform(-1.0, 1.0), random.uniform(0.0, 1.0), 0.0, ]) velocities.extend([ random.uniform(-0.01, 0.01), random.uniform(-0.05, 0.05), ]) ipositions = ngl.Block(fields=[ngl.BufferVec3(data=positions, label='data')], layout='std430') ivelocities = ngl.Block(fields=[ngl.BufferVec2(data=velocities, label='data')], layout='std430') opositions = ngl.Block(fields=[ngl.BufferVec3(count=p, label='data')], layout='std430') animkf = [ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration, 1)] utime = ngl.AnimatedFloat(animkf) uduration = ngl.UniformFloat(cfg.duration) cp = ngl.ComputeProgram(compute_shader, workgroup_size=(1, 1, 1)) cp.update_properties(opositions=ngl.ResourceProps(writable=True)) c = ngl.Compute(workgroup_count=(x, particles, 1), program=cp) c.update_resources( time=utime, duration=uduration, ipositions=ipositions, ivelocities=ivelocities, opositions=opositions, ) quad_width = 0.01 quad = ngl.Quad( corner=(-quad_width/2, -quad_width/2, 0), width=(quad_width, 0, 0), height=(0, quad_width, 0) ) p = ngl.Program( vertex=vertex_shader, fragment=fragment_shader, ) p.update_vert_out_vars(var_uvcoord=ngl.IOVec2(), var_tex0_coord=ngl.IOVec2()) r = ngl.Render(quad, p, nb_instances=particles) r.update_frag_resources(color=ngl.UniformVec4(value=(0, .6, .8, .9))) r.update_vert_resources(positions=opositions) r = ngl.GraphicConfig(r, blend=True, blend_src_factor='src_alpha', blend_dst_factor='one_minus_src_alpha', blend_src_factor_a='zero', blend_dst_factor_a='one') g = ngl.Group() g.add_children(c, r) return ngl.Camera(g)
def _get_easing_node(cfg, easing, curve_zoom, color_program, nb_points=128): text_vratio = 1 / 8. graph_hpad_ratio = 1 / 16. area_size = 2.0 width, height = area_size, area_size text_height = text_vratio * height pad_height = graph_hpad_ratio * height # Colors hue = random.uniform(0, 0.6) color = list(colorsys.hls_to_rgb(hue, 0.6, 1.0)) + [1] ucolor = ngl.UniformVec4(value=color) graph_bg_ucolor = ngl.UniformVec4(value=(.15, .15, .15, 1)) normed_graph_bg_ucolor = ngl.UniformVec4(value=(0, 0, 0, 1)) line_ucolor = ngl.UniformVec4(value=(1, 1, 1, .4)) # Text legend text = ngl.Text(text=easing, fg_color=color, padding=3, bg_color=(0, 0, 0, 1), box_corner=(-width / 2., height / 2. - text_height, 0), box_width=(width, 0, 0), box_height=(0, text_height, 0), label='%s legend' % easing) # Graph drawing area (where the curve may overflow) graph_size = area_size - text_height - pad_height * 2 graph_block = _block(graph_size, graph_size, color_program, corner=(-graph_size / 2, -(graph_size + text_height) / 2, 0), color=graph_bg_ucolor) # Normed area of the graph normed_graph_size = graph_size * curve_zoom normed_graph_block = _block(normed_graph_size, normed_graph_size, color_program, corner=(-normed_graph_size / 2, -(normed_graph_size + text_height) / 2, 0), color=normed_graph_bg_ucolor) # Curve easing_name, easing_args = _easing_split(easing) curve_scale_factor = graph_size / area_size * curve_zoom vertices_data = array.array('f') for i in range(nb_points + 1): t = i / float(nb_points) v = ngl.easing_evaluate(easing_name, t, easing_args) x = curve_scale_factor * (t * width - width / 2.) y = curve_scale_factor * (v * height - height / 2.) y -= text_height / 2. vertices_data.extend([x, y, 0]) vertices = ngl.BufferVec3(data=vertices_data) geometry = ngl.Geometry(vertices, topology='line_strip') curve = ngl.Render(geometry, color_program, label='%s curve' % easing) curve.update_uniforms(color=ucolor) # Value cursor y = 2 / 3. * pad_height x = y * math.sqrt(3) cursor_geometry = ngl.Triangle((-x, y, 0), (0, 0, 0), (-x, -y, 0)) cursor = ngl.Render(cursor_geometry, color_program, label='%s cursor' % easing) cursor.update_uniforms(color=ucolor) # Horizontal value line hline_data = array.array('f', (0, 0, 0, graph_size, 0, 0)) hline_vertices = ngl.BufferVec3(data=hline_data) hline_geometry = ngl.Geometry(hline_vertices, topology='line_strip') hline = ngl.Render(hline_geometry, color_program, label='%s value line' % easing) hline.update_uniforms(color=line_ucolor) # Value animation (cursor + h-line) value_x = -graph_size / 2. value_y = (-text_height - normed_graph_size) / 2. value_animkf = ( ngl.AnimKeyFrameVec3(0, (value_x, value_y, 0)), ngl.AnimKeyFrameVec3(cfg.duration, (value_x, value_y + normed_graph_size, 0), easing_name, easing_args), ) value_anim = ngl.Group(children=(hline, cursor)) value_anim = ngl.Translate(value_anim, anim=ngl.AnimatedVec3(value_animkf), label='%s value anim' % easing) # Vertical time line vline_data = array.array('f', (0, 0, 0, 0, graph_size, 0)) vline_vertices = ngl.BufferVec3(data=vline_data) vline_geometry = ngl.Geometry(vline_vertices, topology='line_strip') vline = ngl.Render(vline_geometry, color_program, label='%s time line' % easing) vline.update_uniforms(color=line_ucolor) # Time animation (v-line only) time_x = -normed_graph_size / 2. time_y = (-text_height - graph_size) / 2. time_animkf = (ngl.AnimKeyFrameVec3(0, (time_x, time_y, 0)), ngl.AnimKeyFrameVec3( cfg.duration, (time_x + normed_graph_size, time_y, 0))) time_anim = ngl.Translate(vline, anim=ngl.AnimatedVec3(time_animkf), label='%s time anim' % easing) group = ngl.Group(label='%s block' % easing) group.add_children(text, graph_block, normed_graph_block, curve, value_anim, time_anim) return group
animated_buffer_vec3=lambda data: ngl.AnimatedBufferVec3( keyframes=_get_anim_kf(ngl.AnimKeyFrameBuffer, data)), animated_buffer_vec4=lambda data: ngl.AnimatedBufferVec4( keyframes=_get_anim_kf(ngl.AnimKeyFrameBuffer, data)), animated_quat_mat4=lambda data: ngl.AnimatedQuat( keyframes=_get_anim_kf(ngl.AnimKeyFrameQuat, data), as_mat4=True), animated_quat_vec4=lambda data: ngl.AnimatedQuat( keyframes=_get_anim_kf(ngl.AnimKeyFrameQuat, data), as_mat4=False), array_float=lambda data: ngl.BufferFloat(data=data), array_int=lambda data: ngl.BufferInt(data=data), array_ivec2=lambda data: ngl.BufferIVec2(data=data), array_ivec3=lambda data: ngl.BufferIVec3(data=data), array_ivec4=lambda data: ngl.BufferIVec4(data=data), array_mat4=lambda data: ngl.BufferMat4(data=data), array_vec2=lambda data: ngl.BufferVec2(data=data), array_vec3=lambda data: ngl.BufferVec3(data=data), array_vec4=lambda data: ngl.BufferVec4(data=data), single_bool=lambda data: ngl.UniformBool(data), single_float=lambda data: ngl.UniformFloat(data), single_int=lambda data: ngl.UniformInt(data), single_ivec2=lambda data: ngl.UniformIVec2(data), single_ivec3=lambda data: ngl.UniformIVec3(data), single_ivec4=lambda data: ngl.UniformIVec4(data), single_uint=lambda data: ngl.UniformUInt(data), single_uvec2=lambda data: ngl.UniformUIVec2(data), single_uvec3=lambda data: ngl.UniformUIVec3(data), single_uvec4=lambda data: ngl.UniformUIVec4(data), single_mat4=lambda data: ngl.UniformMat4(data), single_quat_mat4=lambda data: ngl.UniformQuat(data, as_mat4=True), single_quat_vec4=lambda data: ngl.UniformQuat(data, as_mat4=False), single_vec2=lambda data: ngl.UniformVec2(data),
def cropboard(cfg, dim_clr=3, dim_cut=9): cfg.duration = 5.0 + 1.0 nb_kf = 2 buffers = [ get_random_color_buffer(cfg.rng, dim_clr) for _ in range(nb_kf) ] random_animkf = [] time_scale = cfg.duration / float(nb_kf) for i, buf in enumerate(buffers + [buffers[0]]): random_animkf.append(ngl.AnimKeyFrameBuffer(i * time_scale, buf)) random_buffer = ngl.AnimatedBufferVec4(keyframes=random_animkf) random_tex = ngl.Texture2D(data_src=random_buffer, width=dim_clr, height=dim_clr) kw = kh = 1.0 / dim_cut qw = qh = 2.0 / dim_cut p = ngl.Program(vertex=cfg.get_vert("cropboard"), fragment=cfg.get_frag("texture")) p.update_vert_out_vars(var_tex0_coord=ngl.IOVec2()) uv_offset_buffer = array.array("f") translate_a_buffer = array.array("f") translate_b_buffer = array.array("f") if set_indices: indices = array.array("H", [0, 2, 1, 1, 3, 0]) indices_buffer = ngl.BufferUShort(data=indices) vertices = array.array( "f", [ # fmt: off 0, 0, 0, qw, qh, 0, qw, 0, 0, 0, qh, 0, # fmt: on ], ) uvcoords = array.array( "f", [ # fmt: off 0, 1.0, kw, 1.0 - kh, kw, 1.0, 0, 1.0 - kh, # fmt: on ], ) vertices_buffer = ngl.BufferVec3(data=vertices) uvcoords_buffer = ngl.BufferVec2(data=uvcoords) q = ngl.Geometry(vertices=vertices_buffer, uvcoords=uvcoords_buffer, indices=indices_buffer) else: q = ngl.Quad( corner=(0, 0, 0), width=(qw, 0, 0), height=(0, qh, 0), uv_corner=(0, 0), uv_width=(kw, 0), uv_height=(0, kh), ) for y in range(dim_cut): for x in range(dim_cut): uv_offset = [x * kw, (y + 1.0) * kh - 1.0] src = [cfg.rng.uniform(-2, 2), cfg.rng.uniform(-2, 2)] dst = [x * qw - 1.0, 1.0 - (y + 1.0) * qh] uv_offset_buffer.extend(uv_offset) translate_a_buffer.extend(src) translate_b_buffer.extend(dst) utime_animkf = [ ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration - 1.0, 1) ] utime = ngl.AnimatedFloat(utime_animkf) render = ngl.Render(q, p, nb_instances=dim_cut**2) render.update_frag_resources(tex0=random_tex) render.update_vert_resources(time=utime) render.update_instance_attributes( uv_offset=ngl.BufferVec2(data=uv_offset_buffer), translate_a=ngl.BufferVec2(data=translate_a_buffer), translate_b=ngl.BufferVec2(data=translate_b_buffer), ) return render
def particules(cfg, particules=32): '''Particules demo using compute shaders and instancing''' random.seed(0) shader_version = '310 es' if cfg.backend == 'gles' else '430' shader_header = '#version %s\n' % shader_version compute_shader = shader_header + cfg.get_comp('particules') vertex_shader = shader_header + cfg.get_vert('particules') fragment_shader = shader_header + cfg.get_frag('particules') cfg.duration = 6 x = 64 p = x * particules positions = array.array('f') velocities = array.array('f') for i in range(p): positions.extend([ random.uniform(-1.0, 1.0), random.uniform(0.0, 1.0), 0.0, ]) velocities.extend([ random.uniform(-0.01, 0.01), random.uniform(-0.05, 0.05), ]) ipositions = ngl.Block(fields=[ngl.BufferVec3(data=positions)], layout='std430') ivelocities = ngl.Block(fields=[ngl.BufferVec2(data=velocities)], layout='std430') opositions = ngl.Block(fields=[ngl.BufferVec3(count=p)], layout='std430') animkf = [ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration, 1)] utime = ngl.AnimatedFloat(animkf) uduration = ngl.UniformFloat(cfg.duration) cp = ngl.ComputeProgram(compute_shader) c = ngl.Compute(x, particules, 1, cp) c.update_uniforms( time=utime, duration=uduration, ) c.update_blocks( ipositions_buffer=ipositions, ivelocities_buffer=ivelocities, opositions_buffer=opositions, ) quad_width = 0.01 quad = ngl.Quad( corner=(-quad_width/2, -quad_width/2, 0), width=(quad_width, 0, 0), height=(0, quad_width, 0) ) p = ngl.Program( vertex=vertex_shader, fragment=fragment_shader, ) r = ngl.Render(quad, p, nb_instances=particules) r.update_uniforms(color=ngl.UniformVec4(value=(0, .6, .8, .9))) r.update_blocks(positions_buffer=opositions) r = ngl.GraphicConfig(r, blend=True, blend_src_factor='src_alpha', blend_dst_factor='one_minus_src_alpha', blend_src_factor_a='zero', blend_dst_factor_a='one') g = ngl.Group() g.add_children(c, r) return ngl.Camera(g)